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

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

Merge "Adding Battery saver policy to alarms"

parents 44859f71 17f6e200
Loading
Loading
Loading
Loading
+58 −37
Original line number Diff line number Diff line
@@ -274,11 +274,8 @@ public class AppStateTrackerImpl implements AppStateTracker {
                int uid, @NonNull String packageName) {
            updateJobsForUidPackage(uid, packageName, sender.isUidActive(uid));

            if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ false)) {
            if (!sender.areAlarmsRestricted(uid, packageName)) {
                unblockAlarmsForUidPackage(uid, packageName);
            } else if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ true)) {
                // we need to deliver the allow-while-idle alarms for this uid, package
                unblockAllUnrestrictedAlarms();
            }

            if (!sender.isRunAnyInBackgroundAppOpsAllowed(uid, packageName)) {
@@ -302,6 +299,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
            final boolean isActive = sender.isUidActive(uid);

            updateJobsForUid(uid, isActive);
            updateAlarmsForUid(uid);

            if (isActive) {
                unblockAlarmsForUid(uid);
@@ -313,7 +311,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
         */
        private void onPowerSaveUnexempted(AppStateTrackerImpl sender) {
            updateAllJobs();
            unblockAllUnrestrictedAlarms();
            updateAllAlarms();
        }

        /**
@@ -322,6 +320,8 @@ public class AppStateTrackerImpl implements AppStateTracker {
         */
        private void onPowerSaveExemptionListChanged(AppStateTrackerImpl sender) {
            updateAllJobs();
            updateAllAlarms();
            unblockAllUnrestrictedAlarms();
        }

        /**
@@ -344,7 +344,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
        private void onExemptedBucketChanged(AppStateTrackerImpl sender) {
            // This doesn't happen very often, so just re-evaluate all jobs / alarms.
            updateAllJobs();
            unblockAllUnrestrictedAlarms();
            updateAllAlarms();
        }

        /**
@@ -352,10 +352,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
         */
        private void onForceAllAppsStandbyChanged(AppStateTrackerImpl sender) {
            updateAllJobs();

            if (!sender.isForceAllAppsStandbyEnabled()) {
                unblockAllUnrestrictedAlarms();
            }
            updateAllAlarms();
        }

        /**
@@ -386,6 +383,19 @@ public class AppStateTrackerImpl implements AppStateTracker {
        public void stopForegroundServicesForUidPackage(int uid, String packageName) {
        }

        /**
         * Called when all alarms need to be re-evaluated for eligibility based on
         * {@link #areAlarmsRestrictedByBatterySaver}.
         */
        public void updateAllAlarms() {
        }

        /**
         * Called when the given uid state changes to active / idle.
         */
        public void updateAlarmsForUid(int uid) {
        }

        /**
         * Called when the job restrictions for multiple UIDs might have changed, so the alarm
         * manager should re-evaluate all restrictions for all blocked jobs.
@@ -918,7 +928,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
                    // Feature flag for forced app standby changed.
                    final boolean unblockAlarms;
                    synchronized (mLock) {
                        unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
                        unblockAlarms = !mForcedAppStandbyEnabled;
                    }
                    for (Listener l : cloneListeners()) {
                        l.updateAllJobs();
@@ -1109,53 +1119,64 @@ public class AppStateTrackerImpl implements AppStateTracker {
    }

    /**
     * @return whether alarms should be restricted for a UID package-name.
     * @return whether alarms should be restricted for a UID package-name, due to explicit
     * user-forced app standby. Use {{@link #areAlarmsRestrictedByBatterySaver} to check for
     * restrictions induced by battery saver.
     */
    public boolean areAlarmsRestricted(int uid, @NonNull String packageName,
            boolean isExemptOnBatterySaver) {
        return isRestricted(uid, packageName, /*useTempExemptionListToo=*/ false,
                isExemptOnBatterySaver);
    public boolean areAlarmsRestricted(int uid, @NonNull String packageName) {
        if (isUidActive(uid)) {
            return false;
        }
        synchronized (mLock) {
            final int appId = UserHandle.getAppId(uid);
            if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) {
                return false;
            }
            return (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName));
        }

    /**
     * @return whether jobs should be restricted for a UID package-name.
     */
    public boolean areJobsRestricted(int uid, @NonNull String packageName,
            boolean hasForegroundExemption) {
        return isRestricted(uid, packageName, /*useTempExemptionListToo=*/ true,
                hasForegroundExemption);
    }

    /**
     * @return whether foreground services should be suppressed in the background
     * due to forced app standby for the given app
     * @return whether alarms should be restricted when due to battery saver.
     */
    public boolean areForegroundServicesRestricted(int uid, @NonNull String packageName) {
    public boolean areAlarmsRestrictedByBatterySaver(int uid, @NonNull String packageName) {
        if (isUidActive(uid)) {
            return false;
        }
        synchronized (mLock) {
            return isRunAnyRestrictedLocked(uid, packageName);
            final int appId = UserHandle.getAppId(uid);
            if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) {
                return false;
            }
            final int userId = UserHandle.getUserId(uid);
            if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole()
                    && mExemptedBucketPackages.contains(userId, packageName)) {
                return false;
            }
            return mForceAllAppsStandby;
        }
    }


    /**
     * @return whether force-app-standby is effective for a UID package-name.
     * @return whether jobs should be restricted for a UID package-name. This could be due to
     * battery saver or user-forced app standby
     */
    private boolean isRestricted(int uid, @NonNull String packageName,
            boolean useTempExemptionListToo, boolean exemptOnBatterySaver) {
    public boolean areJobsRestricted(int uid, @NonNull String packageName,
            boolean hasForegroundExemption) {
        if (isUidActive(uid)) {
            return false;
        }
        synchronized (mLock) {
            final int appId = UserHandle.getAppId(uid);
            if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) {
                return false;
            }
            if (useTempExemptionListToo && ArrayUtils.contains(mTempExemptAppIds, appId)) {
            if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)
                    || ArrayUtils.contains(mTempExemptAppIds, appId)) {
                return false;
            }
            if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
                return true;
            }
            if (exemptOnBatterySaver) {
            if (hasForegroundExemption) {
                return false;
            }
            final int userId = UserHandle.getUserId(uid);
+9 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import java.util.Date;
 */
class Alarm {
    @VisibleForTesting
    public static final int NUM_POLICIES = 3;
    public static final int NUM_POLICIES = 4;
    /**
     * Index used to store the time the alarm was requested to expire. To be used with
     * {@link #setPolicyElapsed(int, long)}.
@@ -59,6 +59,12 @@ class Alarm {
     */
    public static final int DEVICE_IDLE_POLICY_INDEX = 2;

    /**
     * Index used to store the earliest time the alarm can expire based on battery saver policy.
     * To be used with {@link #setPolicyElapsed(int, long)}.
     */
    public static final int BATTERY_SAVER_POLICY_INDEX = 3;

    public final int type;
    /**
     * The original trigger time supplied by the caller. This can be in the elapsed or rtc time base
@@ -223,6 +229,8 @@ class Alarm {
                return "app_standby";
            case DEVICE_IDLE_POLICY_INDEX:
                return "device_idle";
            case BATTERY_SAVER_POLICY_INDEX:
                return "battery_saver";
            default:
                return "--unknown--";
        }
+112 −71
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ 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.BATTERY_SAVER_POLICY_INDEX;
import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX;
import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;

@@ -156,6 +157,7 @@ public class AlarmManagerService extends SystemService {

    static final int TICK_HISTORY_DEPTH = 10;
    static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
    static final long INDEFINITE_DELAY = 365 * MILLIS_IN_DAY;

    // Indices into the KEYS_APP_STANDBY_QUOTAS array.
    static final int ACTIVE_INDEX = 0;
@@ -964,8 +966,7 @@ public class AlarmManagerService extends SystemService {
     * Check all alarms in {@link #mPendingBackgroundAlarms} and send the ones that are not
     * restricted.
     *
     * This is only called when the global "force all apps-standby" flag changes or when the
     * power save whitelist changes, so it's okay to be slow.
     * This is only called when the power save whitelist changes, so it's okay to be slow.
     */
    void sendAllUnrestrictedPendingBackgroundAlarmsLocked() {
        final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
@@ -984,7 +985,6 @@ public class AlarmManagerService extends SystemService {
            Predicate<Alarm> isBackgroundRestricted) {

        for (int uidIndex = pendingAlarms.size() - 1; uidIndex >= 0; uidIndex--) {
            final int uid = pendingAlarms.keyAt(uidIndex);
            final ArrayList<Alarm> alarmsForUid = pendingAlarms.valueAt(uidIndex);

            for (int alarmIndex = alarmsForUid.size() - 1; alarmIndex >= 0; alarmIndex--) {
@@ -1619,6 +1619,44 @@ public class AlarmManagerService extends SystemService {
        return true;
    }

    /**
     * Adjusts the delivery time of the alarm based on battery saver rules.
     *
     * @param alarm The alarm to adjust
     * @return {@code true} if the alarm delivery time was updated.
     */
    private boolean adjustDeliveryTimeBasedOnBatterySaver(Alarm alarm) {
        final long nowElapsed = mInjector.getElapsedRealtime();
        if (isExemptFromBatterySaver(alarm)) {
            return false;
        }

        if (!(mAppStateTracker != null && mAppStateTracker.areAlarmsRestrictedByBatterySaver(
                alarm.creatorUid, alarm.sourcePackage))) {
            return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, nowElapsed);
        }

        final long batterSaverPolicyElapsed;
        if ((alarm.flags & (AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) {
            // Unrestricted.
            batterSaverPolicyElapsed = nowElapsed;
        } else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
            // Allowed but limited.
            final long minDelay;
            if (mUseAllowWhileIdleShortTime.get(alarm.creatorUid)) {
                minDelay = mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
            } else {
                minDelay = mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
            }
            final long lastDispatch = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0);
            batterSaverPolicyElapsed = (lastDispatch == 0) ? nowElapsed : lastDispatch + minDelay;
        } else {
            // Not allowed.
            batterSaverPolicyElapsed = nowElapsed + INDEFINITE_DELAY;
        }
        return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, batterSaverPolicyElapsed);
    }

    /**
     * Adjusts the delivery time of the alarm based on device_idle (doze) rules.
     *
@@ -1756,6 +1794,7 @@ public class AlarmManagerService extends SystemService {
        if (a.alarmClock != null) {
            mNextAlarmClockMayChange = true;
        }
        adjustDeliveryTimeBasedOnBatterySaver(a);
        adjustDeliveryTimeBasedOnBucketLocked(a);
        mAlarmStore.add(a);
        rescheduleKernelAlarmsLocked();
@@ -2230,14 +2269,6 @@ public class AlarmManagerService extends SystemService {
                    pw.print(": ");
                    final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
                    TimeUtils.formatDuration(lastTime, nowELAPSED, pw);

                    final long minInterval = getWhileIdleMinIntervalLocked(uid);
                    pw.print("  Next allowed:");
                    TimeUtils.formatDuration(lastTime + minInterval, nowELAPSED, pw);
                    pw.print(" (");
                    TimeUtils.formatDuration(minInterval, 0, pw);
                    pw.print(")");

                    pw.println();
                }
                pw.decreaseIndent();
@@ -2511,8 +2542,6 @@ public class AlarmManagerService extends SystemService {
                proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.UID, uid);
                proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.TIME_MS,
                        lastTime);
                proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS,
                        lastTime + getWhileIdleMinIntervalLocked(uid));
                proto.end(token);
            }

@@ -3119,30 +3148,36 @@ public class AlarmManagerService extends SystemService {
        }
    }

    private boolean isExemptFromBatterySaver(Alarm alarm) {
        if (alarm.alarmClock != null) {
            return true;
        }
        if ((alarm.operation != null)
                && (alarm.operation.isActivity() || alarm.operation.isForegroundService())) {
            return true;
        }
        if (UserHandle.isCore(alarm.creatorUid)) {
            return true;
        }
        return false;
    }

    private boolean isBackgroundRestricted(Alarm alarm) {
        boolean exemptOnBatterySaver = (alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0;
        if (alarm.alarmClock != null) {
            // Don't defer alarm clocks
            return false;
        }
        if (alarm.operation != null) {
            if (alarm.operation.isActivity()) {
        if (alarm.operation != null && alarm.operation.isActivity()) {
            // Don't defer starting actual UI
            return false;
        }
            if (alarm.operation.isForegroundService()) {
                // FG service alarms are nearly as important; consult AST policy
                exemptOnBatterySaver = true;
            }
        }
        final String sourcePackage = alarm.sourcePackage;
        final int sourceUid = alarm.creatorUid;
        if (UserHandle.isCore(sourceUid)) {
            return false;
        }
        return (mAppStateTracker != null) &&
                mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage,
                        exemptOnBatterySaver);
        return (mAppStateTracker != null) && mAppStateTracker.areAlarmsRestricted(sourceUid,
                sourcePackage);
    }

    private static native long init();
@@ -3153,46 +3188,10 @@ public class AlarmManagerService extends SystemService {
    private static native int setKernelTimezone(long nativeData, int minuteswest);
    private static native long getNextAlarm(long nativeData, int type);

    private long getWhileIdleMinIntervalLocked(int uid) {
        final boolean ebs = (mAppStateTracker != null)
                && mAppStateTracker.isForceAllAppsStandbyEnabled();

        if (!ebs || mUseAllowWhileIdleShortTime.get(uid)) {
            // if the last allow-while-idle went off while uid was fg, or the uid
            // recently came into fg, don't block the alarm for long.
            return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
        }
        return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
    }

    boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) {
        boolean hasWakeup = false;
        final ArrayList<Alarm> pendingAlarms = mAlarmStore.removePendingAlarms(nowELAPSED);
        for (final Alarm alarm : pendingAlarms) {
            if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
                // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
                // schedule such alarms.  The first such alarm from an app is always delivered.
                final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, -1);
                final long minTime = lastTime + getWhileIdleMinIntervalLocked(alarm.creatorUid);
                if (lastTime >= 0 && nowELAPSED < minTime) {
                    // 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.setPolicyElapsed(REQUESTER_POLICY_INDEX, minTime);
                    if (RECORD_DEVICE_IDLE_ALARMS) {
                        IdleDispatchEntry ent = new IdleDispatchEntry();
                        ent.uid = alarm.uid;
                        ent.pkg = alarm.operation.getCreatorPackage();
                        ent.tag = alarm.operation.getTag("");
                        ent.op = "RESCHEDULE";
                        ent.elapsedRealtime = nowELAPSED;
                        ent.argRealtime = lastTime;
                        mAllowWhileIdleDispatches.add(ent);
                    }
                    setImplLocked(alarm);
                    continue;
                }
            }
            if (isBackgroundRestricted(alarm)) {
                // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred
                if (DEBUG_BG_LIMIT) {
@@ -3924,8 +3923,41 @@ public class AlarmManagerService extends SystemService {
    }

    private final Listener mForceAppStandbyListener = new Listener() {

        @Override
        public void updateAllAlarms() {
            // Called when:
            // 1. Power exemption list changes,
            // 2. Battery saver state is toggled,
            // 3. Any package is moved into or out of the EXEMPTED bucket.
            synchronized (mLock) {
                if (mAlarmStore.updateAlarmDeliveries(
                        a -> adjustDeliveryTimeBasedOnBatterySaver(a))) {
                    rescheduleKernelAlarmsLocked();
                }
            }
        }

        @Override
        public void updateAlarmsForUid(int uid) {
            // Called when the given uid's state switches b/w active and idle.
            synchronized (mLock) {
                if (mAlarmStore.updateAlarmDeliveries(a -> {
                    if (a.creatorUid != uid) {
                        return false;
                    }
                    return adjustDeliveryTimeBasedOnBatterySaver(a);
                })) {
                    rescheduleKernelAlarmsLocked();
                }
            }
        }

        @Override
        public void unblockAllUnrestrictedAlarms() {
            // Called when:
            // 1. Power exemption list changes,
            // 2. User FAS feature is disabled.
            synchronized (mLock) {
                sendAllUnrestrictedPendingBackgroundAlarmsLocked();
            }
@@ -3934,12 +3966,14 @@ public class AlarmManagerService extends SystemService {
        @Override
        public void unblockAlarmsForUid(int uid) {
            synchronized (mLock) {
                // Called when the given uid becomes active.
                sendPendingBackgroundAlarmsLocked(uid, null);
            }
        }

        @Override
        public void unblockAlarmsForUidPackage(int uid, String packageName) {
            // Called when user turns off FAS for this (uid, package).
            synchronized (mLock) {
                sendPendingBackgroundAlarmsLocked(uid, packageName);
            }
@@ -3950,9 +3984,14 @@ public class AlarmManagerService extends SystemService {
            synchronized (mLock) {
                if (foreground) {
                    mUseAllowWhileIdleShortTime.put(uid, true);

                    // Note we don't have to drain the pending while-idle alarms here, because
                    // this event should coincide with unblockAlarmsForUid().
                    if (mAlarmStore.updateAlarmDeliveries(a -> {
                        if (a.creatorUid != uid || (a.flags & FLAG_ALLOW_WHILE_IDLE) == 0) {
                            return false;
                        }
                        return adjustDeliveryTimeBasedOnBatterySaver(a);
                    })) {
                        rescheduleKernelAlarmsLocked();
                    }
                }
            }
        }
@@ -4236,18 +4275,20 @@ public class AlarmManagerService extends SystemService {
            if (allowWhileIdle) {
                // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
                mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
                mAlarmStore.updateAlarmDeliveries(a -> {
                    if (a.creatorUid != alarm.creatorUid) {
                        return false;
                    }
                    return adjustDeliveryTimeBasedOnDeviceIdle(a);
                });
                if ((mAppStateTracker == null)
                        || mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
                    mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
                } else {
                    mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
                }
                mAlarmStore.updateAlarmDeliveries(a -> {
                    if (a.creatorUid != alarm.creatorUid
                            || (a.flags & FLAG_ALLOW_WHILE_IDLE) == 0) {
                        return false;
                    }
                    return adjustDeliveryTimeBasedOnDeviceIdle(a)
                            | adjustDeliveryTimeBasedOnBatterySaver(a);
                });
                if (RECORD_DEVICE_IDLE_ALARMS) {
                    IdleDispatchEntry ent = new IdleDispatchEntry();
                    ent.uid = alarm.uid;
+354 −123

File changed.

Preview size limit exceeded, changes collapsed.

+124 −6

File changed.

Preview size limit exceeded, changes collapsed.