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