From bd8f2ea6973a5f01628b312bd390aab72631fe07 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Thu, 8 Oct 2020 21:34:01 -0700 Subject: [PATCH] Adding a policy mechanism to control alarms Alarms now keep track of their deliverability per different throttling policies. Each policy can dictate a time such that the alarm cannot expire any earlier than that. The ultimate delivery start is then calculated as the latest of these times. This makes it simpler to manage different throttling policies separately. Adding two policies to start: 1. Requester policy: This defines the time when the caller requested the alarm to go off. For an alarm with FLAG_IDLE_UNTIL, this is adjusted to be before the next WAKE_FROM_IDLE. This is an exceptional case as this alarm is supposed to be exempt from all the other policies. 2. App-standby policy: This defines the time when the caller app is going to be in quota as per its app-standby-bucket. The delivery end is chosen to the delivery start or (requester policy time + the supplied window), whichever is later. Also, fixed some bugs related to idle-until-time not getting snapped to the next wake-from-idle time in some cases. Test: atest FrameworksMockingServicesTests:\ com.android.server.alarm atest CtsAlarmManagerTestCases atest CtsAppTestCases:AlarmManagerTest Bug: 170279979 Change-Id: Ib7fac90fe4804b624568ca4c6eba7a4cbc8a8aad --- .../java/com/android/server/alarm/Alarm.java | 225 ++++++++++---- .../server/alarm/AlarmManagerService.java | 278 ++++++++---------- .../com/android/server/alarm/AlarmStore.java | 17 +- .../server/alarm/BatchingAlarmStore.java | 45 ++- .../server/alarm/AlarmManagerServiceTest.java | 152 +++++++++- .../android/server/alarm/AlarmStoreTest.java | 88 +++--- .../com/android/server/alarm/AlarmTest.java | 122 ++++++++ .../alarm/BackgroundRestrictedAlarmsTest.java | 2 +- .../com/android/server/alarm/Constants.java | 22 ++ 9 files changed, 659 insertions(+), 292 deletions(-) create mode 100644 services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java create mode 100644 services/tests/mockingservicestests/src/com/android/server/alarm/Constants.java diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java index f672e4b711c43..45ea23321d158 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java @@ -16,10 +16,13 @@ package com.android.server.alarm; +import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.RTC; import static android.app.AlarmManager.RTC_WAKEUP; +import static com.android.server.alarm.AlarmManagerService.clampPositive; + import android.app.AlarmManager; import android.app.IAlarmListener; import android.app.PendingIntent; @@ -32,8 +35,28 @@ import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; +/** + * Class to describe an alarm that is used to the set the kernel timer that returns when the timer + * expires. The timer will wake up the device if the alarm is a "wakeup" alarm. + */ class Alarm { + private static final int NUM_POLICIES = 2; + /** + * Index used to store the time the alarm was requested to expire. To be used with + * {@link #setPolicyElapsed(int, long)} + */ + public static final int REQUESTER_POLICY_INDEX = 0; + /** + * Index used to store the earliest time the alarm can expire based on app-standby policy. + * To be used with {@link #setPolicyElapsed(int, long)} + */ + public static final int APP_STANDBY_POLICY_INDEX = 1; + public final int type; + /** + * The original trigger time supplied by the caller. This can be in the elapsed or rtc time base + * depending on the type of this alarm + */ public final long origWhen; public final boolean wakeup; public final PendingIntent operation; @@ -47,42 +70,40 @@ class Alarm { public final int creatorUid; public final String packageName; public final String sourcePackage; + public final long windowLength; + public final long repeatInterval; public int count; - public long when; - public long windowLength; - public long whenElapsed; // 'when' in the elapsed time base - public long maxWhenElapsed; // also in the elapsed time base - // Expected alarm expiry time before app standby deferring is applied. - public long expectedWhenElapsed; - public long expectedMaxWhenElapsed; - public long repeatInterval; + /** The earliest time this alarm is eligible to fire according to each policy */ + private long[] mPolicyWhenElapsed; + /** The ultimate delivery time to be used for this alarm */ + private long mWhenElapsed; + private long mMaxWhenElapsed; public AlarmManagerService.PriorityClass priorityClass; - Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen, - long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag, - WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info, - int _uid, String _pkgName) { - type = _type; - origWhen = _when; - wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP - || _type == AlarmManager.RTC_WAKEUP; - when = _when; - whenElapsed = _whenElapsed; - expectedWhenElapsed = _whenElapsed; - windowLength = _windowLength; - maxWhenElapsed = expectedMaxWhenElapsed = AlarmManagerService.clampPositive(_maxWhen); - repeatInterval = _interval; - operation = _op; - listener = _rec; - listenerTag = _listenerTag; - statsTag = makeTag(_op, _listenerTag, _type); - workSource = _ws; - flags = _flags; - alarmClock = _info; - uid = _uid; - packageName = _pkgName; + Alarm(int type, long when, long requestedWhenElapsed, long windowLength, long interval, + PendingIntent op, IAlarmListener rec, String listenerTag, WorkSource ws, int flags, + AlarmManager.AlarmClockInfo info, int uid, String pkgName) { + this.type = type; + origWhen = when; + wakeup = type == AlarmManager.ELAPSED_REALTIME_WAKEUP + || type == AlarmManager.RTC_WAKEUP; + mPolicyWhenElapsed = new long[NUM_POLICIES]; + mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] = requestedWhenElapsed; + mWhenElapsed = requestedWhenElapsed; + this.windowLength = windowLength; + mMaxWhenElapsed = clampPositive(requestedWhenElapsed + windowLength); + repeatInterval = interval; + operation = op; + listener = rec; + this.listenerTag = listenerTag; + statsTag = makeTag(op, listenerTag, type); + workSource = ws; + this.flags = flags; + alarmClock = info; + this.uid = uid; + packageName = pkgName; sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName; - creatorUid = (operation != null) ? operation.getCreatorUid() : uid; + creatorUid = (operation != null) ? operation.getCreatorUid() : this.uid; } public static String makeTag(PendingIntent pi, String tag, int type) { @@ -91,13 +112,6 @@ class Alarm { return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag); } - public AlarmManagerService.WakeupEvent makeWakeupEvent(long nowRTC) { - return new AlarmManagerService.WakeupEvent(nowRTC, creatorUid, - (operation != null) - ? operation.getIntent().getAction() - : (":" + listenerTag)); - } - // Returns true if either matches public boolean matches(PendingIntent pi, IAlarmListener rec) { return (operation != null) @@ -109,6 +123,65 @@ class Alarm { return packageName.equals(sourcePackage); } + /** + * Get the earliest time this alarm is allowed to expire based on the given policy. + * + * @param policyIndex The index of the policy. One of [{@link #REQUESTER_POLICY_INDEX}, + * {@link #APP_STANDBY_POLICY_INDEX}]. + */ + public long getPolicyElapsed(int policyIndex) { + return mPolicyWhenElapsed[policyIndex]; + } + + /** + * Get the earliest time that this alarm should be delivered to the requesting app. + */ + public long getWhenElapsed() { + return mWhenElapsed; + } + + /** + * Get the latest time that this alarm should be delivered to the requesting app. Will be equal + * to {@link #getWhenElapsed()} in case this is an exact alarm. + */ + public long getMaxWhenElapsed() { + return mMaxWhenElapsed; + } + + /** + * Set the earliest time this alarm can expire based on the passed policy index. + * + * @return {@code true} if this change resulted in a change in the ultimate delivery time (or + * time window in the case of inexact alarms) of this alarm. + * @see #getWhenElapsed() + * @see #getMaxWhenElapsed() + * @see #getPolicyElapsed(int) + */ + public boolean setPolicyElapsed(int policyIndex, long policyElapsed) { + mPolicyWhenElapsed[policyIndex] = policyElapsed; + return updateWhenElapsed(); + } + + /** + * @return {@code true} if either {@link #mWhenElapsed} or {@link #mMaxWhenElapsed} changes + * due to this call. + */ + private boolean updateWhenElapsed() { + final long oldWhenElapsed = mWhenElapsed; + mWhenElapsed = 0; + for (int i = 0; i < NUM_POLICIES; i++) { + mWhenElapsed = Math.max(mWhenElapsed, mPolicyWhenElapsed[i]); + } + + final long oldMaxWhenElapsed = mMaxWhenElapsed; + // windowLength should always be >= 0 here. + final long maxRequestedElapsed = clampPositive( + mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] + windowLength); + mMaxWhenElapsed = Math.max(maxRequestedElapsed, mWhenElapsed); + + return (oldWhenElapsed != mWhenElapsed) || (oldMaxWhenElapsed != mMaxWhenElapsed); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(128); @@ -116,11 +189,11 @@ class Alarm { sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(" type "); sb.append(type); - sb.append(" when "); - sb.append(when); + sb.append(" origWhen "); + sb.append(origWhen); sb.append(" "); sb.append(" whenElapsed "); - sb.append(whenElapsed); + sb.append(getWhenElapsed()); sb.append(" "); sb.append(sourcePackage); sb.append('}'); @@ -136,30 +209,46 @@ class Alarm { dump(ipw, nowELAPSED, sdf); } + private static String policyIndexToString(int index) { + switch (index) { + case REQUESTER_POLICY_INDEX: + return "requester"; + case APP_STANDBY_POLICY_INDEX: + return "app_standby"; + default: + return "unknown"; + } + } + + public static String typeToString(int type) { + switch (type) { + case RTC: + return "RTC"; + case RTC_WAKEUP: + return "RTC_WAKEUP"; + case ELAPSED_REALTIME: + return "ELAPSED"; + case ELAPSED_REALTIME_WAKEUP: + return "ELAPSED_WAKEUP"; + default: + return "--unknown--"; + } + } + public void dump(IndentingPrintWriter ipw, long nowELAPSED, SimpleDateFormat sdf) { final boolean isRtc = (type == RTC || type == RTC_WAKEUP); ipw.print("tag="); ipw.println(statsTag); ipw.print("type="); - ipw.print(type); - ipw.print(" expectedWhenElapsed="); - TimeUtils.formatDuration(expectedWhenElapsed, nowELAPSED, ipw); - ipw.print(" expectedMaxWhenElapsed="); - TimeUtils.formatDuration(expectedMaxWhenElapsed, nowELAPSED, ipw); - ipw.print(" whenElapsed="); - TimeUtils.formatDuration(whenElapsed, nowELAPSED, ipw); - ipw.print(" maxWhenElapsed="); - TimeUtils.formatDuration(maxWhenElapsed, nowELAPSED, ipw); - ipw.print(" when="); + ipw.print(typeToString(type)); + ipw.print(" origWhen="); if (isRtc) { - ipw.print(sdf.format(new Date(when))); + ipw.print(sdf.format(new Date(origWhen))); } else { - TimeUtils.formatDuration(when, nowELAPSED, ipw); + TimeUtils.formatDuration(origWhen, nowELAPSED, ipw); } - ipw.println(); - - ipw.print("window="); + ipw.print(" window="); TimeUtils.formatDuration(windowLength, ipw); ipw.print(" repeatInterval="); ipw.print(repeatInterval); @@ -168,6 +257,19 @@ class Alarm { ipw.print(" flags=0x"); ipw.println(Integer.toHexString(flags)); + ipw.print("policyWhenElapsed:"); + for (int i = 0; i < NUM_POLICIES; i++) { + ipw.print(" " + policyIndexToString(i) + "="); + TimeUtils.formatDuration(mPolicyWhenElapsed[i], nowELAPSED, ipw); + } + ipw.println(); + + ipw.print("whenElapsed="); + TimeUtils.formatDuration(getWhenElapsed(), nowELAPSED, ipw); + ipw.print(" maxWhenElapsed="); + TimeUtils.formatDuration(mMaxWhenElapsed, nowELAPSED, ipw); + ipw.println(); + if (alarmClock != null) { ipw.println("Alarm clock:"); @@ -177,9 +279,10 @@ class Alarm { ipw.print(" showIntent="); ipw.println(alarmClock.getShowIntent()); } - ipw.print("operation="); - ipw.println(operation); - + if (operation != null) { + ipw.print("operation="); + ipw.println(operation); + } if (listener != null) { ipw.print("listener="); ipw.println(listener.asBinder()); @@ -191,7 +294,7 @@ class Alarm { proto.write(AlarmProto.TAG, statsTag); proto.write(AlarmProto.TYPE, type); - proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, whenElapsed - nowElapsed); + proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, getWhenElapsed() - nowElapsed); proto.write(AlarmProto.WINDOW_LENGTH_MS, windowLength); proto.write(AlarmProto.REPEAT_INTERVAL_MS, repeatInterval); proto.write(AlarmProto.COUNT, count); 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 05910a5b171e6..82819dab0f691 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -26,6 +26,9 @@ import static android.app.AlarmManager.RTC_WAKEUP; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.os.UserHandle.USER_SYSTEM; +import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX; +import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX; + import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.Activity; @@ -727,9 +730,9 @@ public class AlarmManagerService extends SystemService { } // within each class, sort by nominal delivery time - if (lhs.whenElapsed < rhs.whenElapsed) { + if (lhs.getWhenElapsed() < rhs.getWhenElapsed()) { return -1; - } else if (lhs.whenElapsed > rhs.whenElapsed) { + } else if (lhs.getWhenElapsed() > rhs.getWhenElapsed()) { return 1; } @@ -798,9 +801,12 @@ public class AlarmManagerService extends SystemService { this(context, new Injector(context)); } + private static boolean isRtc(int type) { + return (type == RTC || type == RTC_WAKEUP); + } + private long convertToElapsed(long when, int type) { - final boolean isRtc = (type == RTC || type == RTC_WAKEUP); - if (isRtc) { + if (isRtc(type)) { when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime(); } return when; @@ -823,13 +829,29 @@ public class AlarmManagerService extends SystemService { } // The RTC clock has moved arbitrarily, so we need to recalculate all the RTC alarm deliveries. - void reevaluateRtcAlarms(final long nowElapsed) { + void reevaluateRtcAlarms() { synchronized (mLock) { - final ArrayList rtcAlarms = mAlarmStore.remove(a -> (a.type == RTC - || a.type == RTC_WAKEUP)); - for (final Alarm a : rtcAlarms) { - restoreAlarmLocked(a, nowElapsed); - setImplLocked(a); + boolean changed = mAlarmStore.updateAlarmDeliveries(a -> { + if (!isRtc(a.type)) { + return false; + } + return restoreRequestedTime(a); + }); + + if (mNextWakeFromIdle != null && isRtc(mNextWakeFromIdle.type)) { + // The next wake from idle got updated due to the rtc time change, implying we need + // to update the time we have to come out of idle too. + changed |= mAlarmStore.updateAlarmDeliveries(a -> { + if (a != mPendingIdleUntil) { + return false; + } + return adjustIdleUntilTime(a); + }); + } + + if (changed) { + rescheduleKernelAlarmsLocked(); + // Only time shifted, so the next alarm clock will not change } } } @@ -844,7 +866,7 @@ public class AlarmManagerService extends SystemService { boolean reorderAlarmsBasedOnStandbyBuckets(ArraySet> targetPackages) { final long start = mStatLogger.getTime(); - final boolean changed = mAlarmStore.recalculateAlarmDeliveries(a -> { + final boolean changed = mAlarmStore.updateAlarmDeliveries(a -> { final Pair packageUser = Pair.create(a.sourcePackage, UserHandle.getUserId(a.creatorUid)); if (targetPackages != null && !targetPackages.contains(packageUser)) { @@ -857,23 +879,8 @@ public class AlarmManagerService extends SystemService { return changed; } - private void restoreAlarmLocked(Alarm a, long nowElapsed) { - a.when = a.origWhen; - long whenElapsed = convertToElapsed(a.when, a.type); - final long maxElapsed; - if (a.windowLength == AlarmManager.WINDOW_EXACT) { - // Exact - maxElapsed = whenElapsed; - } else { - // Not exact. Preserve any explicit window, otherwise recalculate - // the window based on the alarm's new futurity. Note that this - // reflects a policy of preferring timely to deferred delivery. - maxElapsed = (a.windowLength > 0) - ? clampPositive(whenElapsed + a.windowLength) - : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval); - } - a.expectedWhenElapsed = a.whenElapsed = whenElapsed; - a.expectedMaxWhenElapsed = a.maxWhenElapsed = maxElapsed; + private boolean restoreRequestedTime(Alarm a) { + return a.setPolicyElapsed(REQUESTER_POLICY_INDEX, convertToElapsed(a.origWhen, a.type)); } static long clampPositive(long val) { @@ -973,14 +980,17 @@ public class AlarmManagerService extends SystemService { // Recurring alarms may have passed several alarm intervals while the // alarm was kept pending. Send the appropriate trigger count. if (alarm.repeatInterval > 0) { - alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval; + alarm.count += (nowELAPSED - alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX)) + / alarm.repeatInterval; // Also schedule its next recurrence final long delta = alarm.count * alarm.repeatInterval; - final long nextElapsed = alarm.expectedWhenElapsed + delta; - setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength, - maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), - alarm.repeatInterval, alarm.operation, null, null, alarm.flags, - alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName); + final long nextElapsed = alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX) + delta; + final long nextMaxElapsed = maxTriggerTime(nowELAPSED, nextElapsed, + alarm.repeatInterval); + setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed, + nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null, + null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid, + alarm.packageName); // Kernel alarms will be rescheduled as needed in setImplLocked } } @@ -1026,18 +1036,10 @@ public class AlarmManagerService extends SystemService { if (mPendingWhileIdleAlarms.size() > 0) { ArrayList alarms = mPendingWhileIdleAlarms; mPendingWhileIdleAlarms = new ArrayList<>(); - final long nowElapsed = mInjector.getElapsedRealtime(); for (int i = alarms.size() - 1; i >= 0; i--) { - Alarm a = alarms.get(i); - restoreAlarmLocked(a, nowElapsed); - setImplLocked(a); + setImplLocked(alarms.get(i)); } } - - // Reschedule everything. - rescheduleKernelAlarmsLocked(); - updateNextAlarmClockLocked(); - } static final class InFlight { @@ -1449,6 +1451,11 @@ public class AlarmManagerService extends SystemService { } } + if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) { + // Do not support windows for idle-until alarms. + windowLength = AlarmManager.WINDOW_EXACT; + } + // Sanity check the window length. This will catch people mistakenly // trying to pass an end-of-window timestamp rather than a duration. if (windowLength > AlarmManager.INTERVAL_HALF_DAY) { @@ -1515,17 +1522,17 @@ public class AlarmManagerService extends SystemService { Slog.w(TAG, errorMsg); throw new IllegalStateException(errorMsg); } - setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed, - interval, operation, directReceiver, listenerTag, flags, workSource, - alarmClock, callingUid, callingPackage); + setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation, + directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, + callingPackage); } } private void setImplLocked(int type, long when, long whenElapsed, long windowLength, - long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver, + long interval, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) { - Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval, + final Alarm a = new Alarm(type, when, whenElapsed, windowLength, interval, operation, directReceiver, listenerTag, workSource, flags, alarmClock, callingUid, callingPackage); if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) { @@ -1560,72 +1567,55 @@ public class AlarmManagerService extends SystemService { } /** - * Adjusts the idle-until alarm delivery time based on the upcoming wake-from-idle alarm. + * An alarm with {@link AlarmManager#FLAG_IDLE_UNTIL} is a special alarm that will put the + * system into idle until it goes off. We need to pull it earlier if there are existing alarms + * that have requested to bring us out of idle at an earlier time. * * @param alarm The alarm to adjust * @return true if the alarm delivery time was updated. */ private boolean adjustIdleUntilTime(Alarm alarm) { - if ((alarm.flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) { + if ((alarm.flags & AlarmManager.FLAG_IDLE_UNTIL) == 0) { return false; } - // This is a special alarm that will put the system into idle until it goes off. - // The caller has given the time they want this to happen at, however we need - // to pull that earlier if there are existing alarms that have requested to - // bring us out of idle at an earlier time. - if (mNextWakeFromIdle != null && alarm.whenElapsed > mNextWakeFromIdle.whenElapsed) { - alarm.when = alarm.whenElapsed = alarm.maxWhenElapsed = mNextWakeFromIdle.whenElapsed; + restoreRequestedTime(alarm); + long triggerBeforeFuzz = alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX); + if (mNextWakeFromIdle != null && triggerBeforeFuzz > mNextWakeFromIdle.getWhenElapsed()) { + triggerBeforeFuzz = mNextWakeFromIdle.getWhenElapsed(); } // Add fuzz to make the alarm go off some time before the actual desired time. - final long nowElapsed = mInjector.getElapsedRealtime(); - final int fuzz = fuzzForDuration(alarm.whenElapsed - nowElapsed); + final int fuzz = fuzzForDuration(alarm.getWhenElapsed() - mInjector.getElapsedRealtime()); + final int delta; if (fuzz > 0) { if (mRandom == null) { mRandom = new Random(); } - final int delta = mRandom.nextInt(fuzz); - alarm.whenElapsed -= delta; - if (false) { - Slog.d(TAG, "Alarm when: " + alarm.whenElapsed); - Slog.d(TAG, "Delta until alarm: " + (alarm.whenElapsed - nowElapsed)); - Slog.d(TAG, "Applied fuzz: " + fuzz); - Slog.d(TAG, "Final delta: " + delta); - Slog.d(TAG, "Final when: " + alarm.whenElapsed); - } - alarm.when = alarm.maxWhenElapsed = alarm.whenElapsed; + delta = mRandom.nextInt(fuzz); + } else { + delta = 0; } + alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, triggerBeforeFuzz - delta); return true; } /** - * Adjusts the alarm delivery time based on the current app standby bucket. + * Adjusts the alarm's policy time for app_standby. * - * @param alarm The alarm to adjust - * @return true if the alarm delivery time was updated. + * @param alarm The alarm to update. + * @return {@code true} if the actual delivery time of the given alarm was updated due to + * adjustments made in this call. */ private boolean adjustDeliveryTimeBasedOnBucketLocked(Alarm alarm) { - if (isExemptFromAppStandby(alarm)) { - return false; + final long nowElapsed = mInjector.getElapsedRealtime(); + if (isExemptFromAppStandby(alarm) || mAppStandbyParole) { + return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed); } - if (mAppStandbyParole) { - if (alarm.whenElapsed > alarm.expectedWhenElapsed) { - // We did defer this alarm earlier, restore original requirements - alarm.whenElapsed = alarm.expectedWhenElapsed; - alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; - return true; - } - return false; - } - final long oldWhenElapsed = alarm.whenElapsed; - final long oldMaxWhenElapsed = alarm.maxWhenElapsed; final String sourcePackage = alarm.sourcePackage; final int sourceUserId = UserHandle.getUserId(alarm.creatorUid); final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket( - sourcePackage, sourceUserId, mInjector.getElapsedRealtime()); + sourcePackage, sourceUserId, nowElapsed); - // Quota deferring implementation: - boolean deferred = false; final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage, sourceUserId); if (standbyBucket == UsageStatsManager.STANDBY_BUCKET_RESTRICTED) { @@ -1635,14 +1625,9 @@ public class AlarmManagerService extends SystemService { if (wakeupsInWindow > 0) { final long lastWakeupTime = mAppWakeupHistory.getNthLastWakeupForPackage( sourcePackage, sourceUserId, mConstants.APP_STANDBY_RESTRICTED_QUOTA); - if (mInjector.getElapsedRealtime() - lastWakeupTime - < mConstants.APP_STANDBY_RESTRICTED_WINDOW) { - final long minElapsed = - lastWakeupTime + mConstants.APP_STANDBY_RESTRICTED_WINDOW; - if (alarm.expectedWhenElapsed < minElapsed) { - alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; - deferred = true; - } + if ((nowElapsed - lastWakeupTime) < mConstants.APP_STANDBY_RESTRICTED_WINDOW) { + return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, + lastWakeupTime + mConstants.APP_STANDBY_RESTRICTED_WINDOW); } } } else { @@ -1651,7 +1636,7 @@ public class AlarmManagerService extends SystemService { final long minElapsed; if (quotaForBucket <= 0) { // Just keep deferring for a day till the quota changes - minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY; + minElapsed = nowElapsed + MILLIS_IN_DAY; } 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) + @@ -1659,19 +1644,11 @@ public class AlarmManagerService extends SystemService { sourcePackage, sourceUserId, quotaForBucket); minElapsed = t + mConstants.APP_STANDBY_WINDOW; } - if (alarm.expectedWhenElapsed < minElapsed) { - alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; - deferred = true; - } + return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, minElapsed); } } - if (!deferred) { - // Restore original requirements in case they were changed earlier. - alarm.whenElapsed = alarm.expectedWhenElapsed; - alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; - } - - return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed); + // wakeupsInWindow are less than the permitted quota, hence no deferring is needed. + return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed); } private static boolean isAllowedWhileIdle(Alarm a) { @@ -1691,7 +1668,7 @@ public class AlarmManagerService extends SystemService { ent.tag = a.operation.getTag(""); ent.op = "SET"; ent.elapsedRealtime = mInjector.getElapsedRealtime(); - ent.argRealtime = a.whenElapsed; + ent.argRealtime = a.getWhenElapsed(); mAllowWhileIdleDispatches.add(ent); if (mPendingIdleUntil == null) { IdleDispatchEntry ent2 = new IdleDispatchEntry(); @@ -1704,6 +1681,7 @@ public class AlarmManagerService extends SystemService { if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) { Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil + " to " + a); + mAlarmStore.remove(mPendingIdleUntil::equals); } mPendingIdleUntil = a; final ArrayList notAllowedWhileIdleAlarms = mAlarmStore.remove( @@ -1718,18 +1696,16 @@ public class AlarmManagerService extends SystemService { } } if ((a.flags & AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) { - if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) { + if (mNextWakeFromIdle == null || mNextWakeFromIdle.getWhenElapsed() + > a.getWhenElapsed()) { mNextWakeFromIdle = a; // If this wake from idle is earlier than whatever was previously scheduled, - // and we are currently idling, then we need to rebatch alarms in case the idle - // until time needs to be updated. + // and we are currently idling, then the idle-until time needs to be updated. if (mPendingIdleUntil != null) { - final long nowElapsed = mInjector.getElapsedRealtime(); - mAlarmStore.recalculateAlarmDeliveries(alarm -> { + mAlarmStore.updateAlarmDeliveries(alarm -> { if (alarm != mPendingIdleUntil) { return false; } - restoreAlarmLocked(alarm, nowElapsed); return adjustIdleUntilTime(alarm); }); } @@ -2563,7 +2539,7 @@ public class AlarmManagerService extends SystemService { long getNextWakeFromIdleTimeImpl() { synchronized (mLock) { - return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE; + return mNextWakeFromIdle != null ? mNextWakeFromIdle.getWhenElapsed() : Long.MAX_VALUE; } } @@ -2784,12 +2760,11 @@ public class AlarmManagerService extends SystemService { restorePending = true; } if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) { - mNextWakeFromIdle = null; - mAlarmStore.recalculateAlarmDeliveries(alarm -> { + mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm(); + mAlarmStore.updateAlarmDeliveries(alarm -> { if (alarm != mPendingIdleUntil) { return false; } - restoreAlarmLocked(alarm, mInjector.getElapsedRealtime()); return adjustIdleUntilTime(alarm); }); } @@ -2834,15 +2809,14 @@ public class AlarmManagerService extends SystemService { mPendingBackgroundAlarms.removeAt(i); } } - // If we're currently keying off of this app's alarms for doze transitions, - // make sure to reset to other triggers. + // If we're currently using this app's alarms to come out of doze, + // make sure to reset to any remaining WAKE_FROM_IDLE alarms. if (mNextWakeFromIdle != null && mNextWakeFromIdle.uid == uid) { - mNextWakeFromIdle = null; - mAlarmStore.recalculateAlarmDeliveries(alarm -> { + mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm(); + mAlarmStore.updateAlarmDeliveries(alarm -> { if (alarm != mPendingIdleUntil) { return false; } - restoreAlarmLocked(alarm, mInjector.getElapsedRealtime()); return adjustIdleUntilTime(alarm); }); } @@ -2906,15 +2880,14 @@ public class AlarmManagerService extends SystemService { mPendingBackgroundAlarms.removeAt(i); } } - // If we're currently keying off of this app's alarms for doze transitions, - // make sure to reset to other triggers. + // If we're currently using this app's alarms to come out of doze, + // make sure to reset to any remaining WAKE_FROM_IDLE alarms. if (removedNextWakeFromIdle.value) { - mNextWakeFromIdle = null; - mAlarmStore.recalculateAlarmDeliveries(alarm -> { + mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm(); + mAlarmStore.updateAlarmDeliveries(alarm -> { if (alarm != mPendingIdleUntil) { return false; } - restoreAlarmLocked(alarm, mInjector.getElapsedRealtime()); return adjustIdleUntilTime(alarm); }); } @@ -3071,20 +3044,6 @@ public class AlarmManagerService extends SystemService { } } - private static final String labelForType(int type) { - switch (type) { - case RTC: - return "RTC"; - case RTC_WAKEUP: - return "RTC_WAKEUP"; - case ELAPSED_REALTIME: - return "ELAPSED"; - case ELAPSED_REALTIME_WAKEUP: - return "ELAPSED_WAKEUP"; - } - return "--unknown--"; - } - private static final void dumpAlarmList(PrintWriter pw, ArrayList list, String prefix, long nowELAPSED, SimpleDateFormat sdf) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, prefix, prefix); @@ -3095,7 +3054,7 @@ public class AlarmManagerService extends SystemService { long nowELAPSED, SimpleDateFormat sdf) { for (int i = list.size() - 1; i >= 0; i--) { final Alarm a = list.get(i); - final String label = labelForType(a.type); + final String label = Alarm.typeToString(a.type); ipw.print(label); ipw.print(" #"); ipw.print(i); @@ -3125,6 +3084,9 @@ public class AlarmManagerService extends SystemService { } final String sourcePackage = alarm.sourcePackage; final int sourceUid = alarm.creatorUid; + if (UserHandle.isCore(sourceUid)) { + return false; + } return (mAppStateTracker != null) && mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage, exemptOnBatterySaver); @@ -3169,11 +3131,7 @@ public class AlarmManagerService extends SystemService { // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE // alarm went off for this app. Reschedule the alarm to be in the // correct time period. - alarm.expectedWhenElapsed = alarm.whenElapsed = minTime; - if (alarm.maxWhenElapsed < minTime) { - alarm.maxWhenElapsed = minTime; - } - alarm.expectedMaxWhenElapsed = alarm.maxWhenElapsed; + alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, minTime); if (RECORD_DEVICE_IDLE_ALARMS) { IdleDispatchEntry ent = new IdleDispatchEntry(); ent.uid = alarm.uid; @@ -3213,12 +3171,11 @@ public class AlarmManagerService extends SystemService { restorePendingWhileIdleAlarmsLocked(); } if (mNextWakeFromIdle == alarm) { - mNextWakeFromIdle = null; - mAlarmStore.recalculateAlarmDeliveries(a -> { + mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm(); + mAlarmStore.updateAlarmDeliveries(a -> { if (a != mPendingIdleUntil) { return false; } - restoreAlarmLocked(a, nowELAPSED); return adjustIdleUntilTime(a); }); } @@ -3228,14 +3185,17 @@ public class AlarmManagerService extends SystemService { if (alarm.repeatInterval > 0) { // this adjustment will be zero if we're late by // less than one full repeat interval - alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval; + alarm.count += (nowELAPSED - alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX)) + / alarm.repeatInterval; // Also schedule its next recurrence final long delta = alarm.count * alarm.repeatInterval; - final long nextElapsed = alarm.expectedWhenElapsed + delta; - setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength, - maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), - alarm.repeatInterval, alarm.operation, null, null, alarm.flags, - alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName); + final long nextElapsed = alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX) + delta; + final long nextMaxElapsed = maxTriggerTime(nowELAPSED, nextElapsed, + alarm.repeatInterval); + setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed, + nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null, + null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid, + alarm.packageName); } if (alarm.wakeup) { @@ -3277,7 +3237,7 @@ public class AlarmManagerService extends SystemService { } } - static int fuzzForDuration(long duration) { + int fuzzForDuration(long duration) { if (duration < 15 * 60 * 1000) { // If the duration until the time is less than 15 minutes, the maximum fuzz // is the duration. @@ -3480,7 +3440,7 @@ public class AlarmManagerService extends SystemService { FrameworkStatsLog.write(FrameworkStatsLog.WALL_CLOCK_TIME_SHIFTED, nowRTC); removeImpl(null, mTimeTickTrigger); removeImpl(mDateChangeSender, null); - reevaluateRtcAlarms(nowELAPSED); + reevaluateRtcAlarms(); mClockReceiver.scheduleTimeTickEvent(); mClockReceiver.scheduleDateChangedEvent(); synchronized (mLock) { diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java index 9fdbb8bbffc7c..7a846b9b82db7 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java @@ -47,6 +47,15 @@ public interface AlarmStore { */ ArrayList remove(Predicate whichAlarms); + /** + * Gets the earliest alarm with the flag {@link android.app.AlarmManager#FLAG_WAKE_FROM_IDLE} + * based on {@link Alarm#getWhenElapsed()}. + * + * @return An alarm object matching the description above or {@code null} if no such alarm was + * found. + */ + Alarm getNextWakeFromIdleAlarm(); + /** * Returns the total number of alarms in this store. */ @@ -71,7 +80,7 @@ public interface AlarmStore { /** * Removes all alarms that are pending delivery at the given time. * - * @param nowElapsed The time at which delivery eligibility is evaluated. + * @param nowElapsed The time at which delivery eligibility is evaluated. * @return The list of alarms pending at the given time. */ ArrayList removePendingAlarms(long nowElapsed); @@ -82,7 +91,7 @@ public interface AlarmStore { * * @return {@code true} if any of the alarm deliveries changed due to this call. */ - boolean recalculateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator); + boolean updateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator); /** * Returns all the alarms in the form of a list. @@ -97,6 +106,7 @@ public interface AlarmStore { * Primary useful for debugging. Can be called from the * {@link android.os.Binder#dump(FileDescriptor PrintWriter, String[]) dump} method of the * caller. + * * @param ipw The {@link IndentingPrintWriter} to write to. * @param nowElapsed the time when the dump is requested in the * {@link SystemClock#elapsedRealtime() @@ -112,7 +122,7 @@ public interface AlarmStore { /** * A functional interface used to update the alarm. Used to describe the update in - * {@link #recalculateAlarmDeliveries(AlarmDeliveryCalculator)} + * {@link #updateAlarmDeliveries(AlarmDeliveryCalculator)} */ @FunctionalInterface interface AlarmDeliveryCalculator { @@ -125,3 +135,4 @@ public interface AlarmStore { boolean updateAlarmDelivery(Alarm a); } } + diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java index 91c0c0579c690..cbfe80bdce249 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java @@ -66,8 +66,8 @@ public class BatchingAlarmStore implements AlarmStore { }; private static final Comparator sIncreasingTimeOrder = (a1, a2) -> { - long when1 = a1.whenElapsed; - long when2 = a2.whenElapsed; + long when1 = a1.getWhenElapsed(); + long when2 = a2.getWhenElapsed(); if (when1 > when2) { return 1; } @@ -99,11 +99,28 @@ public class BatchingAlarmStore implements AlarmStore { } if (!removed.isEmpty()) { mSize -= removed.size(); + // Not needed if only whole batches were removed, but keeping existing behavior. rebatchAllAlarms(); } return removed; } + @Override + public Alarm getNextWakeFromIdleAlarm() { + for (final Batch batch : mAlarmBatches) { + if ((batch.mFlags & AlarmManager.FLAG_WAKE_FROM_IDLE) == 0) { + continue; + } + for (int i = 0; i < batch.size(); i++) { + final Alarm a = batch.get(i); + if ((a.flags & AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) { + return a; + } + } + } + return null; + } + private void rebatchAllAlarms() { final long start = mStatLogger.getTime(); final ArrayList oldBatches = (ArrayList) mAlarmBatches.clone(); @@ -157,7 +174,7 @@ public class BatchingAlarmStore implements AlarmStore { } @Override - public boolean recalculateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator) { + public boolean updateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator) { boolean changed = false; for (final Batch b : mAlarmBatches) { for (int i = 0; i < b.size(); i++) { @@ -204,7 +221,7 @@ public class BatchingAlarmStore implements AlarmStore { private void insertAndBatchAlarm(Alarm alarm) { final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1 - : attemptCoalesce(alarm.whenElapsed, alarm.maxWhenElapsed); + : attemptCoalesce(alarm.getWhenElapsed(), alarm.getMaxWhenElapsed()); if (whichBatch < 0) { addBatch(mAlarmBatches, new Batch(alarm)); @@ -247,8 +264,8 @@ public class BatchingAlarmStore implements AlarmStore { final ArrayList mAlarms = new ArrayList<>(); Batch(Alarm seed) { - mStart = seed.whenElapsed; - mEnd = clampPositive(seed.maxWhenElapsed); + mStart = seed.getWhenElapsed(); + mEnd = clampPositive(seed.getMaxWhenElapsed()); mFlags = seed.flags; mAlarms.add(seed); } @@ -276,12 +293,12 @@ public class BatchingAlarmStore implements AlarmStore { if (DEBUG_BATCH) { Slog.v(TAG, "Adding " + alarm + " to " + this); } - if (alarm.whenElapsed > mStart) { - mStart = alarm.whenElapsed; + if (alarm.getWhenElapsed() > mStart) { + mStart = alarm.getWhenElapsed(); newStart = true; } - if (alarm.maxWhenElapsed < mEnd) { - mEnd = alarm.maxWhenElapsed; + if (alarm.getMaxWhenElapsed() < mEnd) { + mEnd = alarm.getMaxWhenElapsed(); } mFlags |= alarm.flags; @@ -309,11 +326,11 @@ public class BatchingAlarmStore implements AlarmStore { Slog.wtf(TAG, "Removed TIME_TICK alarm"); } } else { - if (alarm.whenElapsed > newStart) { - newStart = alarm.whenElapsed; + if (alarm.getWhenElapsed() > newStart) { + newStart = alarm.getWhenElapsed(); } - if (alarm.maxWhenElapsed < newEnd) { - newEnd = alarm.maxWhenElapsed; + if (alarm.getMaxWhenElapsed() < newEnd) { + newEnd = alarm.getMaxWhenElapsed(); } newFlags |= alarm.flags; i++; 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 d61783ef59d22..a5f0834778633 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -48,10 +48,13 @@ import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_INT import static com.android.server.alarm.AlarmManagerService.IS_WAKEUP_MASK; import static com.android.server.alarm.AlarmManagerService.TIME_CHANGED_MASK; import static com.android.server.alarm.AlarmManagerService.WORKING_INDEX; +import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE; +import static com.android.server.alarm.Constants.TEST_CALLING_UID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; @@ -82,6 +85,7 @@ import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; import android.provider.Settings; +import android.util.IndentingPrintWriter; import android.util.Log; import android.util.SparseArray; @@ -108,6 +112,8 @@ import org.mockito.MockitoSession; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.concurrent.Executor; @@ -116,9 +122,7 @@ import java.util.concurrent.Executor; @RunWith(AndroidJUnit4.class) public class AlarmManagerServiceTest { private static final String TAG = AlarmManagerServiceTest.class.getSimpleName(); - private static final String TEST_CALLING_PACKAGE = "com.android.framework.test-package"; private static final int SYSTEM_UI_UID = 12345; - private static final int TEST_CALLING_UID = 67890; private static final int TEST_CALLING_USER = UserHandle.getUserId(TEST_CALLING_UID); private long mAppStandbyWindow; @@ -350,19 +354,31 @@ public class AlarmManagerServiceTest { } private void setTestAlarm(int type, long triggerTime, PendingIntent operation) { - setTestAlarm(type, triggerTime, operation, 0, TEST_CALLING_UID); + setTestAlarm(type, triggerTime, operation, 0, AlarmManager.FLAG_STANDALONE, + TEST_CALLING_UID); } private void setRepeatingTestAlarm(int type, long firstTrigger, long interval, PendingIntent pi) { - setTestAlarm(type, firstTrigger, pi, interval, TEST_CALLING_UID); + setTestAlarm(type, firstTrigger, pi, interval, AlarmManager.FLAG_STANDALONE, + TEST_CALLING_UID); + } + + private void setIdleUntilAlarm(int type, long triggerTime, PendingIntent pi) { + setTestAlarm(type, triggerTime, pi, 0, AlarmManager.FLAG_IDLE_UNTIL, TEST_CALLING_UID); + } + + private void setWakeFromIdle(int type, long triggerTime, PendingIntent pi) { + // Note: Only alarm clock alarms are allowed to include this flag in the actual service. + // But this is a unit test so we'll only test the flag for granularity and convenience. + setTestAlarm(type, triggerTime, pi, 0, + AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE, TEST_CALLING_UID); } private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval, - int callingUid) { - mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, interval, - operation, null, "test", AlarmManager.FLAG_STANDALONE, null, null, - callingUid, TEST_CALLING_PACKAGE); + int flags, int callingUid) { + mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, interval, operation, null, + "test", flags, null, null, callingUid, TEST_CALLING_PACKAGE); } private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener) { @@ -1002,7 +1018,7 @@ public class AlarmManagerServiceTest { for (int i = 0; i < numAlarms; i++) { int mockUid = UserHandle.getUid(mockUserId, 1234 + i); setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, - getNewMockPendingIntent(mockUid), 0, mockUid); + getNewMockPendingIntent(mockUid), 0, AlarmManager.FLAG_STANDALONE, mockUid); } assertEquals(numAlarms, mService.mAlarmsPerUid.size()); mService.removeUserLocked(mockUserId); @@ -1142,6 +1158,116 @@ public class AlarmManagerServiceTest { } } + @Test + public void singleIdleUntil() { + doReturn(0).when(mService).fuzzForDuration(anyLong()); + + final PendingIntent idleUntilPi6 = getNewMockPendingIntent(); + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, idleUntilPi6); + + assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi6, null)); + assertEquals(mNowElapsedTest + 6, mTestTimer.getElapsed()); + assertEquals(mNowElapsedTest + 6, mService.mPendingIdleUntil.getWhenElapsed()); + + final PendingIntent idleUntilPi2 = getNewMockPendingIntent(); + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, idleUntilPi2); + + // The same mPendingIdleUntil should get updated, even with a different PendingIntent. + assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi2, null)); + assertEquals(mNowElapsedTest + 2, mTestTimer.getElapsed()); + assertEquals(1, mService.mAlarmStore.size()); + + final PendingIntent idleUntilPi10 = getNewMockPendingIntent(); + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 10, idleUntilPi10); + + // The same thing should happen even when the new alarm is in farther in the future. + assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi10, null)); + assertEquals(mNowElapsedTest + 10, mTestTimer.getElapsed()); + assertEquals(1, mService.mAlarmStore.size()); + } + + @Test + public void nextWakeFromIdle() throws Exception { + assertNull(mService.mNextWakeFromIdle); + + final PendingIntent wakeFromIdle6 = getNewMockPendingIntent(); + final long trigger6 = mNowElapsedTest + 6; + setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger6, wakeFromIdle6); + + assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null)); + assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed()); + assertEquals(trigger6, mTestTimer.getElapsed()); + + final PendingIntent wakeFromIdle10 = getNewMockPendingIntent(); + final long trigger10 = mNowElapsedTest + 10; + setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger10, wakeFromIdle10); + + // mNextWakeFromIdle should not get updated. + assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null)); + assertEquals(trigger6, mTestTimer.getElapsed()); + assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed()); + + final PendingIntent wakeFromIdle3 = getNewMockPendingIntent(); + final long trigger3 = mNowElapsedTest + 3; + setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger3, wakeFromIdle3); + + // mNextWakeFromIdle should always reflect the next earliest wake_from_idle alarm. + assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle3, null)); + assertEquals(trigger3, mTestTimer.getElapsed()); + assertEquals(trigger3, mService.mNextWakeFromIdle.getWhenElapsed()); + + mNowElapsedTest = trigger3; + mTestTimer.expire(); + + assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null)); + assertEquals(trigger6, mTestTimer.getElapsed()); + assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed()); + + mService.removeLocked(wakeFromIdle6, null); + + assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle10, null)); + assertEquals(trigger10, mTestTimer.getElapsed()); + assertEquals(trigger10, mService.mNextWakeFromIdle.getWhenElapsed()); + + mService.removeLocked(wakeFromIdle10, null); + assertNull(mService.mNextWakeFromIdle); + } + + @Test + public void idleUntilBeforeWakeFromIdle() { + doReturn(0).when(mService).fuzzForDuration(anyLong()); + + final PendingIntent idleUntilPi = getNewMockPendingIntent(); + final long requestedIdleUntil = mNowElapsedTest + 10; + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, requestedIdleUntil, idleUntilPi); + + assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); + + final PendingIntent wakeFromIdle5 = getNewMockPendingIntent(); + setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, wakeFromIdle5); + assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); + + final PendingIntent wakeFromIdle8 = getNewMockPendingIntent(); + setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, wakeFromIdle8); + assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); + + final PendingIntent wakeFromIdle12 = getNewMockPendingIntent(); + setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 12, wakeFromIdle12); + assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); + + mService.removeLocked(wakeFromIdle5, null); + assertEquals(mNowElapsedTest + 8, mService.mPendingIdleUntil.getWhenElapsed()); + + mService.removeLocked(wakeFromIdle8, null); + assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); + + mService.removeLocked(idleUntilPi, null); + assertNull(mService.mPendingIdleUntil); + + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 15, idleUntilPi); + assertEquals(mNowElapsedTest + 12, mService.mPendingIdleUntil.getWhenElapsed()); + } + @After public void tearDown() { if (mMockingSession != null) { @@ -1149,4 +1275,12 @@ public class AlarmManagerServiceTest { } LocalServices.removeServiceForTest(AlarmManagerInternal.class); } + + private void dumpAllAlarms(String tag, ArrayList alarms) { + System.out.println(tag + ": "); + IndentingPrintWriter ipw = new IndentingPrintWriter(new PrintWriter(System.out)); + AlarmManagerService.dumpAlarmList(ipw, alarms, mNowElapsedTest, + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")); + ipw.close(); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java index 9e43b4ab9b5a8..f0490ce469dd2 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java @@ -16,6 +16,9 @@ package com.android.server.alarm; +import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE; +import static com.android.server.alarm.Constants.TEST_CALLING_UID; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -35,9 +38,6 @@ import java.util.ArrayList; @Presubmit @RunWith(AndroidJUnit4.class) public class AlarmStoreTest { - private static final int TEST_CALLING_UID = 12345; - private static final String TEST_CALLING_PACKAGE = "android.alarm.unit.test"; - private AlarmStore mAlarmStore; @Before @@ -45,22 +45,22 @@ public class AlarmStoreTest { mAlarmStore = new BatchingAlarmStore(null); } - private static Alarm createAlarm(long whenElapsed, long windowLength, PendingIntent mockPi, + private static Alarm createAlarm(long whenElapsed, long windowLength, AlarmManager.AlarmClockInfo alarmClock) { - return createAlarm(AlarmManager.ELAPSED_REALTIME, whenElapsed, windowLength, mockPi, + return createAlarm(AlarmManager.ELAPSED_REALTIME, whenElapsed, windowLength, alarmClock); } private static Alarm createWakeupAlarm(long whenElapsed, long windowLength, - PendingIntent mockPi, AlarmManager.AlarmClockInfo alarmClock) { - return createAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength, mockPi, + AlarmManager.AlarmClockInfo alarmClock) { + return createAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength, alarmClock); } private static Alarm createAlarm(int type, long whenElapsed, long windowLength, - PendingIntent mockPi, AlarmManager.AlarmClockInfo alarmClock) { - return new Alarm(type, whenElapsed, whenElapsed, windowLength, whenElapsed + windowLength, - 0, mockPi, null, null, null, 0, alarmClock, TEST_CALLING_UID, TEST_CALLING_PACKAGE); + AlarmManager.AlarmClockInfo alarmClock) { + return new Alarm(type, whenElapsed, whenElapsed, windowLength, 0, mock(PendingIntent.class), + null, null, null, 0, alarmClock, TEST_CALLING_UID, TEST_CALLING_PACKAGE); } private void addAlarmsToStore(Alarm... alarms) { @@ -71,11 +71,11 @@ public class AlarmStoreTest { @Test public void add() { - final Alarm a1 = createAlarm(1, 0, mock(PendingIntent.class), null); + final Alarm a1 = createAlarm(1, 0, null); mAlarmStore.add(a1); assertEquals(1, mAlarmStore.size()); - final Alarm a2 = createAlarm(2, 0, mock(PendingIntent.class), null); + final Alarm a2 = createAlarm(2, 0, null); mAlarmStore.add(a2); assertEquals(2, mAlarmStore.size()); @@ -86,17 +86,17 @@ public class AlarmStoreTest { @Test public void remove() { - final Alarm a1 = createAlarm(1, 0, mock(PendingIntent.class), null); - final Alarm a2 = createAlarm(2, 0, mock(PendingIntent.class), null); - final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null); + final Alarm a1 = createAlarm(1, 0, null); + final Alarm a2 = createAlarm(2, 0, null); + final Alarm a5 = createAlarm(5, 0, null); addAlarmsToStore(a1, a2, a5); - ArrayList removed = mAlarmStore.remove(a -> (a.whenElapsed < 4)); + ArrayList removed = mAlarmStore.remove(a -> (a.getWhenElapsed() < 4)); assertEquals(2, removed.size()); assertEquals(1, mAlarmStore.size()); assertTrue(removed.contains(a1) && removed.contains(a2)); - final Alarm a8 = createAlarm(8, 0, mock(PendingIntent.class), null); + final Alarm a8 = createAlarm(8, 0, null); addAlarmsToStore(a8, a2, a1); removed = mAlarmStore.remove(unused -> false); @@ -110,10 +110,10 @@ public class AlarmStoreTest { @Test public void removePendingAlarms() { - final Alarm a1_11 = createAlarm(1, 10, mock(PendingIntent.class), null); - final Alarm a2_5 = createAlarm(2, 3, mock(PendingIntent.class), null); - final Alarm a6_9 = createAlarm(6, 3, mock(PendingIntent.class), null); - addAlarmsToStore(a2_5, a6_9, a1_11); + final Alarm a1to11 = createAlarm(1, 10, null); + final Alarm a2to5 = createAlarm(2, 3, null); + final Alarm a6to9 = createAlarm(6, 3, null); + addAlarmsToStore(a2to5, a6to9, a1to11); final ArrayList pendingAt0 = mAlarmStore.removePendingAlarms(0); assertEquals(0, pendingAt0.size()); @@ -121,24 +121,24 @@ public class AlarmStoreTest { final ArrayList pendingAt3 = mAlarmStore.removePendingAlarms(3); assertEquals(2, pendingAt3.size()); - assertTrue(pendingAt3.contains(a1_11) && pendingAt3.contains(a2_5)); + assertTrue(pendingAt3.contains(a1to11) && pendingAt3.contains(a2to5)); assertEquals(1, mAlarmStore.size()); - addAlarmsToStore(a2_5, a1_11); + addAlarmsToStore(a2to5, a1to11); final ArrayList pendingAt7 = mAlarmStore.removePendingAlarms(7); assertEquals(3, pendingAt7.size()); - assertTrue(pendingAt7.contains(a1_11) && pendingAt7.contains(a2_5) && pendingAt7.contains( - a6_9)); + assertTrue(pendingAt7.contains(a1to11) && pendingAt7.contains(a2to5) && pendingAt7.contains( + a6to9)); assertEquals(0, mAlarmStore.size()); } @Test public void getNextWakeupDeliveryTime() { - final Alarm a1_10 = createAlarm(1, 9, mock(PendingIntent.class), null); - final Alarm a3_8_wakeup = createWakeupAlarm(3, 5, mock(PendingIntent.class), null); - final Alarm a6_wakeup = createWakeupAlarm(6, 0, mock(PendingIntent.class), null); - final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null); - addAlarmsToStore(a5, a6_wakeup, a3_8_wakeup, a1_10); + final Alarm a1to10 = createAlarm(1, 9, null); + final Alarm a3to8wakeup = createWakeupAlarm(3, 5, null); + final Alarm a6wakeup = createWakeupAlarm(6, 0, null); + final Alarm a5 = createAlarm(5, 0, null); + addAlarmsToStore(a5, a6wakeup, a3to8wakeup, a1to10); // The wakeup alarms are [6] and [3, 8], hence 6 is the latest time till when we can // defer delivering any wakeup alarm. @@ -155,11 +155,11 @@ public class AlarmStoreTest { @Test public void getNextDeliveryTime() { - final Alarm a1_10 = createAlarm(1, 9, mock(PendingIntent.class), null); - final Alarm a3_8_wakeup = createWakeupAlarm(3, 5, mock(PendingIntent.class), null); - final Alarm a6_wakeup = createWakeupAlarm(6, 0, mock(PendingIntent.class), null); - final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null); - addAlarmsToStore(a5, a6_wakeup, a3_8_wakeup, a1_10); + final Alarm a1to10 = createAlarm(1, 9, null); + final Alarm a3to8wakeup = createWakeupAlarm(3, 5, null); + final Alarm a6wakeup = createWakeupAlarm(6, 0, null); + final Alarm a5 = createAlarm(5, 0, null); + addAlarmsToStore(a5, a6wakeup, a3to8wakeup, a1to10); assertTrue(mAlarmStore.getNextDeliveryTime() <= 5); @@ -168,24 +168,22 @@ public class AlarmStoreTest { } @Test - public void recalculateAlarmDeliveries() { - final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null); - final Alarm a8 = createAlarm(8, 0, mock(PendingIntent.class), null); - final Alarm a10 = createAlarm(10, 0, mock(PendingIntent.class), null); + public void updateAlarmDeliveries() { + final Alarm a5 = createAlarm(5, 0, null); + final Alarm a8 = createAlarm(8, 0, null); + final Alarm a10 = createAlarm(10, 0, null); addAlarmsToStore(a8, a10, a5); assertEquals(5, mAlarmStore.getNextDeliveryTime()); - mAlarmStore.recalculateAlarmDeliveries(a -> { - a.whenElapsed += 3; - a.maxWhenElapsed = a.whenElapsed; + mAlarmStore.updateAlarmDeliveries(a -> { + a.setPolicyElapsed(Alarm.REQUESTER_POLICY_INDEX, a.getWhenElapsed() + 3); return true; }); assertEquals(8, mAlarmStore.getNextDeliveryTime()); - mAlarmStore.recalculateAlarmDeliveries(a -> { - a.whenElapsed = 20 - a.whenElapsed; - a.maxWhenElapsed = a.whenElapsed; + mAlarmStore.updateAlarmDeliveries(a -> { + a.setPolicyElapsed(Alarm.REQUESTER_POLICY_INDEX, 20 - a.getWhenElapsed()); return true; }); assertEquals(7, mAlarmStore.getNextDeliveryTime()); diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java new file mode 100644 index 0000000000000..efcfae38c3d3d --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.alarm; + +import static android.app.AlarmManager.ELAPSED_REALTIME; + +import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX; +import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX; +import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE; +import static com.android.server.alarm.Constants.TEST_CALLING_UID; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import android.app.PendingIntent; +import android.platform.test.annotations.Presubmit; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@RunWith(AndroidJUnit4.class) +public class AlarmTest { + + private Alarm createDefaultAlarm(long requestedElapsed, long windowLength) { + return new Alarm(ELAPSED_REALTIME, 0, requestedElapsed, windowLength, 0, + mock(PendingIntent.class), null, null, null, 0, null, TEST_CALLING_UID, + TEST_CALLING_PACKAGE); + } + + @Test + public void initSetsOnlyRequesterPolicy() { + final Alarm a = createDefaultAlarm(4567, 2); + assertEquals(4567, a.getPolicyElapsed(REQUESTER_POLICY_INDEX)); + assertEquals(0, a.getPolicyElapsed(APP_STANDBY_POLICY_INDEX)); + } + + @Test + public void whenElapsed() { + final Alarm a = createDefaultAlarm(0, 0); + + a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4); + a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10); + assertEquals(10, a.getWhenElapsed()); + + a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 12); + assertEquals(12, a.getWhenElapsed()); + + a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 7); + assertEquals(10, a.getWhenElapsed()); + + a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 2); + assertEquals(7, a.getWhenElapsed()); + + a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 7); + assertEquals(7, a.getWhenElapsed()); + } + + @Test + public void maxWhenElapsed() { + final Alarm a = createDefaultAlarm(10, 12); + assertEquals(22, a.getMaxWhenElapsed()); + + a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 15); + assertEquals(27, a.getMaxWhenElapsed()); + + a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 2); + assertEquals(14, a.getMaxWhenElapsed()); + + a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 5); + assertEquals(14, a.getMaxWhenElapsed()); + + a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 16); + assertEquals(16, a.getMaxWhenElapsed()); + + a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 12); + assertEquals(14, a.getMaxWhenElapsed()); + } + + @Test + public void setPolicyElapsed() { + final Alarm exactAlarm = createDefaultAlarm(10, 0); + + assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4)); + assertTrue(exactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10)); + + assertFalse(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 8)); + assertFalse(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 10)); + assertFalse(exactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 8)); + + assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 7)); + + final Alarm inexactAlarm = createDefaultAlarm(10, 5); + + assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4)); + assertTrue(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10)); + + // whenElapsed won't change, but maxWhenElapsed will. + assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 8)); + assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 10)); + + assertFalse(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 8)); + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java index 6465739f6822f..5bb6a42b26041 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java @@ -45,7 +45,7 @@ public class BackgroundRestrictedAlarmsTest { } uidAlarms.add(new Alarm( removeIt ? RTC : RTC_WAKEUP, - 0, 0, 0, 0, 0, null, null, null, null, 0, null, uid, name)); + 0, 0, 0, 0, null, null, null, null, 0, null, uid, name)); return all; } diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/Constants.java b/services/tests/mockingservicestests/src/com/android/server/alarm/Constants.java new file mode 100644 index 0000000000000..2552db8a310ac --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/Constants.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.alarm; + +public interface Constants { + String TEST_CALLING_PACKAGE = "com.android.framework.test-package"; + int TEST_CALLING_UID = 67890; +}