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") @GuardedBy("mLock")
final SparseBooleanArray mActiveUids = new SparseBooleanArray(); 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. * 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. * 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) { 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. * 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); mExemptedBucketPackages.remove(userId, pkgName);
mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName)); mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName));
mActiveUids.delete(uid); mActiveUids.delete(uid);
mForegroundUids.delete(uid);
} }
break; break;
} }
@@ -496,8 +476,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
mIActivityManager.registerUidObserver(new UidObserver(), mIActivityManager.registerUidObserver(new UidObserver(),
ActivityManager.UID_OBSERVER_GONE ActivityManager.UID_OBSERVER_GONE
| ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_IDLE
| ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_ACTIVE,
| ActivityManager.UID_OBSERVER_PROCSTATE,
ActivityManager.PROCESS_STATE_UNKNOWN, null); ActivityManager.PROCESS_STATE_UNKNOWN, null);
mAppOpsService.startWatchingMode(TARGET_OP, null, mAppOpsService.startWatchingMode(TARGET_OP, null,
new AppOpsWatcher()); new AppOpsWatcher());
@@ -698,7 +677,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
private final class UidObserver extends IUidObserver.Stub { private final class UidObserver extends IUidObserver.Stub {
@Override @Override
public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
mHandler.onUidStateChanged(uid, procState);
} }
@Override @Override
@@ -769,7 +747,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
private class MyHandler extends Handler { private class MyHandler extends Handler {
private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0; 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_RUN_ANY_CHANGED = 3;
private static final int MSG_ALL_UNEXEMPTED = 4; private static final int MSG_ALL_UNEXEMPTED = 4;
private static final int MSG_ALL_EXEMPTION_LIST_CHANGED = 5; 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_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
private static final int MSG_EXEMPTED_BUCKET_CHANGED = 10; 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_ACTIVE = 12;
private static final int MSG_ON_UID_GONE = 13; private static final int MSG_ON_UID_GONE = 13;
private static final int MSG_ON_UID_IDLE = 14; 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(); 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) { public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget(); 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(); 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) { public void onUidActive(int uid) {
obtainMessage(MSG_ON_UID_ACTIVE, uid, 0).sendToTarget(); 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); mStatLogger.logDurationStat(Stats.UID_ACTIVE_STATE_CHANGED, start);
return; 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: case MSG_RUN_ANY_CHANGED:
for (Listener l : cloneListeners()) { for (Listener l : cloneListeners()) {
l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj); l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
@@ -944,9 +905,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
handleUserRemoved(msg.arg1); handleUserRemoved(msg.arg1);
return; return;
case MSG_ON_UID_STATE_CHANGED:
handleUidStateChanged(msg.arg1, msg.arg2);
return;
case MSG_ON_UID_ACTIVE: case MSG_ON_UID_ACTIVE:
handleUidActive(msg.arg1); handleUidActive(msg.arg1);
return; 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) { public void handleUidActive(int uid) {
synchronized (mLock) { synchronized (mLock) {
if (addUidToArray(mActiveUids, uid)) { if (addUidToArray(mActiveUids, uid)) {
@@ -1007,9 +951,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
if (removeUidFromArray(mActiveUids, uid, remove)) { if (removeUidFromArray(mActiveUids, uid, remove)) {
mHandler.notifyUidActiveStateChanged(uid); mHandler.notifyUidActiveStateChanged(uid);
} }
if (removeUidFromArray(mForegroundUids, uid, remove)) {
mHandler.notifyUidForegroundStateChanged(uid);
}
} }
} }
} }
@@ -1026,7 +967,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
} }
} }
cleanUpArrayForUser(mActiveUids, removedUserId); cleanUpArrayForUser(mActiveUids, removedUserId);
cleanUpArrayForUser(mForegroundUids, removedUserId);
mExemptedBucketPackages.remove(removedUserId); mExemptedBucketPackages.remove(removedUserId);
} }
} }
@@ -1221,22 +1161,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
return ret; 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. * @return whether force all apps standby is enabled or not.
*/ */
@@ -1315,9 +1239,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
pw.print("Active uids: "); pw.print("Active uids: ");
dumpUids(pw, mActiveUids); dumpUids(pw, mActiveUids);
pw.print("Foreground uids: ");
dumpUids(pw, mForegroundUids);
pw.print("Except-idle + user exemption list appids: "); pw.print("Except-idle + user exemption list appids: ");
pw.println(Arrays.toString(mPowerExemptAllAppIds)); 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) { for (int appId : mPowerExemptAllAppIds) {
proto.write(AppStateTrackerProto.POWER_SAVE_EXEMPT_APP_IDS, appId); 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.SparseArray;
import android.util.SparseBooleanArray; import android.util.SparseBooleanArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.TimeUtils; import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream; 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_BG_LIMIT = localLOGV || false;
static final boolean DEBUG_STANDBY = localLOGV || false; static final boolean DEBUG_STANDBY = localLOGV || false;
static final boolean RECORD_ALARMS_IN_HISTORY = true; 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 String TIMEZONE_PROPERTY = "persist.sys.timezone";
static final int TICK_HISTORY_DEPTH = 10; static final int TICK_HISTORY_DEPTH = 10;
@@ -208,6 +208,7 @@ public class AlarmManagerService extends SystemService {
new ArrayList<>(); new ArrayList<>();
AlarmHandler mHandler; AlarmHandler mHandler;
AppWakeupHistory mAppWakeupHistory; AppWakeupHistory mAppWakeupHistory;
AppWakeupHistory mAllowWhileIdleHistory;
ClockReceiver mClockReceiver; ClockReceiver mClockReceiver;
final DeliveryTracker mDeliveryTracker = new DeliveryTracker(); final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
IBinder.DeathRecipient mListenerDeathRecipient; IBinder.DeathRecipient mListenerDeathRecipient;
@@ -230,19 +231,6 @@ public class AlarmManagerService extends SystemService {
*/ */
int mSystemUiUid; 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) { static boolean isTimeTickAlarm(Alarm a) {
return a.uid == Process.SYSTEM_UID && TIME_TICK_TAG.equals(a.listenerTag); return a.uid == Process.SYSTEM_UID && TIME_TICK_TAG.equals(a.listenerTag);
} }
@@ -290,9 +278,11 @@ public class AlarmManagerService extends SystemService {
private boolean mAppStandbyParole; 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 = private ArrayMap<Pair<String, Integer>, LongArrayQueue> mPackageHistory =
new ArrayMap<>(); new ArrayMap<>();
private long mWindowSize; private long mWindowSize;
@@ -353,7 +343,6 @@ public class AlarmManagerService extends SystemService {
} }
void dump(IndentingPrintWriter pw, long nowElapsed) { void dump(IndentingPrintWriter pw, long nowElapsed) {
pw.println("App Alarm history:");
pw.increaseIndent(); pw.increaseIndent();
for (int i = 0; i < mPackageHistory.size(); i++) { for (int i = 0; i < mPackageHistory.size(); i++) {
final Pair<String, Integer> packageUser = mPackageHistory.keyAt(i); final Pair<String, Integer> packageUser = mPackageHistory.keyAt(i);
@@ -389,10 +378,6 @@ public class AlarmManagerService extends SystemService {
@VisibleForTesting @VisibleForTesting
static final String KEY_MAX_INTERVAL = "max_interval"; static final String KEY_MAX_INTERVAL = "max_interval";
@VisibleForTesting @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 static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
= "allow_while_idle_whitelist_duration"; = "allow_while_idle_whitelist_duration";
@VisibleForTesting @VisibleForTesting
@@ -422,11 +407,12 @@ public class AlarmManagerService extends SystemService {
private static final String KEY_TIME_TICK_ALLOWED_WHILE_IDLE = private static final String KEY_TIME_TICK_ALLOWED_WHILE_IDLE =
"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_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 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_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_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10 * 1000;
private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000; private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
private static final int DEFAULT_MAX_ALARMS_PER_UID = 500; 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_LAZY_BATCHING = true;
private static final boolean DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE = 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 // Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -456,12 +445,6 @@ public class AlarmManagerService extends SystemService {
// Maximum alarm recurrence interval // Maximum alarm recurrence interval
public long MAX_INTERVAL = DEFAULT_MAX_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. // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
public long ALLOW_WHILE_IDLE_WHITELIST_DURATION public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
= DEFAULT_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 LAZY_BATCHING = DEFAULT_LAZY_BATCHING;
public boolean TIME_TICK_ALLOWED_WHILE_IDLE = DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE; 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; private long mLastAllowWhileIdleWhitelistDuration = -1;
Constants() { Constants() {
@@ -523,15 +508,13 @@ public class AlarmManagerService extends SystemService {
MAX_INTERVAL = properties.getLong( MAX_INTERVAL = properties.getLong(
KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL); KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
break; break;
case KEY_ALLOW_WHILE_IDLE_SHORT_TIME: case KEY_ALLOW_WHILE_IDLE_QUOTA:
ALLOW_WHILE_IDLE_SHORT_TIME = properties.getLong( ALLOW_WHILE_IDLE_QUOTA = properties.getInt(KEY_ALLOW_WHILE_IDLE_QUOTA,
KEY_ALLOW_WHILE_IDLE_SHORT_TIME, DEFAULT_ALLOW_WHILE_IDLE_QUOTA);
DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME); if (ALLOW_WHILE_IDLE_QUOTA <= 0) {
break; Slog.w(TAG, "Cannot have allow-while-idle quota lower than 1.");
case KEY_ALLOW_WHILE_IDLE_LONG_TIME: ALLOW_WHILE_IDLE_QUOTA = 1;
ALLOW_WHILE_IDLE_LONG_TIME = properties.getLong( }
KEY_ALLOW_WHILE_IDLE_LONG_TIME,
DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
break; break;
case KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION: case KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION:
ALLOW_WHILE_IDLE_WHITELIST_DURATION = properties.getLong( ALLOW_WHILE_IDLE_WHITELIST_DURATION = properties.getLong(
@@ -660,14 +643,11 @@ public class AlarmManagerService extends SystemService {
TimeUtils.formatDuration(LISTENER_TIMEOUT, pw); TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
pw.println(); pw.println();
pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("allow_while_idle_window=");
pw.print("="); TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WINDOW, pw);
TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
pw.println(); pw.println();
pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print(KEY_ALLOW_WHILE_IDLE_QUOTA, ALLOW_WHILE_IDLE_QUOTA);
pw.print("=");
TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
pw.println(); pw.println();
pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); 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); TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
pw.println(); pw.println();
pw.print(KEY_MAX_ALARMS_PER_UID); pw.print(KEY_MAX_ALARMS_PER_UID, MAX_ALARMS_PER_UID);
pw.print("="); pw.println();
pw.println(MAX_ALARMS_PER_UID);
pw.print(KEY_APP_STANDBY_WINDOW); pw.print(KEY_APP_STANDBY_WINDOW);
pw.print("="); pw.print("=");
@@ -685,14 +664,12 @@ public class AlarmManagerService extends SystemService {
pw.println(); pw.println();
for (int i = 0; i < KEYS_APP_STANDBY_QUOTAS.length; i++) { for (int i = 0; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
pw.print(KEYS_APP_STANDBY_QUOTAS[i]); pw.print(KEYS_APP_STANDBY_QUOTAS[i], APP_STANDBY_QUOTAS[i]);
pw.print("="); pw.println();
pw.println(APP_STANDBY_QUOTAS[i]);
} }
pw.print(KEY_APP_STANDBY_RESTRICTED_QUOTA); pw.print(KEY_APP_STANDBY_RESTRICTED_QUOTA, APP_STANDBY_RESTRICTED_QUOTA);
pw.print("="); pw.println();
pw.println(APP_STANDBY_RESTRICTED_QUOTA);
pw.print(KEY_APP_STANDBY_RESTRICTED_WINDOW); pw.print(KEY_APP_STANDBY_RESTRICTED_WINDOW);
pw.print("="); pw.print("=");
@@ -715,10 +692,6 @@ public class AlarmManagerService extends SystemService {
proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL); proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL);
proto.write(ConstantsProto.MAX_INTERVAL_DURATION_MS, MAX_INTERVAL); proto.write(ConstantsProto.MAX_INTERVAL_DURATION_MS, MAX_INTERVAL);
proto.write(ConstantsProto.LISTENER_TIMEOUT_DURATION_MS, LISTENER_TIMEOUT); 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, proto.write(ConstantsProto.ALLOW_WHILE_IDLE_WHITELIST_DURATION_MS,
ALLOW_WHILE_IDLE_WHITELIST_DURATION); ALLOW_WHILE_IDLE_WHITELIST_DURATION);
@@ -1268,6 +1241,7 @@ public class AlarmManagerService extends SystemService {
mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater); mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater);
mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW); mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
mAllowWhileIdleHistory = new AppWakeupHistory(Constants.ALLOW_WHILE_IDLE_WINDOW);
mNextWakeup = mNextNonWakeup = 0; mNextWakeup = mNextNonWakeup = 0;
@@ -1636,25 +1610,28 @@ public class AlarmManagerService extends SystemService {
return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, nowElapsed); return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, nowElapsed);
} }
final long batterSaverPolicyElapsed; final long batterySaverPolicyElapsed;
if ((alarm.flags & (AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) { if ((alarm.flags & (AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) {
// Unrestricted. // Unrestricted.
batterSaverPolicyElapsed = nowElapsed; batterySaverPolicyElapsed = nowElapsed;
} else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) { } else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
// Allowed but limited. // Allowed but limited.
final long minDelay; final int userId = UserHandle.getUserId(alarm.creatorUid);
if (mUseAllowWhileIdleShortTime.get(alarm.creatorUid)) { final int quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
minDelay = mConstants.ALLOW_WHILE_IDLE_SHORT_TIME; final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow(
alarm.sourcePackage, userId);
if (dispatchesInWindow < quota) {
// fine to go out immediately.
batterySaverPolicyElapsed = nowElapsed;
} else { } 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 { } else {
// Not allowed. // 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; deviceIdlePolicyTime = nowElapsed;
} else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) { } else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
// Allowed but limited. // Allowed but limited.
final long lastDispatch = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0); final int userId = UserHandle.getUserId(alarm.creatorUid);
deviceIdlePolicyTime = (lastDispatch == 0) ? nowElapsed final int quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
: lastDispatch + mConstants.ALLOW_WHILE_IDLE_LONG_TIME; 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 { } else {
// Not allowed. // Not allowed.
deviceIdlePolicyTime = mPendingIdleUntil.getWhenElapsed(); deviceIdlePolicyTime = mPendingIdleUntil.getWhenElapsed();
@@ -1723,11 +1709,11 @@ public class AlarmManagerService extends SystemService {
if (wakeupsInWindow >= quotaForBucket) { if (wakeupsInWindow >= quotaForBucket) {
final long minElapsed; final long minElapsed;
if (quotaForBucket <= 0) { if (quotaForBucket <= 0) {
// Just keep deferring for a day till the quota changes // Just keep deferring indefinitely till the quota changes.
minElapsed = nowElapsed + MILLIS_IN_DAY; minElapsed = nowElapsed + INDEFINITE_DELAY;
} else { } else {
// Suppose the quota for window was q, and the qth last delivery time for this // 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( final long t = mAppWakeupHistory.getNthLastWakeupForPackage(
sourcePackage, sourceUserId, quotaForBucket); sourcePackage, sourceUserId, quotaForBucket);
minElapsed = t + mConstants.APP_STANDBY_WINDOW; minElapsed = t + mConstants.APP_STANDBY_WINDOW;
@@ -1748,17 +1734,10 @@ public class AlarmManagerService extends SystemService {
ent.uid = a.uid; ent.uid = a.uid;
ent.pkg = a.operation.getCreatorPackage(); ent.pkg = a.operation.getCreatorPackage();
ent.tag = a.operation.getTag(""); ent.tag = a.operation.getTag("");
ent.op = "SET"; ent.op = "START IDLE";
ent.elapsedRealtime = mInjector.getElapsedRealtime(); ent.elapsedRealtime = mInjector.getElapsedRealtime();
ent.argRealtime = a.getWhenElapsed(); ent.argRealtime = a.getWhenElapsed();
mAllowWhileIdleDispatches.add(ent); 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)) { if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
@@ -2182,6 +2161,7 @@ public class AlarmManagerService extends SystemService {
pw.println("]"); pw.println("]");
pw.println(); pw.println();
pw.println("App Alarm history:");
mAppWakeupHistory.dump(pw, nowELAPSED); mAppWakeupHistory.dump(pw, nowELAPSED);
if (mPendingIdleUntil != null) { if (mPendingIdleUntil != null) {
@@ -2259,30 +2239,8 @@ public class AlarmManagerService extends SystemService {
pw.println(); pw.println();
} }
if (mLastAllowWhileIdleDispatch.size() > 0) { pw.println("Allow while idle history:");
pw.println("Last allow while idle dispatch times:"); mAllowWhileIdleHistory.dump(pw, nowELAPSED);
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();
if (mLog.dump(pw, "Recent problems:")) { if (mLog.dump(pw, "Recent problems:")) {
pw.println(); pw.println();
@@ -2533,25 +2491,6 @@ public class AlarmManagerService extends SystemService {
f.dumpDebug(proto, AlarmManagerServiceDumpProto.OUTSTANDING_DELIVERIES); 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); mLog.dumpDebug(proto, AlarmManagerServiceDumpProto.RECENT_PROBLEMS);
final FilterStats[] topFilters = new FilterStats[10]; final FilterStats[] topFilters = new FilterStats[10];
@@ -3049,11 +2988,6 @@ public class AlarmManagerService extends SystemService {
mPendingBackgroundAlarms.removeAt(i); 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)) { if (mNextWakeFromIdle != null && whichAlarms.test(mNextWakeFromIdle)) {
mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm(); mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
if (mPendingIdleUntil != null) { if (mPendingIdleUntil != null) {
@@ -3215,6 +3149,16 @@ public class AlarmManagerService extends SystemService {
if (mPendingIdleUntil == alarm) { if (mPendingIdleUntil == alarm) {
mPendingIdleUntil = null; mPendingIdleUntil = null;
mAlarmStore.updateAlarmDeliveries(a -> adjustDeliveryTimeBasedOnDeviceIdle(a)); 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) { if (mNextWakeFromIdle == alarm) {
mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm(); mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
@@ -3829,7 +3773,6 @@ public class AlarmManagerService extends SystemService {
IntentFilter sdFilter = new IntentFilter(); IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
sdFilter.addAction(Intent.ACTION_USER_STOPPED); sdFilter.addAction(Intent.ACTION_USER_STOPPED);
sdFilter.addAction(Intent.ACTION_UID_REMOVED);
getContext().registerReceiver(this, sdFilter); getContext().registerReceiver(this, sdFilter);
} }
@@ -3856,12 +3799,7 @@ public class AlarmManagerService extends SystemService {
if (userHandle >= 0) { if (userHandle >= 0) {
removeUserLocked(userHandle); removeUserLocked(userHandle);
mAppWakeupHistory.removeForUser(userHandle); mAppWakeupHistory.removeForUser(userHandle);
} mAllowWhileIdleHistory.removeForUser(userHandle);
return;
case Intent.ACTION_UID_REMOVED:
if (uid >= 0) {
mLastAllowWhileIdleDispatch.delete(uid);
mUseAllowWhileIdleShortTime.delete(uid);
} }
return; return;
case Intent.ACTION_PACKAGE_REMOVED: case Intent.ACTION_PACKAGE_REMOVED:
@@ -3885,6 +3823,7 @@ public class AlarmManagerService extends SystemService {
if (uid >= 0) { if (uid >= 0) {
// package-removed and package-restarted case // package-removed and package-restarted case
mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid));
mAllowWhileIdleHistory.removeForPackage(pkg, UserHandle.getUserId(uid));
removeLocked(uid); removeLocked(uid);
} else { } else {
// external-applications-unavailable case // 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 @Override
public void removeAlarmsForUid(int uid) { public void removeAlarmsForUid(int uid) {
synchronized (mLock) { synchronized (mLock) {
@@ -4273,22 +4195,23 @@ public class AlarmManagerService extends SystemService {
notifyBroadcastAlarmPendingLocked(alarm.uid); notifyBroadcastAlarmPendingLocked(alarm.uid);
} }
if (allowWhileIdle) { if (allowWhileIdle) {
// Record the last time this uid handled an ALLOW_WHILE_IDLE alarm. final boolean doze = (mPendingIdleUntil != null);
mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED); final boolean batterySaver = (mAppStateTracker != null
if ((mAppStateTracker == null) && mAppStateTracker.isForceAllAppsStandbyEnabled());
|| mAppStateTracker.isUidInForeground(alarm.creatorUid)) { if (doze || batterySaver) {
mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true); // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm while the
} else { // device was in doze or battery saver.
mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false); 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) { if (RECORD_DEVICE_IDLE_ALARMS) {
IdleDispatchEntry ent = new IdleDispatchEntry(); IdleDispatchEntry ent = new IdleDispatchEntry();
ent.uid = alarm.uid; ent.uid = alarm.uid;
@@ -4300,8 +4223,6 @@ public class AlarmManagerService extends SystemService {
} }
} }
if (!isExemptFromAppStandby(alarm)) { if (!isExemptFromAppStandby(alarm)) {
final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
UserHandle.getUserId(alarm.creatorUid));
mAppWakeupHistory.recordAlarmForPackage(alarm.sourcePackage, mAppWakeupHistory.recordAlarmForPackage(alarm.sourcePackage,
UserHandle.getUserId(alarm.creatorUid), nowELAPSED); UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
} }

View File

@@ -271,8 +271,7 @@ public class AppStateTrackerTest {
verify(mMockIActivityManager).registerUidObserver( verify(mMockIActivityManager).registerUidObserver(
uidObserverArgumentCaptor.capture(), uidObserverArgumentCaptor.capture(),
eq(ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE eq(ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
| ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_ACTIVE),
| ActivityManager.UID_OBSERVER_PROCSTATE),
eq(ActivityManager.PROCESS_STATE_UNKNOWN), eq(ActivityManager.PROCESS_STATE_UNKNOWN),
isNull()); isNull());
verify(mMockIAppOpsService).startWatchingMode( verify(mMockIAppOpsService).startWatchingMode(
@@ -650,11 +649,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActiveSynced(UID_2)); assertFalse(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID)); 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, mIUidObserver.onUidStateChanged(UID_2,
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0, ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0,
ActivityManager.PROCESS_CAPABILITY_NONE); ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -670,11 +664,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActiveSynced(UID_2)); assertFalse(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID)); 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, mIUidObserver.onUidStateChanged(UID_1,
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
ActivityManager.PROCESS_CAPABILITY_NONE); ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -686,10 +675,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2)); assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID)); 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); mIUidObserver.onUidGone(UID_1, true);
waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain();
@@ -699,10 +684,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2)); assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID)); 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); mIUidObserver.onUidIdle(UID_2, true);
waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain();
@@ -712,10 +693,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2)); assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID)); 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, mIUidObserver.onUidStateChanged(UID_1,
ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0,
ActivityManager.PROCESS_CAPABILITY_NONE); ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -727,10 +704,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2)); assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID)); 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, mIUidObserver.onUidStateChanged(UID_1,
ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0,
ActivityManager.PROCESS_CAPABILITY_NONE); ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -746,10 +719,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActiveSynced(UID_2)); assertFalse(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID)); 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(). // The result from AMI.isUidActive() only affects isUidActiveSynced().
when(mMockIActivityManagerInternal.isUidActive(anyInt())).thenReturn(true); when(mMockIActivityManagerInternal.isUidActive(anyInt())).thenReturn(true);
@@ -760,11 +729,6 @@ public class AppStateTrackerTest {
assertTrue(instance.isUidActiveSynced(UID_1)); assertTrue(instance.isUidActiveSynced(UID_1));
assertTrue(instance.isUidActiveSynced(UID_2)); assertTrue(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID)); assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
assertFalse(instance.isUidInForeground(UID_1));
assertFalse(instance.isUidInForeground(UID_2));
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
} }
@Test @Test
@@ -1480,7 +1444,6 @@ public class AppStateTrackerTest {
callStart(instance); callStart(instance);
instance.mActiveUids.put(UID_1, true); instance.mActiveUids.put(UID_1, true);
instance.mForegroundUids.put(UID_2, true);
instance.mRunAnyRestrictedPackages.add(Pair.create(UID_1, PACKAGE_1)); instance.mRunAnyRestrictedPackages.add(Pair.create(UID_1, PACKAGE_1));
instance.mExemptedBucketPackages.add(UserHandle.getUserId(UID_2), PACKAGE_2); instance.mExemptedBucketPackages.add(UserHandle.getUserId(UID_2), PACKAGE_2);
@@ -1493,7 +1456,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved); mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(1, instance.mActiveUids.size()); assertEquals(1, instance.mActiveUids.size());
assertEquals(1, instance.mForegroundUids.size());
assertEquals(1, instance.mRunAnyRestrictedPackages.size()); assertEquals(1, instance.mRunAnyRestrictedPackages.size());
assertEquals(1, instance.mExemptedBucketPackages.size()); assertEquals(1, instance.mExemptedBucketPackages.size());
@@ -1506,7 +1468,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved); mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(1, instance.mActiveUids.size()); assertEquals(1, instance.mActiveUids.size());
assertEquals(1, instance.mForegroundUids.size());
assertEquals(1, instance.mRunAnyRestrictedPackages.size()); assertEquals(1, instance.mRunAnyRestrictedPackages.size());
assertEquals(1, instance.mExemptedBucketPackages.size()); assertEquals(1, instance.mExemptedBucketPackages.size());
@@ -1518,7 +1479,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved); mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(0, instance.mActiveUids.size()); assertEquals(0, instance.mActiveUids.size());
assertEquals(1, instance.mForegroundUids.size());
assertEquals(0, instance.mRunAnyRestrictedPackages.size()); assertEquals(0, instance.mRunAnyRestrictedPackages.size());
assertEquals(1, instance.mExemptedBucketPackages.size()); assertEquals(1, instance.mExemptedBucketPackages.size());
@@ -1530,7 +1490,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved); mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(0, instance.mActiveUids.size()); assertEquals(0, instance.mActiveUids.size());
assertEquals(0, instance.mForegroundUids.size());
assertEquals(0, instance.mRunAnyRestrictedPackages.size()); assertEquals(0, instance.mRunAnyRestrictedPackages.size());
assertEquals(0, instance.mExemptedBucketPackages.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.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_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.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.ALLOW_WHILE_IDLE_WINDOW;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME; 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_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_LAZY_BATCHING;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT; 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_MAX_INTERVAL;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_FUTURITY; 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.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.INDEFINITE_DELAY;
import static com.android.server.alarm.AlarmManagerService.IS_WAKEUP_MASK; import static com.android.server.alarm.AlarmManagerService.IS_WAKEUP_MASK;
import static com.android.server.alarm.AlarmManagerService.TIME_CHANGED_MASK; import static com.android.server.alarm.AlarmManagerService.TIME_CHANGED_MASK;
@@ -409,6 +410,12 @@ public class AlarmManagerServiceTest {
return mockPi; 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) { private void setDeviceConfigLong(String key, long val) {
mDeviceConfigKeys.add(key); mDeviceConfigKeys.add(key);
doReturn(val).when(mDeviceConfigProperties).getLong(eq(key), anyLong()); doReturn(val).when(mDeviceConfigProperties).getLong(eq(key), anyLong());
@@ -430,10 +437,12 @@ public class AlarmManagerServiceTest {
setDeviceConfigLong(KEY_MIN_INTERVAL, 0); setDeviceConfigLong(KEY_MIN_INTERVAL, 0);
mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]); mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_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()); .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()); .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); mService.mConstants.onPropertiesChanged(mDeviceConfigProperties);
} }
@@ -496,15 +505,13 @@ public class AlarmManagerServiceTest {
setDeviceConfigLong(KEY_MIN_FUTURITY, 5); setDeviceConfigLong(KEY_MIN_FUTURITY, 5);
setDeviceConfigLong(KEY_MIN_INTERVAL, 10); setDeviceConfigLong(KEY_MIN_INTERVAL, 10);
setDeviceConfigLong(KEY_MAX_INTERVAL, 15); setDeviceConfigLong(KEY_MAX_INTERVAL, 15);
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 20); setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, 20);
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, 25);
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION, 30); setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION, 30);
setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 35); setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 35);
assertEquals(5, mService.mConstants.MIN_FUTURITY); assertEquals(5, mService.mConstants.MIN_FUTURITY);
assertEquals(10, mService.mConstants.MIN_INTERVAL); assertEquals(10, mService.mConstants.MIN_INTERVAL);
assertEquals(15, mService.mConstants.MAX_INTERVAL); assertEquals(15, mService.mConstants.MAX_INTERVAL);
assertEquals(20, mService.mConstants.ALLOW_WHILE_IDLE_SHORT_TIME); assertEquals(20, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA);
assertEquals(25, mService.mConstants.ALLOW_WHILE_IDLE_LONG_TIME);
assertEquals(30, mService.mConstants.ALLOW_WHILE_IDLE_WHITELIST_DURATION); assertEquals(30, mService.mConstants.ALLOW_WHILE_IDLE_WHITELIST_DURATION);
assertEquals(35, mService.mConstants.LISTENER_TIMEOUT); assertEquals(35, mService.mConstants.LISTENER_TIMEOUT);
} }
@@ -1301,62 +1308,54 @@ public class AlarmManagerServiceTest {
public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception { public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception {
doReturn(0).when(mService).fuzzForDuration(anyLong()); doReturn(0).when(mService).fuzzForDuration(anyLong());
final long awiDelayForTest = 23; setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + ALLOW_WHILE_IDLE_WINDOW + 1000,
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest);
setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000,
getNewMockPendingIntent()); getNewMockPendingIntent());
assertNotNull(mService.mPendingIdleUntil); assertNotNull(mService.mPendingIdleUntil);
final long seedTrigger = mNowElapsedTest + 3; final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA;
final int numAlarms = 10; final long firstTrigger = mNowElapsedTest + 10;
final PendingIntent[] pis = new PendingIntent[numAlarms]; for (int i = 0; i < quota; i++) {
for (int i = 0; i < numAlarms; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
pis[i] = getNewMockPendingIntent(); getNewMockPendingIntent(), false);
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, seedTrigger + i * i, pis[i], false); mNowElapsedTest = mTestTimer.getElapsed();
}
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;
mTestTimer.expire(); 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 @Test
public void allowWhileIdleUnrestrictedInIdle() throws Exception { public void allowWhileIdleUnrestricted() throws Exception {
doReturn(0).when(mService).fuzzForDuration(anyLong()); doReturn(0).when(mService).fuzzForDuration(anyLong());
final long awiDelayForTest = 127; // Both battery saver and doze are on.
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest);
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 0);
setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000, setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000,
getNewMockPendingIntent()); getNewMockPendingIntent());
assertNotNull(mService.mPendingIdleUntil); assertNotNull(mService.mPendingIdleUntil);
final long seedTrigger = mNowElapsedTest + 3; when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
for (int i = 1; i <= 5; i++) { TEST_CALLING_PACKAGE)).thenReturn(true);
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, seedTrigger + i * i,
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); getNewMockPendingIntent(), true);
} }
for (int i = 1; i <= 5; i++) { // All of them should fire as expected.
final long nextTrigger = mTestTimer.getElapsed(); for (int i = 0; i < numAlarms; i++) {
assertEquals("Wrong trigger for alarm " + i, seedTrigger + i * i, nextTrigger); mNowElapsedTest = mTestTimer.getElapsed();
mNowElapsedTest = nextTrigger; assertEquals("Incorrect trigger at i=" + i, firstTrigger + i, mNowElapsedTest);
mTestTimer.expire(); mTestTimer.expire();
} }
} }
@@ -1427,9 +1426,10 @@ public class AlarmManagerServiceTest {
verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture()); verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture());
final AppStateTrackerImpl.Listener listener = listenerArgumentCaptor.getValue(); final AppStateTrackerImpl.Listener listener = listenerArgumentCaptor.getValue();
final PendingIntent alarmPi = getNewMockPendingIntent();
when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
TEST_CALLING_PACKAGE)).thenReturn(true); TEST_CALLING_PACKAGE)).thenReturn(true);
final PendingIntent alarmPi = getNewMockPendingIntent();
setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 7, alarmPi); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 7, alarmPi);
assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed()); assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed());
@@ -1446,61 +1446,64 @@ public class AlarmManagerServiceTest {
@Test @Test
public void allowWhileIdleAlarmsInBatterySaver() throws Exception { 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, when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
TEST_CALLING_PACKAGE)).thenReturn(true); 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); 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); 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; firstTrigger = mNowElapsedTest + 10;
mTestTimer.expire(); for (int i = 0; i < quota; i++) {
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
assertEquals(mNowElapsedTest + longDelay, mTestTimer.getElapsed()); getNewMockPendingIntent(), false);
listener.onUidForeground(TEST_CALLING_UID, true); }
// The next alarm should be deferred by shortDelay. // This delivery time maintains the quota invariant. Should not be deferred.
assertEquals(mNowElapsedTest + shortDelay, mTestTimer.getElapsed()); expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW + 5;
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger,
mNowElapsedTest = mTestTimer.getElapsed();
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1,
getNewMockPendingIntent(), false); getNewMockPendingIntent(), false);
for (int i = 0; i < quota; i++) {
when(mAppStateTracker.isUidInForeground(TEST_CALLING_UID)).thenReturn(true); mNowElapsedTest = mTestTimer.getElapsed();
mTestTimer.expire(); mTestTimer.expire();
// The next alarm should be deferred by shortDelay again. }
assertEquals(mNowElapsedTest + shortDelay, mTestTimer.getElapsed()); assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
mTestTimer.getElapsed());
mNowElapsedTest = mTestTimer.getElapsed();
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1,
getNewMockPendingIntent(), true);
when(mAppStateTracker.isUidInForeground(TEST_CALLING_UID)).thenReturn(false);
mTestTimer.expire();
final long lastAwiDispatch = mNowElapsedTest;
// Unrestricted, so should not be changed.
assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed());
mNowElapsedTest = mTestTimer.getElapsed();
// AWI_unrestricted should not affect normal AWI bookkeeping.
// The next alarm is after the short delay but before the long delay.
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, lastAwiDispatch + shortDelay + 1,
getNewMockPendingIntent(), false);
mTestTimer.expire();
assertEquals(lastAwiDispatch + longDelay, mTestTimer.getElapsed());
listener.onUidForeground(TEST_CALLING_UID, true);
assertEquals(lastAwiDispatch + shortDelay + 1, mTestTimer.getElapsed());
} }
@Test @Test