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

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

Merge "Exempting prioritized alarms from min_window" into sc-dev

parents a9d0dfcd 856a92d3
Loading
Loading
Loading
Loading
+53 −55
Original line number Diff line number Diff line
@@ -1684,17 +1684,13 @@ public class AlarmManagerService extends SystemService {
            }
        }

        if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
            // Do not support windows for idle-until alarms.
            windowLength = AlarmManager.WINDOW_EXACT;
        }

        // Snap the window to reasonable limits.
        if (windowLength > INTERVAL_DAY) {
            Slog.w(TAG, "Window length " + windowLength
                    + "ms suspiciously long; limiting to 1 day");
            windowLength = INTERVAL_DAY;
        } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW) {
        } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW
                && (flags & FLAG_PRIORITIZE) == 0) {
            if (CompatChanges.isChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS,
                    callingPackage, UserHandle.getUserHandleForUid(callingUid))) {
                Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to "
@@ -1741,7 +1737,7 @@ public class AlarmManagerService extends SystemService {
        final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;

        final long maxElapsed;
        if (windowLength == AlarmManager.WINDOW_EXACT) {
        if (windowLength == 0) {
            maxElapsed = triggerElapsed;
        } else if (windowLength < 0) {
            maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
@@ -2145,17 +2141,63 @@ public class AlarmManagerService extends SystemService {
                        + " does not belong to the calling uid " + callingUid);
            }

            // Repeating alarms must use PendingIntent, not direct listener
            if (interval != 0 && directReceiver != null) {
                throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
            }

            if (workSource != null) {
                getContext().enforcePermission(
                        android.Manifest.permission.UPDATE_DEVICE_STATS,
                        Binder.getCallingPid(), callingUid, "AlarmManager.set");
            }

            if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
                // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
                // manager when to come out of idle mode, which is only for DeviceIdleController.
                if (callingUid != Process.SYSTEM_UID) {
                    // TODO (b/169463012): Throw instead of tolerating this mistake.
                    flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
                } else {
                    // Do not support windows for idle-until alarms.
                    windowLength = 0;
                }
            }

            // Remove flags reserved for the service, we will apply those later as appropriate.
            flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
                    | FLAG_ALLOW_WHILE_IDLE_COMPAT);

            // If this alarm is for an alarm clock, then it must be exact and we will
            // use it to wake early from idle if needed.
            if (alarmClock != null) {
                flags |= FLAG_WAKE_FROM_IDLE;
                windowLength = 0;

            // If the caller is a core system component or on the user's allowlist, and not calling
            // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
            // This means we will allow these alarms to go off as normal even while idle, with no
            // timing restrictions.
            } else if (workSource == null && (UserHandle.isCore(callingUid)
                    || UserHandle.isSameApp(callingUid, mSystemUiUid)
                    || ((mAppStateTracker != null)
                    && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) {
                flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
                flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_PRIORITIZE);
            }

            final boolean allowWhileIdle = (flags & FLAG_ALLOW_WHILE_IDLE) != 0;
            final boolean exact = (windowLength == AlarmManager.WINDOW_EXACT);
            final boolean exact = (windowLength == 0);

            // make sure the caller is allowed to use the requested kind of alarm, and also
            // Make sure the caller is allowed to use the requested kind of alarm, and also
            // decide what quota and broadcast options to use.
            Bundle idleOptions = null;
            if ((flags & FLAG_PRIORITIZE) != 0) {
                getContext().enforcePermission(
                        Manifest.permission.SCHEDULE_PRIORITIZED_ALARM,
                        Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized");
                flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_ALLOW_WHILE_IDLE_COMPAT);
                // The API doesn't allow using both together.
                flags &= ~FLAG_ALLOW_WHILE_IDLE;
            } else if (exact || allowWhileIdle) {
                final boolean needsPermission;
                boolean lowerQuota;
@@ -2193,55 +2235,11 @@ public class AlarmManagerService extends SystemService {
                }
            }

            // Repeating alarms must use PendingIntent, not direct listener
            if (interval != 0) {
                if (directReceiver != null) {
                    throw new IllegalArgumentException(
                            "Repeating alarms cannot use AlarmReceivers");
                }
            }

            if (workSource != null) {
                getContext().enforcePermission(
                        android.Manifest.permission.UPDATE_DEVICE_STATS,
                        Binder.getCallingPid(), callingUid, "AlarmManager.set");
            }

            // No incoming callers can request either WAKE_FROM_IDLE or
            // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
            flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);

            // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
            // manager when to come out of idle mode, which is only for DeviceIdleController.
            if (callingUid != Process.SYSTEM_UID) {
                flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
            }

            // If this is an exact time alarm, then it can't be batched with other alarms.
            if (windowLength == AlarmManager.WINDOW_EXACT) {
            if (exact) {
                flags |= AlarmManager.FLAG_STANDALONE;
            }

            // If this alarm is for an alarm clock, then it must be standalone and we will
            // use it to wake early from idle if needed.
            if (alarmClock != null) {
                flags |= FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;

            // If the caller is a core system component or on the user's whitelist, and not calling
            // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
            // This means we will allow these alarms to go off as normal even while idle, with no
            // timing restrictions.
            } else if (workSource == null && (UserHandle.isCore(callingUid)
                    || UserHandle.isSameApp(callingUid, mSystemUiUid)
                    || ((mAppStateTracker != null)
                        && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) {
                flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
                flags &= ~FLAG_ALLOW_WHILE_IDLE;
                flags &= ~FLAG_ALLOW_WHILE_IDLE_COMPAT;
                flags &= ~FLAG_PRIORITIZE;
                idleOptions = null;
            }

            setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
                    listenerTag, flags, workSource, alarmClock, callingUid, callingPackage,
                    idleOptions);
+0 −1
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.alarm;

import static com.android.server.alarm.AlarmManagerService.TAG;
import static com.android.server.alarm.AlarmManagerService.dumpAlarmList;
import static com.android.server.alarm.AlarmManagerService.isTimeTickAlarm;

+29 −6
Original line number Diff line number Diff line
@@ -468,8 +468,9 @@ public class AlarmManagerServiceTest {
                TEST_CALLING_UID);
    }

    private void setPrioritizedAlarm(int type, long triggerTime, IAlarmListener listener) {
        mService.setImpl(type, triggerTime, WINDOW_EXACT, 0, null, listener, "test",
    private void setPrioritizedAlarm(int type, long triggerTime, long windowLength,
            IAlarmListener listener) {
        mService.setImpl(type, triggerTime, windowLength, 0, null, listener, "test",
                FLAG_STANDALONE | FLAG_PRIORITIZE, null, null, TEST_CALLING_UID,
                TEST_CALLING_PACKAGE, null);
    }
@@ -1685,7 +1686,7 @@ public class AlarmManagerServiceTest {
        final int numAlarms = 10;
        for (int i = 0; i < numAlarms; i++) {
            setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
                    new IAlarmListener.Stub() {
                    0, new IAlarmListener.Stub() {
                        @Override
                        public void doAlarm(IAlarmCompleteListener callback)
                                throws RemoteException {
@@ -1720,7 +1721,7 @@ public class AlarmManagerServiceTest {
        final int numAlarms = 10;
        for (int i = 0; i < numAlarms; i++) {
            setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
                    new IAlarmListener.Stub() {
                    0, new IAlarmListener.Stub() {
                        @Override
                        public void doAlarm(IAlarmCompleteListener callback)
                                throws RemoteException {
@@ -1738,12 +1739,12 @@ public class AlarmManagerServiceTest {
        }
        assertEquals(numAlarms, alarmsFired.get());

        setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, new IAlarmListener.Stub() {
        setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, 0, new IAlarmListener.Stub() {
            @Override
            public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
            }
        });
        setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, new IAlarmListener.Stub() {
        setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, 0, new IAlarmListener.Stub() {
            @Override
            public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
            }
@@ -2262,6 +2263,28 @@ public class AlarmManagerServiceTest {
        }
    }

    @Test
    public void minWindowPriorityAlarm() {
        doReturn(true).when(
                () -> CompatChanges.isChangeEnabled(
                        eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
                        anyString(), any(UserHandle.class)));
        final long minWindow = 73;
        setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);

        // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC.
        for (int window = 1; window <= minWindow; window++) {
            setPrioritizedAlarm(ELAPSED_REALTIME, 0, window, new IAlarmListener.Stub() {
                @Override
                public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
                }
            });
            assertEquals(1, mService.mAlarmStore.size());
            final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
            assertEquals(window, a.windowLength);
        }
    }

    @Test
    public void denyListPackagesAdded() {
        mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"});