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

Commit f8ea12bd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Adding device-idle policy time to alarms"

parents d7c538d5 87f47ac1
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import android.util.IndentingPrintWriter;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.VisibleForTesting;

import java.text.SimpleDateFormat;
import java.util.Date;

@@ -39,17 +41,23 @@ import java.util.Date;
 * expires. The timer will wake up the device if the alarm is a "wakeup" alarm.
 */
class Alarm {
    private static final int NUM_POLICIES = 2;
    @VisibleForTesting
    public static final int NUM_POLICIES = 3;
    /**
     * Index used to store the time the alarm was requested to expire. To be used with
     * {@link #setPolicyElapsed(int, long)}
     * {@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)}
     * To be used with {@link #setPolicyElapsed(int, long)}.
     */
    public static final int APP_STANDBY_POLICY_INDEX = 1;
    /**
     * Index used to store the earliest time the alarm can expire based on the device's doze policy.
     * To be used with {@link #setPolicyElapsed(int, long)}.
     */
    public static final int DEVICE_IDLE_POLICY_INDEX = 2;

    public final int type;
    /**
@@ -128,10 +136,18 @@ class Alarm {
     * @param policyIndex The index of the policy. One of [{@link #REQUESTER_POLICY_INDEX},
     *                    {@link #APP_STANDBY_POLICY_INDEX}].
     */
    public long getPolicyElapsed(int policyIndex) {
    @VisibleForTesting
    long getPolicyElapsed(int policyIndex) {
        return mPolicyWhenElapsed[policyIndex];
    }

    /**
     * @return the time this alarm was requested to go off in the elapsed time base.
     */
    public long getRequestedElapsed() {
        return mPolicyWhenElapsed[REQUESTER_POLICY_INDEX];
    }

    /**
     * Get the earliest time that this alarm should be delivered to the requesting app.
     */
@@ -205,8 +221,10 @@ class Alarm {
                return "requester";
            case APP_STANDBY_POLICY_INDEX:
                return "app_standby";
            case DEVICE_IDLE_POLICY_INDEX:
                return "device_idle";
            default:
                return "unknown";
                return "--unknown--";
        }
    }

+140 −175

File changed.

Preview size limit exceeded, changes collapsed.

+156 −50
Original line number Diff line number Diff line
@@ -17,8 +17,14 @@ 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.FLAG_ALLOW_WHILE_IDLE;
import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
import static android.app.AlarmManager.FLAG_IDLE_UNTIL;
import static android.app.AlarmManager.FLAG_STANDALONE;
import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE;
import static android.app.AlarmManager.RTC;
import static android.app.AlarmManager.RTC_WAKEUP;
import static android.app.AlarmManager.WINDOW_EXACT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
@@ -66,7 +72,6 @@ import static org.mockito.Mockito.atLeastOnce;

import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.app.IActivityManager;
import android.app.IAlarmCompleteListener;
import android.app.IAlarmListener;
@@ -85,7 +90,6 @@ 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;

@@ -112,8 +116,6 @@ 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;
@@ -354,48 +356,51 @@ public class AlarmManagerServiceTest {
    }

    private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
        setTestAlarm(type, triggerTime, operation, 0, AlarmManager.FLAG_STANDALONE,
                TEST_CALLING_UID);
        setTestAlarm(type, triggerTime, operation, 0, FLAG_STANDALONE, TEST_CALLING_UID);
    }

    private void setRepeatingTestAlarm(int type, long firstTrigger, long interval,
            PendingIntent pi) {
        setTestAlarm(type, firstTrigger, pi, interval, AlarmManager.FLAG_STANDALONE,
                TEST_CALLING_UID);
        setTestAlarm(type, firstTrigger, pi, interval, 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);
        setTestAlarm(type, triggerTime, pi, 0, 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);
        setTestAlarm(type, triggerTime, pi, 0, FLAG_WAKE_FROM_IDLE | FLAG_STANDALONE,
                TEST_CALLING_UID);
    }

    private void setAllowWhileIdleAlarm(int type, long triggerTime, PendingIntent pi,
            boolean unrestricted) {
        final int flags = unrestricted ? FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED : FLAG_ALLOW_WHILE_IDLE;
        setTestAlarm(type, triggerTime, pi, 0, flags, TEST_CALLING_UID);
    }

    private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval,
            int flags, int callingUid) {
        mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, interval, operation, null,
                "test", flags, null, null, callingUid, TEST_CALLING_PACKAGE);
        mService.setImpl(type, triggerTime, WINDOW_EXACT, interval, operation, null, "test", flags,
                null, null, callingUid, TEST_CALLING_PACKAGE);
    }

    private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener) {
        mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, 0,
                null, listener, "test", AlarmManager.FLAG_STANDALONE, null, null,
                TEST_CALLING_UID, TEST_CALLING_PACKAGE);
        mService.setImpl(type, triggerTime, WINDOW_EXACT, 0, null, listener, "test",
                FLAG_STANDALONE, null, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
    }


    private PendingIntent getNewMockPendingIntent() {
        return getNewMockPendingIntent(TEST_CALLING_UID);
        return getNewMockPendingIntent(TEST_CALLING_UID, TEST_CALLING_PACKAGE);
    }

    private PendingIntent getNewMockPendingIntent(int mockUid) {
    private PendingIntent getNewMockPendingIntent(int creatorUid, String creatorPackage) {
        final PendingIntent mockPi = mock(PendingIntent.class, Answers.RETURNS_DEEP_STUBS);
        when(mockPi.getCreatorUid()).thenReturn(mockUid);
        when(mockPi.getCreatorPackage()).thenReturn(TEST_CALLING_PACKAGE);
        when(mockPi.getCreatorUid()).thenReturn(creatorUid);
        when(mockPi.getCreatorPackage()).thenReturn(creatorPackage);
        return mockPi;
    }

@@ -865,7 +870,7 @@ public class AlarmManagerServiceTest {
    public void alarmCountKeyedOnCallingUid() {
        final int mockCreatorUid = 431412;
        setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 5,
                getNewMockPendingIntent(mockCreatorUid));
                getNewMockPendingIntent(mockCreatorUid, TEST_CALLING_PACKAGE));
        assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
        assertEquals(-1, mService.mAlarmsPerUid.get(mockCreatorUid, -1));
    }
@@ -1018,33 +1023,14 @@ 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, AlarmManager.FLAG_STANDALONE, mockUid);
                    getNewMockPendingIntent(mockUid, TEST_CALLING_PACKAGE), 0, FLAG_STANDALONE,
                    mockUid);
        }
        assertEquals(numAlarms, mService.mAlarmsPerUid.size());
        mService.removeUserLocked(mockUserId);
        assertEquals(0, mService.mAlarmsPerUid.size());
    }

    @Test
    public void alarmCountOnRemoveFromPendingWhileIdle() {
        mService.mPendingIdleUntil = mock(Alarm.class);
        final int numAlarms = 15;
        final PendingIntent[] pis = new PendingIntent[numAlarms];
        for (int i = 0; i < numAlarms; i++) {
            pis[i] = getNewMockPendingIntent();
            setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]);
        }
        assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
        assertEquals(numAlarms, mService.mPendingWhileIdleAlarms.size());
        final int toRemove = 8;
        for (int i = 0; i < toRemove; i++) {
            mService.removeLocked(pis[i], null);
            assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
        }
        mService.removeLocked(TEST_CALLING_UID);
        assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
    }

    @Test
    public void alarmCountOnAlarmRemoved() {
        final int numAlarms = 10;
@@ -1268,6 +1254,134 @@ public class AlarmManagerServiceTest {
        assertEquals(mNowElapsedTest + 12, mService.mPendingIdleUntil.getWhenElapsed());
    }

    @Test
    public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception {
        doReturn(0).when(mService).fuzzForDuration(anyLong());

        final long awiDelayForTest = 23;
        setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest);
        setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 0);

        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000,
                getNewMockPendingIntent());
        assertNotNull(mService.mPendingIdleUntil);

        final long seedTrigger = mNowElapsedTest + 3;
        final int numAlarms = 10;
        final PendingIntent[] pis = new PendingIntent[numAlarms];
        for (int i = 0; i < numAlarms; i++) {
            pis[i] = getNewMockPendingIntent();
            setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, seedTrigger + i * i, pis[i], false);
        }

        long lastAwiDispatch = -1;
        int i = 0;
        while (i < numAlarms) {
            final long nextDispatch = (lastAwiDispatch >= 0) ? (lastAwiDispatch + awiDelayForTest)
                    : (seedTrigger + i * i);
            assertEquals("Wrong allow-while-idle dispatch", nextDispatch, mTestTimer.getElapsed());

            mNowElapsedTest = nextDispatch;
            mTestTimer.expire();

            while (i < numAlarms && (seedTrigger + i * i) <= nextDispatch) {
                verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(),
                        any(Handler.class), isNull(), any());
                i++;
            }
            Log.d(TAG, "Dispatched alarms upto " + i + " at " + nextDispatch);
            lastAwiDispatch = nextDispatch;
        }
    }

    @Test
    public void allowWhileIdleUnrestricted() throws Exception {
        doReturn(0).when(mService).fuzzForDuration(anyLong());

        final long awiDelayForTest = 127;
        setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest);
        setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 0);

        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000,
                getNewMockPendingIntent());
        assertNotNull(mService.mPendingIdleUntil);

        final long seedTrigger = mNowElapsedTest + 3;
        for (int i = 1; i <= 5; i++) {
            setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, seedTrigger + i * i,
                    getNewMockPendingIntent(), true);
        }
        for (int i = 1; i <= 5; i++) {
            final long nextTrigger = mTestTimer.getElapsed();
            assertEquals("Wrong trigger for alarm " + i, seedTrigger + i * i, nextTrigger);
            mNowElapsedTest = nextTrigger;
            mTestTimer.expire();
        }
    }

    @Test
    public void deviceIdleThrottling() throws Exception {
        doReturn(0).when(mService).fuzzForDuration(anyLong());

        final long deviceIdleUntil = mNowElapsedTest + 1234;
        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, deviceIdleUntil, getNewMockPendingIntent());

        assertEquals(deviceIdleUntil, mTestTimer.getElapsed());

        final int numAlarms = 10;
        final PendingIntent[] pis = new PendingIntent[numAlarms];
        for (int i = 0; i < numAlarms; i++) {
            setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + i + 1,
                    pis[i] = getNewMockPendingIntent());
            assertEquals(deviceIdleUntil, mTestTimer.getElapsed());
        }

        mNowElapsedTest = mTestTimer.getElapsed();
        mTestTimer.expire();
        for (int i = 0; i < numAlarms; i++) {
            verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(),
                    any(Handler.class), isNull(), any());
        }
    }

    @Test
    public void dispatchOrder() throws Exception {
        doReturn(0).when(mService).fuzzForDuration(anyLong());

        final long deviceIdleUntil = mNowElapsedTest + 1234;
        final PendingIntent idleUntilPi = getNewMockPendingIntent();
        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, deviceIdleUntil, idleUntilPi);

        assertEquals(deviceIdleUntil, mTestTimer.getElapsed());

        final PendingIntent pi5wakeup = getNewMockPendingIntent();
        final PendingIntent pi4wakeupPackage = getNewMockPendingIntent();
        final PendingIntent pi2nonWakeup = getNewMockPendingIntent(57, "test.different.package");

        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, pi5wakeup);
        setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 4, pi4wakeupPackage);
        setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 2, pi2nonWakeup);

        mNowElapsedTest = deviceIdleUntil;
        mTestTimer.expire();

        // The order of the alarms in delivery list should be:
        // IdleUntil, all alarms of a package with any wakeup alarms, then the rest.
        // Within a package, alarms should be ordered by requested delivery time.
        final PendingIntent[] expectedOrder = new PendingIntent[]{
                idleUntilPi, pi4wakeupPackage, pi5wakeup, pi2nonWakeup};

        ArgumentCaptor<ArrayList<Alarm>> listCaptor = ArgumentCaptor.forClass(ArrayList.class);
        verify(mService).deliverAlarmsLocked(listCaptor.capture(), anyLong());
        final ArrayList<Alarm> deliveryList = listCaptor.getValue();

        assertEquals(expectedOrder.length, deliveryList.size());
        for (int i = 0; i < expectedOrder.length; i++) {
            assertTrue("Unexpected alarm: " + deliveryList.get(i) + " at pos: " + i,
                    deliveryList.get(i).matches(expectedOrder[i], null));
        }
    }

    @After
    public void tearDown() {
        if (mMockingSession != null) {
@@ -1275,12 +1389,4 @@ public class AlarmManagerServiceTest {
        }
        LocalServices.removeServiceForTest(AlarmManagerInternal.class);
    }

    private void dumpAllAlarms(String tag, ArrayList<Alarm> 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();
    }
}
+49 −31
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ 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.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

@@ -45,22 +46,17 @@ public class AlarmStoreTest {
        mAlarmStore = new BatchingAlarmStore(null);
    }

    private static Alarm createAlarm(long whenElapsed, long windowLength,
            AlarmManager.AlarmClockInfo alarmClock) {
        return createAlarm(AlarmManager.ELAPSED_REALTIME, whenElapsed, windowLength,
                alarmClock);
    private static Alarm createAlarm(long whenElapsed, long windowLength) {
        return createAlarm(AlarmManager.ELAPSED_REALTIME, whenElapsed, windowLength, 0);
    }

    private static Alarm createWakeupAlarm(long whenElapsed, long windowLength,
            AlarmManager.AlarmClockInfo alarmClock) {
        return createAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength,
                alarmClock);
    private static Alarm createWakeupAlarm(long whenElapsed, long windowLength, int flags) {
        return createAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength, flags);
    }

    private static Alarm createAlarm(int type, long whenElapsed, long windowLength,
            AlarmManager.AlarmClockInfo alarmClock) {
    private static Alarm createAlarm(int type, long whenElapsed, long windowLength, int flags) {
        return new Alarm(type, whenElapsed, whenElapsed, windowLength, 0, mock(PendingIntent.class),
                null, null, null, 0, alarmClock, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
                null, null, null, flags, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
    }

    private void addAlarmsToStore(Alarm... alarms) {
@@ -71,11 +67,11 @@ public class AlarmStoreTest {

    @Test
    public void add() {
        final Alarm a1 = createAlarm(1, 0, null);
        final Alarm a1 = createAlarm(1, 0);
        mAlarmStore.add(a1);
        assertEquals(1, mAlarmStore.size());

        final Alarm a2 = createAlarm(2, 0, null);
        final Alarm a2 = createAlarm(2, 0);
        mAlarmStore.add(a2);
        assertEquals(2, mAlarmStore.size());

@@ -86,9 +82,9 @@ public class AlarmStoreTest {

    @Test
    public void remove() {
        final Alarm a1 = createAlarm(1, 0, null);
        final Alarm a2 = createAlarm(2, 0, null);
        final Alarm a5 = createAlarm(5, 0, null);
        final Alarm a1 = createAlarm(1, 0);
        final Alarm a2 = createAlarm(2, 0);
        final Alarm a5 = createAlarm(5, 0);
        addAlarmsToStore(a1, a2, a5);

        ArrayList<Alarm> removed = mAlarmStore.remove(a -> (a.getWhenElapsed() < 4));
@@ -96,7 +92,7 @@ public class AlarmStoreTest {
        assertEquals(1, mAlarmStore.size());
        assertTrue(removed.contains(a1) && removed.contains(a2));

        final Alarm a8 = createAlarm(8, 0, null);
        final Alarm a8 = createAlarm(8, 0);
        addAlarmsToStore(a8, a2, a1);

        removed = mAlarmStore.remove(unused -> false);
@@ -110,9 +106,9 @@ public class AlarmStoreTest {

    @Test
    public void removePendingAlarms() {
        final Alarm a1to11 = createAlarm(1, 10, null);
        final Alarm a2to5 = createAlarm(2, 3, null);
        final Alarm a6to9 = createAlarm(6, 3, null);
        final Alarm a1to11 = createAlarm(1, 10);
        final Alarm a2to5 = createAlarm(2, 3);
        final Alarm a6to9 = createAlarm(6, 3);
        addAlarmsToStore(a2to5, a6to9, a1to11);

        final ArrayList<Alarm> pendingAt0 = mAlarmStore.removePendingAlarms(0);
@@ -134,10 +130,10 @@ public class AlarmStoreTest {

    @Test
    public void getNextWakeupDeliveryTime() {
        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);
        final Alarm a1to10 = createAlarm(1, 9);
        final Alarm a3to8wakeup = createWakeupAlarm(3, 5, 0);
        final Alarm a6wakeup = createWakeupAlarm(6, 0, 0);
        final Alarm a5 = createAlarm(5, 0);
        addAlarmsToStore(a5, a6wakeup, a3to8wakeup, a1to10);

        // The wakeup alarms are [6] and [3, 8], hence 6 is the latest time till when we can
@@ -155,10 +151,10 @@ public class AlarmStoreTest {

    @Test
    public void getNextDeliveryTime() {
        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);
        final Alarm a1to10 = createAlarm(1, 9);
        final Alarm a3to8wakeup = createWakeupAlarm(3, 5, 0);
        final Alarm a6wakeup = createWakeupAlarm(6, 0, 0);
        final Alarm a5 = createAlarm(5, 0);
        addAlarmsToStore(a5, a6wakeup, a3to8wakeup, a1to10);

        assertTrue(mAlarmStore.getNextDeliveryTime() <= 5);
@@ -167,11 +163,33 @@ public class AlarmStoreTest {
        assertEquals(0, mAlarmStore.getNextWakeupDeliveryTime());
    }

    @Test
    public void getNextWakeFromIdle() {
        final Alarm a3 = createWakeupAlarm(3, 0, AlarmManager.FLAG_WAKE_FROM_IDLE);
        final Alarm a5 = createWakeupAlarm(5, 0, AlarmManager.FLAG_WAKE_FROM_IDLE);
        final Alarm a7 = createWakeupAlarm(7, 0, AlarmManager.FLAG_WAKE_FROM_IDLE);

        mAlarmStore.add(a5);
        assertEquals(a5, mAlarmStore.getNextWakeFromIdleAlarm());

        mAlarmStore.add(a7);
        assertEquals(a5, mAlarmStore.getNextWakeFromIdleAlarm());

        mAlarmStore.add(a3);
        assertEquals(a3, mAlarmStore.getNextWakeFromIdleAlarm());

        mAlarmStore.remove(a -> (a == a3) || (a == a5));
        assertEquals(a7, mAlarmStore.getNextWakeFromIdleAlarm());

        mAlarmStore.remove(a -> (a == a7));
        assertNull(mAlarmStore.getNextWakeFromIdleAlarm());
    }

    @Test
    public void updateAlarmDeliveries() {
        final Alarm a5 = createAlarm(5, 0, null);
        final Alarm a8 = createAlarm(8, 0, null);
        final Alarm a10 = createAlarm(10, 0, null);
        final Alarm a5 = createAlarm(5, 0);
        final Alarm a8 = createAlarm(8, 0);
        final Alarm a10 = createAlarm(10, 0);
        addAlarmsToStore(a8, a10, a5);

        assertEquals(5, mAlarmStore.getNextDeliveryTime());
+61 −26
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ 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.NUM_POLICIES;
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;
@@ -36,6 +37,8 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Random;

@Presubmit
@RunWith(AndroidJUnit4.class)
public class AlarmTest {
@@ -49,29 +52,54 @@ public class AlarmTest {
    @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));

        for (int i = 0; i < NUM_POLICIES; i++) {
            if (i == REQUESTER_POLICY_INDEX) {
                assertEquals(4567, a.getPolicyElapsed(i));
            } else {
                assertEquals(0, a.getPolicyElapsed(i));
            }
        }
    }

    /**
     * Generates a long matrix {@code A} of size {@code NxN}, with the property that the {@code i}th
     * row will have the {@code i}th element largest in that row.
     *
     * In other words, {@code A[i][i]} will be the maximum of {@code A[i][j]} over all {@code j},
     * {@code 0<=j<N}.
     */
    private static long[][] generatePolicyTestMatrix(int n) {
        final long[][] data = new long[n][n];
        final Random random = new Random(971);
        for (int i = 0; i < n; i++) {
            data[i][i] = 1;
            for (int j = 0; j < n; j++) {
                if (i != j) {
                    data[i][j] = random.nextInt(1 << 20);
                    data[i][i] += data[i][j];
                }
            }
        }
        return data;
    }

    @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());
        final long[][] uniqueData = generatePolicyTestMatrix(NUM_POLICIES);
        for (int i = 0; i < NUM_POLICIES; i++) {
            for (int j = 0; j < NUM_POLICIES; j++) {
                a.setPolicyElapsed(j, uniqueData[i][j]);
            }
            assertEquals(uniqueData[i][i], a.getWhenElapsed());
        }

        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 7);
        assertEquals(7, a.getWhenElapsed());
        for (int i = 0; i < NUM_POLICIES; i++) {
            a.setPolicyElapsed(i, 3);
        }
        assertEquals(3, a.getWhenElapsed());
    }

    @Test
@@ -85,18 +113,21 @@ public class AlarmTest {
        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());
        for (int i = 0; i < NUM_POLICIES; i++) {
            if (i == REQUESTER_POLICY_INDEX) {
                continue;
            }
            a.setPolicyElapsed(i, 17);
            // getWhenElapsed is 17, so getMaxWhenElapsed will return 17 too.
            assertEquals(17, a.getMaxWhenElapsed());

        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 12);
            a.setPolicyElapsed(i, 5);
            assertEquals(14, a.getMaxWhenElapsed());
        }
    }

    @Test
    public void setPolicyElapsed() {
    public void setPolicyElapsedExact() {
        final Alarm exactAlarm = createDefaultAlarm(10, 0);

        assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));
@@ -108,6 +139,10 @@ public class AlarmTest {

        assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 7));

    }

    @Test
    public void setPolicyElapsedInexact() {
        final Alarm inexactAlarm = createDefaultAlarm(10, 5);

        assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));