Loading apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +40 −2 Original line number Diff line number Diff line Loading @@ -66,6 +66,23 @@ class Alarm { */ public static final int BATTERY_SAVER_POLICY_INDEX = 3; /** * Reason to use for inexact alarms. */ static final int EXACT_ALLOW_REASON_NOT_APPLICABLE = -1; /** * Caller had SCHEDULE_EXACT_ALARM permission. */ static final int EXACT_ALLOW_REASON_PERMISSION = 0; /** * Caller was in the power allow-list. */ static final int EXACT_ALLOW_REASON_ALLOW_LIST = 1; /** * Change wasn't enable for the caller due to compat reasons. */ static final int EXACT_ALLOW_REASON_COMPAT = 2; public final int type; /** * The original trigger time supplied by the caller. This can be in the elapsed or rtc time base Loading @@ -92,13 +109,15 @@ class Alarm { /** The ultimate delivery time to be used for this alarm */ private long mWhenElapsed; private long mMaxWhenElapsed; public int mExactAllowReason; public AlarmManagerService.PriorityClass priorityClass; /** Broadcast options to use when delivering this alarm */ public Bundle mIdleOptions; 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, Bundle idleOptions) { AlarmManager.AlarmClockInfo info, int uid, String pkgName, Bundle idleOptions, int exactAllowReason) { this.type = type; origWhen = when; wakeup = type == AlarmManager.ELAPSED_REALTIME_WAKEUP Loading @@ -119,6 +138,7 @@ class Alarm { this.uid = uid; packageName = pkgName; mIdleOptions = idleOptions; mExactAllowReason = exactAllowReason; sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName; creatorUid = (operation != null) ? operation.getCreatorUid() : this.uid; } Loading Loading @@ -216,7 +236,6 @@ class Alarm { sb.append(type); sb.append(" origWhen "); sb.append(origWhen); sb.append(" "); sb.append(" whenElapsed "); sb.append(getWhenElapsed()); sb.append(" "); Loading @@ -240,6 +259,21 @@ class Alarm { } } private static String exactReasonToString(int reason) { switch (reason) { case EXACT_ALLOW_REASON_ALLOW_LIST: return "allow-listed"; case EXACT_ALLOW_REASON_COMPAT: return "compat"; case EXACT_ALLOW_REASON_PERMISSION: return "permission"; case EXACT_ALLOW_REASON_NOT_APPLICABLE: return "N/A"; default: return "--unknown--"; } } public static String typeToString(int type) { switch (type) { case RTC: Loading Loading @@ -270,6 +304,10 @@ class Alarm { } ipw.print(" window="); TimeUtils.formatDuration(windowLength, ipw); if (mExactAllowReason != EXACT_ALLOW_REASON_NOT_APPLICABLE) { ipw.print(" exactAllowReason="); ipw.print(exactReasonToString(mExactAllowReason)); } ipw.print(" repeatInterval="); ipw.print(repeatInterval); ipw.print(" count="); Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +41 −17 Original line number Diff line number Diff line Loading @@ -38,6 +38,10 @@ 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.BATTERY_SAVER_POLICY_INDEX; import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION; import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX; import android.Manifest; Loading Loading @@ -223,6 +227,7 @@ public class AlarmManagerService extends SystemService { private final Injector mInjector; int mBroadcastRefCount = 0; MetricsHelper mMetricsHelper; PowerManager.WakeLock mWakeLock; SparseIntArray mAlarmsPerUid = new SparseIntArray(); ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>(); Loading Loading @@ -1221,7 +1226,7 @@ public class AlarmManagerService extends SystemService { 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, null); alarm.packageName, null, EXACT_ALLOW_REASON_NOT_APPLICABLE); // Kernel alarms will be rescheduled as needed in setImplLocked } } Loading Loading @@ -1442,6 +1447,7 @@ public class AlarmManagerService extends SystemService { @Override public void onStart() { mInjector.init(); mMetricsHelper = new MetricsHelper(getContext()); mListenerDeathRecipient = new IBinder.DeathRecipient() { @Override Loading Loading @@ -1584,6 +1590,7 @@ public class AlarmManagerService extends SystemService { }); } catch (RemoteException e) { } mMetricsHelper.registerPuller(mAlarmStore); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class); Loading Loading @@ -1691,7 +1698,7 @@ public class AlarmManagerService extends SystemService { void setImpl(int type, long triggerAtTime, long windowLength, long interval, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage, Bundle idleOptions) { int callingUid, String callingPackage, Bundle idleOptions, int exactAllowReason) { if ((operation == null && directReceiver == null) || (operation != null && directReceiver != null)) { Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver"); Loading Loading @@ -1788,7 +1795,7 @@ public class AlarmManagerService extends SystemService { } setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation, directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, callingPackage, idleOptions); callingPackage, idleOptions, exactAllowReason); } } Loading @@ -1796,10 +1803,10 @@ public class AlarmManagerService extends SystemService { long interval, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage, Bundle idleOptions) { Bundle idleOptions, int exactAllowReason) { final Alarm a = new Alarm(type, when, whenElapsed, windowLength, interval, operation, directReceiver, listenerTag, workSource, flags, alarmClock, callingUid, callingPackage, idleOptions); callingUid, callingPackage, idleOptions, exactAllowReason); if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) { Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a + " -- package not allowed to start"); Loading @@ -1808,6 +1815,7 @@ public class AlarmManagerService extends SystemService { removeLocked(operation, directReceiver); incrementAlarmCount(a.uid); setImplLocked(a); MetricsHelper.pushAlarmScheduled(a); } /** Loading Loading @@ -2220,6 +2228,8 @@ public class AlarmManagerService extends SystemService { // Make sure the caller is allowed to use the requested kind of alarm, and also // decide what quota and broadcast options to use. boolean allowListed = false; // For logging the reason. boolean changeDisabled = false; // For logging the reason. Bundle idleOptions = null; if ((flags & FLAG_PRIORITIZE) != 0) { getContext().enforcePermission( Loading @@ -2236,6 +2246,7 @@ public class AlarmManagerService extends SystemService { lowerQuota = !exact; idleOptions = exact ? mOptsWithFgs.toBundle() : mOptsWithoutFgs.toBundle(); } else { changeDisabled = true; needsPermission = false; lowerQuota = allowWhileIdle; idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null; Loading @@ -2250,6 +2261,8 @@ public class AlarmManagerService extends SystemService { } else { Slog.wtf(TAG, errorMessage); } } else { allowListed = true; } // If the app is on the full system power allow-list (not except-idle), or we're // in a soft failure mode, we still allow the alarms. Loading @@ -2263,15 +2276,25 @@ public class AlarmManagerService extends SystemService { flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT; } } // If this is an exact time alarm, then it can't be batched with other alarms. final int exactAllowReason; if (exact) { // If this is an exact time alarm, then it can't be batched with other alarms. flags |= AlarmManager.FLAG_STANDALONE; if (changeDisabled) { exactAllowReason = EXACT_ALLOW_REASON_COMPAT; } else if (allowListed) { exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST; } else { exactAllowReason = EXACT_ALLOW_REASON_PERMISSION; } } else { exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE; } setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, callingPackage, idleOptions); idleOptions, exactAllowReason); } @Override Loading Loading @@ -3501,8 +3524,8 @@ public class AlarmManagerService extends SystemService { private static native int setKernelTimezone(long nativeData, int minuteswest); private static native long getNextAlarm(long nativeData, int type); boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) { boolean hasWakeup = false; int triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) { int wakeUps = 0; final ArrayList<Alarm> pendingAlarms = mAlarmStore.removePendingAlarms(nowELAPSED); for (final Alarm alarm : pendingAlarms) { if (isBackgroundRestricted(alarm)) { Loading Loading @@ -3559,11 +3582,11 @@ public class AlarmManagerService extends SystemService { 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, null); alarm.packageName, null, EXACT_ALLOW_REASON_NOT_APPLICABLE); } if (alarm.wakeup) { hasWakeup = true; wakeUps++; } // We removed an alarm clock. Let the caller recompute the next alarm clock. Loading @@ -3584,7 +3607,7 @@ public class AlarmManagerService extends SystemService { } } return hasWakeup; return wakeUps; } long currentNonWakeupFuzzLocked(long nowELAPSED) { Loading Loading @@ -3843,8 +3866,8 @@ public class AlarmManagerService extends SystemService { } mLastTrigger = nowELAPSED; boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED); if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) { final int wakeUps = triggerAlarmsLocked(triggerList, nowELAPSED); if (wakeUps == 0 && checkAllowNonWakeupDelayLocked(nowELAPSED)) { // if there are no wakeup alarms and the screen is off, we can // delay what we have so far until the future. if (mPendingNonWakeupAlarms.size() == 0) { Loading Loading @@ -3896,6 +3919,7 @@ public class AlarmManagerService extends SystemService { reorderAlarmsBasedOnStandbyBuckets(triggerPackages); rescheduleKernelAlarmsLocked(); updateNextAlarmClockLocked(); MetricsHelper.pushAlarmBatchDelivered(triggerList.size(), wakeUps); } } Loading Loading @@ -4126,7 +4150,7 @@ public class AlarmManagerService extends SystemService { setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0, 0, null, mTimeTickTrigger, TIME_TICK_TAG, flags, workSource, null, Process.myUid(), "android", null); Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST); // Finally, remember when we set the tick alarm synchronized (mLock) { Loading @@ -4146,7 +4170,7 @@ public class AlarmManagerService extends SystemService { final WorkSource workSource = null; // Let system take blame for date change events. setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null, AlarmManager.FLAG_STANDALONE, workSource, null, Process.myUid(), "android", null); Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST); } } Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java +5 −1 Original line number Diff line number Diff line Loading @@ -138,6 +138,11 @@ public interface AlarmStore { */ String getName(); /** * Returns the number of alarms that satisfy the given condition. */ int getCount(Predicate<Alarm> condition); /** * A functional interface used to update the alarm. Used to describe the update in * {@link #updateAlarmDeliveries(AlarmDeliveryCalculator)} Loading @@ -153,4 +158,3 @@ public interface AlarmStore { boolean updateAlarmDelivery(Alarm a); } } apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java +18 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.alarm; import static com.android.server.alarm.AlarmManagerService.DEBUG_BATCH; import static com.android.server.alarm.AlarmManagerService.TAG; import static com.android.server.alarm.AlarmManagerService.clampPositive; import static com.android.server.alarm.AlarmManagerService.dumpAlarmList; import static com.android.server.alarm.AlarmManagerService.isTimeTickAlarm; Loading Loading @@ -50,10 +49,12 @@ public class BatchingAlarmStore implements AlarmStore { interface Stats { int REBATCH_ALL_ALARMS = 0; int GET_COUNT = 1; } final StatLogger mStatLogger = new StatLogger(TAG + " stats", new String[]{ "REBATCH_ALL_ALARMS", "GET_COUNT", }); private static final Comparator<Batch> sBatchOrder = Comparator.comparingLong(b -> b.mStart); Loading Loading @@ -219,6 +220,22 @@ public class BatchingAlarmStore implements AlarmStore { return TAG; } @Override public int getCount(Predicate<Alarm> condition) { long start = mStatLogger.getTime(); int count = 0; for (Batch b : mAlarmBatches) { for (int i = 0; i < b.size(); i++) { if (condition.test(b.get(i))) { count++; } } } mStatLogger.logDurationStat(Stats.GET_COUNT, start); return count; } private void insertAndBatchAlarm(Alarm alarm) { final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1 : attemptCoalesce(alarm.getWhenElapsed(), alarm.getMaxWhenElapsed()); Loading apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java +16 −0 Original line number Diff line number Diff line Loading @@ -47,11 +47,13 @@ public class LazyAlarmStore implements AlarmStore { interface Stats { int GET_NEXT_DELIVERY_TIME = 0; int GET_NEXT_WAKEUP_DELIVERY_TIME = 1; int GET_COUNT = 2; } final StatLogger mStatLogger = new StatLogger(TAG + " stats", new String[]{ "GET_NEXT_DELIVERY_TIME", "GET_NEXT_WAKEUP_DELIVERY_TIME", "GET_COUNT", }); // Decreasing time order because it is more efficient to remove from the tail of an array list. Loading Loading @@ -221,4 +223,18 @@ public class LazyAlarmStore implements AlarmStore { public String getName() { return TAG; } @Override public int getCount(Predicate<Alarm> condition) { long start = mStatLogger.getTime(); int count = 0; for (final Alarm a : mAlarms) { if (condition.test(a)) { count++; } } mStatLogger.logDurationStat(Stats.GET_COUNT, start); return count; } } Loading
apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +40 −2 Original line number Diff line number Diff line Loading @@ -66,6 +66,23 @@ class Alarm { */ public static final int BATTERY_SAVER_POLICY_INDEX = 3; /** * Reason to use for inexact alarms. */ static final int EXACT_ALLOW_REASON_NOT_APPLICABLE = -1; /** * Caller had SCHEDULE_EXACT_ALARM permission. */ static final int EXACT_ALLOW_REASON_PERMISSION = 0; /** * Caller was in the power allow-list. */ static final int EXACT_ALLOW_REASON_ALLOW_LIST = 1; /** * Change wasn't enable for the caller due to compat reasons. */ static final int EXACT_ALLOW_REASON_COMPAT = 2; public final int type; /** * The original trigger time supplied by the caller. This can be in the elapsed or rtc time base Loading @@ -92,13 +109,15 @@ class Alarm { /** The ultimate delivery time to be used for this alarm */ private long mWhenElapsed; private long mMaxWhenElapsed; public int mExactAllowReason; public AlarmManagerService.PriorityClass priorityClass; /** Broadcast options to use when delivering this alarm */ public Bundle mIdleOptions; 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, Bundle idleOptions) { AlarmManager.AlarmClockInfo info, int uid, String pkgName, Bundle idleOptions, int exactAllowReason) { this.type = type; origWhen = when; wakeup = type == AlarmManager.ELAPSED_REALTIME_WAKEUP Loading @@ -119,6 +138,7 @@ class Alarm { this.uid = uid; packageName = pkgName; mIdleOptions = idleOptions; mExactAllowReason = exactAllowReason; sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName; creatorUid = (operation != null) ? operation.getCreatorUid() : this.uid; } Loading Loading @@ -216,7 +236,6 @@ class Alarm { sb.append(type); sb.append(" origWhen "); sb.append(origWhen); sb.append(" "); sb.append(" whenElapsed "); sb.append(getWhenElapsed()); sb.append(" "); Loading @@ -240,6 +259,21 @@ class Alarm { } } private static String exactReasonToString(int reason) { switch (reason) { case EXACT_ALLOW_REASON_ALLOW_LIST: return "allow-listed"; case EXACT_ALLOW_REASON_COMPAT: return "compat"; case EXACT_ALLOW_REASON_PERMISSION: return "permission"; case EXACT_ALLOW_REASON_NOT_APPLICABLE: return "N/A"; default: return "--unknown--"; } } public static String typeToString(int type) { switch (type) { case RTC: Loading Loading @@ -270,6 +304,10 @@ class Alarm { } ipw.print(" window="); TimeUtils.formatDuration(windowLength, ipw); if (mExactAllowReason != EXACT_ALLOW_REASON_NOT_APPLICABLE) { ipw.print(" exactAllowReason="); ipw.print(exactReasonToString(mExactAllowReason)); } ipw.print(" repeatInterval="); ipw.print(repeatInterval); ipw.print(" count="); Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +41 −17 Original line number Diff line number Diff line Loading @@ -38,6 +38,10 @@ 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.BATTERY_SAVER_POLICY_INDEX; import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION; import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX; import android.Manifest; Loading Loading @@ -223,6 +227,7 @@ public class AlarmManagerService extends SystemService { private final Injector mInjector; int mBroadcastRefCount = 0; MetricsHelper mMetricsHelper; PowerManager.WakeLock mWakeLock; SparseIntArray mAlarmsPerUid = new SparseIntArray(); ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>(); Loading Loading @@ -1221,7 +1226,7 @@ public class AlarmManagerService extends SystemService { 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, null); alarm.packageName, null, EXACT_ALLOW_REASON_NOT_APPLICABLE); // Kernel alarms will be rescheduled as needed in setImplLocked } } Loading Loading @@ -1442,6 +1447,7 @@ public class AlarmManagerService extends SystemService { @Override public void onStart() { mInjector.init(); mMetricsHelper = new MetricsHelper(getContext()); mListenerDeathRecipient = new IBinder.DeathRecipient() { @Override Loading Loading @@ -1584,6 +1590,7 @@ public class AlarmManagerService extends SystemService { }); } catch (RemoteException e) { } mMetricsHelper.registerPuller(mAlarmStore); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class); Loading Loading @@ -1691,7 +1698,7 @@ public class AlarmManagerService extends SystemService { void setImpl(int type, long triggerAtTime, long windowLength, long interval, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage, Bundle idleOptions) { int callingUid, String callingPackage, Bundle idleOptions, int exactAllowReason) { if ((operation == null && directReceiver == null) || (operation != null && directReceiver != null)) { Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver"); Loading Loading @@ -1788,7 +1795,7 @@ public class AlarmManagerService extends SystemService { } setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation, directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, callingPackage, idleOptions); callingPackage, idleOptions, exactAllowReason); } } Loading @@ -1796,10 +1803,10 @@ public class AlarmManagerService extends SystemService { long interval, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage, Bundle idleOptions) { Bundle idleOptions, int exactAllowReason) { final Alarm a = new Alarm(type, when, whenElapsed, windowLength, interval, operation, directReceiver, listenerTag, workSource, flags, alarmClock, callingUid, callingPackage, idleOptions); callingUid, callingPackage, idleOptions, exactAllowReason); if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) { Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a + " -- package not allowed to start"); Loading @@ -1808,6 +1815,7 @@ public class AlarmManagerService extends SystemService { removeLocked(operation, directReceiver); incrementAlarmCount(a.uid); setImplLocked(a); MetricsHelper.pushAlarmScheduled(a); } /** Loading Loading @@ -2220,6 +2228,8 @@ public class AlarmManagerService extends SystemService { // Make sure the caller is allowed to use the requested kind of alarm, and also // decide what quota and broadcast options to use. boolean allowListed = false; // For logging the reason. boolean changeDisabled = false; // For logging the reason. Bundle idleOptions = null; if ((flags & FLAG_PRIORITIZE) != 0) { getContext().enforcePermission( Loading @@ -2236,6 +2246,7 @@ public class AlarmManagerService extends SystemService { lowerQuota = !exact; idleOptions = exact ? mOptsWithFgs.toBundle() : mOptsWithoutFgs.toBundle(); } else { changeDisabled = true; needsPermission = false; lowerQuota = allowWhileIdle; idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null; Loading @@ -2250,6 +2261,8 @@ public class AlarmManagerService extends SystemService { } else { Slog.wtf(TAG, errorMessage); } } else { allowListed = true; } // If the app is on the full system power allow-list (not except-idle), or we're // in a soft failure mode, we still allow the alarms. Loading @@ -2263,15 +2276,25 @@ public class AlarmManagerService extends SystemService { flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT; } } // If this is an exact time alarm, then it can't be batched with other alarms. final int exactAllowReason; if (exact) { // If this is an exact time alarm, then it can't be batched with other alarms. flags |= AlarmManager.FLAG_STANDALONE; if (changeDisabled) { exactAllowReason = EXACT_ALLOW_REASON_COMPAT; } else if (allowListed) { exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST; } else { exactAllowReason = EXACT_ALLOW_REASON_PERMISSION; } } else { exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE; } setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, callingPackage, idleOptions); idleOptions, exactAllowReason); } @Override Loading Loading @@ -3501,8 +3524,8 @@ public class AlarmManagerService extends SystemService { private static native int setKernelTimezone(long nativeData, int minuteswest); private static native long getNextAlarm(long nativeData, int type); boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) { boolean hasWakeup = false; int triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) { int wakeUps = 0; final ArrayList<Alarm> pendingAlarms = mAlarmStore.removePendingAlarms(nowELAPSED); for (final Alarm alarm : pendingAlarms) { if (isBackgroundRestricted(alarm)) { Loading Loading @@ -3559,11 +3582,11 @@ public class AlarmManagerService extends SystemService { 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, null); alarm.packageName, null, EXACT_ALLOW_REASON_NOT_APPLICABLE); } if (alarm.wakeup) { hasWakeup = true; wakeUps++; } // We removed an alarm clock. Let the caller recompute the next alarm clock. Loading @@ -3584,7 +3607,7 @@ public class AlarmManagerService extends SystemService { } } return hasWakeup; return wakeUps; } long currentNonWakeupFuzzLocked(long nowELAPSED) { Loading Loading @@ -3843,8 +3866,8 @@ public class AlarmManagerService extends SystemService { } mLastTrigger = nowELAPSED; boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED); if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) { final int wakeUps = triggerAlarmsLocked(triggerList, nowELAPSED); if (wakeUps == 0 && checkAllowNonWakeupDelayLocked(nowELAPSED)) { // if there are no wakeup alarms and the screen is off, we can // delay what we have so far until the future. if (mPendingNonWakeupAlarms.size() == 0) { Loading Loading @@ -3896,6 +3919,7 @@ public class AlarmManagerService extends SystemService { reorderAlarmsBasedOnStandbyBuckets(triggerPackages); rescheduleKernelAlarmsLocked(); updateNextAlarmClockLocked(); MetricsHelper.pushAlarmBatchDelivered(triggerList.size(), wakeUps); } } Loading Loading @@ -4126,7 +4150,7 @@ public class AlarmManagerService extends SystemService { setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0, 0, null, mTimeTickTrigger, TIME_TICK_TAG, flags, workSource, null, Process.myUid(), "android", null); Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST); // Finally, remember when we set the tick alarm synchronized (mLock) { Loading @@ -4146,7 +4170,7 @@ public class AlarmManagerService extends SystemService { final WorkSource workSource = null; // Let system take blame for date change events. setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null, AlarmManager.FLAG_STANDALONE, workSource, null, Process.myUid(), "android", null); Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST); } } Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java +5 −1 Original line number Diff line number Diff line Loading @@ -138,6 +138,11 @@ public interface AlarmStore { */ String getName(); /** * Returns the number of alarms that satisfy the given condition. */ int getCount(Predicate<Alarm> condition); /** * A functional interface used to update the alarm. Used to describe the update in * {@link #updateAlarmDeliveries(AlarmDeliveryCalculator)} Loading @@ -153,4 +158,3 @@ public interface AlarmStore { boolean updateAlarmDelivery(Alarm a); } }
apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java +18 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.alarm; import static com.android.server.alarm.AlarmManagerService.DEBUG_BATCH; import static com.android.server.alarm.AlarmManagerService.TAG; import static com.android.server.alarm.AlarmManagerService.clampPositive; import static com.android.server.alarm.AlarmManagerService.dumpAlarmList; import static com.android.server.alarm.AlarmManagerService.isTimeTickAlarm; Loading Loading @@ -50,10 +49,12 @@ public class BatchingAlarmStore implements AlarmStore { interface Stats { int REBATCH_ALL_ALARMS = 0; int GET_COUNT = 1; } final StatLogger mStatLogger = new StatLogger(TAG + " stats", new String[]{ "REBATCH_ALL_ALARMS", "GET_COUNT", }); private static final Comparator<Batch> sBatchOrder = Comparator.comparingLong(b -> b.mStart); Loading Loading @@ -219,6 +220,22 @@ public class BatchingAlarmStore implements AlarmStore { return TAG; } @Override public int getCount(Predicate<Alarm> condition) { long start = mStatLogger.getTime(); int count = 0; for (Batch b : mAlarmBatches) { for (int i = 0; i < b.size(); i++) { if (condition.test(b.get(i))) { count++; } } } mStatLogger.logDurationStat(Stats.GET_COUNT, start); return count; } private void insertAndBatchAlarm(Alarm alarm) { final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1 : attemptCoalesce(alarm.getWhenElapsed(), alarm.getMaxWhenElapsed()); Loading
apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java +16 −0 Original line number Diff line number Diff line Loading @@ -47,11 +47,13 @@ public class LazyAlarmStore implements AlarmStore { interface Stats { int GET_NEXT_DELIVERY_TIME = 0; int GET_NEXT_WAKEUP_DELIVERY_TIME = 1; int GET_COUNT = 2; } final StatLogger mStatLogger = new StatLogger(TAG + " stats", new String[]{ "GET_NEXT_DELIVERY_TIME", "GET_NEXT_WAKEUP_DELIVERY_TIME", "GET_COUNT", }); // Decreasing time order because it is more efficient to remove from the tail of an array list. Loading Loading @@ -221,4 +223,18 @@ public class LazyAlarmStore implements AlarmStore { public String getName() { return TAG; } @Override public int getCount(Predicate<Alarm> condition) { long start = mStatLogger.getTime(); int count = 0; for (final Alarm a : mAlarms) { if (condition.test(a)) { count++; } } mStatLogger.logDurationStat(Stats.GET_COUNT, start); return count; } }