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