Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae9ea5f3 authored by Kweku Adams's avatar Kweku Adams
Browse files

Add a way to disable non-wakeup alarm deferral.

AlarmManager normally delays non-wakeup alarms when the screen is off.
However, tests that depend on components that want to use non-wakeup
alarms while the screen is off will be flaky with this deferral. Make it
possible to disable the deferral for tests. We may also decide to
disable this behavior altogether, so use DeviceConfig to allow
experimentation.

Also fix long comparison overflow issue in AlarmQueue.

Bug: 245987711
Test: atest CtsJobSchedulerTestCases:FlexibilityConstraintTest
Test: atest FrameworksMockingServicesTests:AlarmQueueTest
Change-Id: I35f1299d551eb7099adfecd13449f53fef88de02
parent 1143a298
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -676,6 +676,9 @@ public class AlarmManagerService extends SystemService {
        private static final String KEY_TIME_TICK_ALLOWED_WHILE_IDLE =
                "time_tick_allowed_while_idle";

        private static final String KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF =
                "delay_nonwakeup_alarms_while_screen_off";

        @VisibleForTesting
        static final String KEY_ALLOW_WHILE_IDLE_QUOTA = "allow_while_idle_quota";

@@ -743,6 +746,8 @@ public class AlarmManagerService extends SystemService {

        private static final int DEFAULT_TEMPORARY_QUOTA_BUMP = 0;

        private static final boolean DEFAULT_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF = true;

        // Minimum futurity of a new alarm
        public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;

@@ -835,6 +840,9 @@ public class AlarmManagerService extends SystemService {
         */
        public int TEMPORARY_QUOTA_BUMP = DEFAULT_TEMPORARY_QUOTA_BUMP;

        public boolean DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF =
                DEFAULT_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF;

        private long mLastAllowWhileIdleWhitelistDuration = -1;
        private int mVersion = 0;

@@ -1011,6 +1019,11 @@ public class AlarmManagerService extends SystemService {
                            TEMPORARY_QUOTA_BUMP = properties.getInt(KEY_TEMPORARY_QUOTA_BUMP,
                                    DEFAULT_TEMPORARY_QUOTA_BUMP);
                            break;
                        case KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF:
                            DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF = properties.getBoolean(
                                    KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF,
                                    DEFAULT_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF);
                            break;
                        default:
                            if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
                                // The quotas need to be updated in order, so we can't just rely
@@ -1249,6 +1262,10 @@ public class AlarmManagerService extends SystemService {
            pw.print(KEY_TEMPORARY_QUOTA_BUMP, TEMPORARY_QUOTA_BUMP);
            pw.println();

            pw.print(KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF,
                    DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF);
            pw.println();

            pw.decreaseIndent();
        }

@@ -4360,7 +4377,11 @@ public class AlarmManagerService extends SystemService {
        }
    }

    @GuardedBy("mLock")
    boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
        if (!mConstants.DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF) {
            return false;
        }
        if (mInteractive) {
            return false;
        }
+1 −1
Original line number Diff line number Diff line
@@ -644,7 +644,7 @@ public final class FlexibilityController extends StateController {
        static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE =
                FC_CONFIG_PREFIX + "fallback_flexibility_deadline_ms";
        static final String KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS =
                FC_CONFIG_PREFIX + "min_alarm_time_flexibility_ms";
                FC_CONFIG_PREFIX + "min_time_between_flexibility_alarms_ms";
        static final String KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS =
                FC_CONFIG_PREFIX + "percents_to_drop_num_flexible_constraints";
        static final String KEY_MAX_RESCHEDULED_DEADLINE_MS =
+10 −2
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.function.Predicate;

@@ -52,6 +53,11 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
    private static final boolean DEBUG = false;

    private static final long NOT_SCHEDULED = -1;
    /**
     * The threshold used to consider a new trigger time to be significantly different from the
     * currently used trigger time.
     */
    private static final long SIGNIFICANT_TRIGGER_TIME_CHANGE_THRESHOLD_MS = MINUTE_IN_MILLIS;

    /**
     * Internal priority queue for each key's alarm, ordered by the time the alarm should go off.
@@ -59,7 +65,7 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
     */
    private static class AlarmPriorityQueue<Q> extends PriorityQueue<Pair<Q, Long>> {
        AlarmPriorityQueue() {
            super(1, (o1, o2) -> (int) (o1.second - o2.second));
            super(1, Comparator.comparingLong(o -> o.second));
        }

        /**
@@ -306,8 +312,10 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
        // earlier but not significantly so, then we essentially delay the check for some
        // apps by up to a minute.
        // 3. The alarm is after the current alarm.
        final long timeShiftThresholdMs =
                Math.min(SIGNIFICANT_TRIGGER_TIME_CHANGE_THRESHOLD_MS, mMinTimeBetweenAlarmsMs);
        if (mTriggerTimeElapsed == NOT_SCHEDULED
                || nextTriggerTimeElapsed < mTriggerTimeElapsed - MINUTE_IN_MILLIS
                || nextTriggerTimeElapsed < mTriggerTimeElapsed - timeShiftThresholdMs
                || mTriggerTimeElapsed < nextTriggerTimeElapsed) {
            if (DEBUG) {
                Slog.d(TAG, "Scheduling alarm at " + nextTriggerTimeElapsed
+21 −0
Original line number Diff line number Diff line
@@ -155,6 +155,27 @@ public class AlarmQueueTest {
                anyInt(), eq(nowElapsed + HOUR_IN_MILLIS), eq(ALARM_TAG), any(), any());
    }

    @Test
    public void testAddingLargeAlarmTimes() {
        final AlarmQueue<String> alarmQueue = createAlarmQueue(true, 0);
        final long nowElapsed = mInjector.getElapsedRealtime();

        InOrder inOrder = inOrder(mAlarmManager);

        alarmQueue.addAlarm("com.android.test.1", Long.MAX_VALUE - 5);
        inOrder.verify(mAlarmManager, timeout(1000).times(1))
                .setExact(anyInt(), eq(Long.MAX_VALUE - 5), eq(ALARM_TAG), any(), any());
        alarmQueue.addAlarm("com.android.test.2", Long.MAX_VALUE - 4);
        inOrder.verify(mAlarmManager, never())
                .setExact(anyInt(), anyLong(), eq(ALARM_TAG), any(), any());
        alarmQueue.addAlarm("com.android.test.3", nowElapsed + 5);
        inOrder.verify(mAlarmManager, timeout(1000).times(1))
                .setExact(anyInt(), eq(nowElapsed + 5), eq(ALARM_TAG), any(), any());
        alarmQueue.addAlarm("com.android.test.4", nowElapsed + 6);
        inOrder.verify(mAlarmManager, never())
                .setExact(anyInt(), anyLong(), eq(ALARM_TAG), any(), any());
    }

    /**
     * Verify that updating the alarm time for a key will result in the AlarmManager alarm changing,
     * if needed.