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

Commit d90dd503 authored by Hari Raj Vijayakumar's avatar Hari Raj Vijayakumar Committed by Dmitri Plotnikov
Browse files

Fix AlarmManager high CPU issue

- clampPositive assumes negative value is due to overflow and so sets
   to MAX_VALUE. However it also possible that negative value occurs
    due to addition of negative value(of higher magnitude) with positive
    of lower magnitude. In issue case, NTP sync causes RTC to move
    forward thus pushing whenElapsed to negative range. This means
    maxWhenElapsed would also be negative but is clamped to MAX_VALUE
    causing AlarmManager to go into infinite loop.

Bug: b/308389917
Test: manual
Change-Id: Ie12d5125f1feeeb1a5dd661a744f86d00796d126
Merged-In: I946333b86b2658ec1b70cb1e3110f5eae1b81486
parent 47a3e1b8
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
import static android.app.AlarmManager.RTC;
import static android.app.AlarmManager.RTC_WAKEUP;

import static com.android.server.alarm.AlarmManagerService.clampPositive;
import static com.android.server.alarm.AlarmManagerService.addClampPositive;

import android.app.AlarmManager;
import android.app.IAlarmListener;
@@ -146,7 +146,7 @@ class Alarm {
        mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] = requestedWhenElapsed;
        mWhenElapsed = requestedWhenElapsed;
        this.windowLength = windowLength;
        mMaxWhenElapsed = clampPositive(requestedWhenElapsed + windowLength);
        mMaxWhenElapsed = addClampPositive(requestedWhenElapsed, windowLength);
        repeatInterval = interval;
        operation = op;
        listener = rec;
@@ -241,8 +241,8 @@ class Alarm {

        final long oldMaxWhenElapsed = mMaxWhenElapsed;
        // windowLength should always be >= 0 here.
        final long maxRequestedElapsed = clampPositive(
                mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] + windowLength);
        final long maxRequestedElapsed = addClampPositive(
                mPolicyWhenElapsed[REQUESTER_POLICY_INDEX], windowLength);
        mMaxWhenElapsed = Math.max(maxRequestedElapsed, mWhenElapsed);

        return (oldWhenElapsed != mWhenElapsed) || (oldMaxWhenElapsed != mMaxWhenElapsed);
+15 −3
Original line number Diff line number Diff line
@@ -1498,15 +1498,15 @@ public class AlarmManagerService extends SystemService {
        if (futurity < MIN_FUZZABLE_INTERVAL) {
            futurity = 0;
        }
        long maxElapsed = triggerAtTime + (long) (0.75 * futurity);
        long maxElapsed = addClampPositive(triggerAtTime, (long) (0.75 * futurity));
        // For non-repeating alarms, window is capped at a maximum of one hour from the requested
        // delivery time. This allows for inexact-while-idle alarms to be slightly more reliable.
        // In practice, the delivery window should generally be much smaller than that
        // when the device is not idling.
        if (interval == 0) {
            maxElapsed = Math.min(maxElapsed, triggerAtTime + INTERVAL_HOUR);
            maxElapsed = Math.min(maxElapsed, addClampPositive(triggerAtTime, INTERVAL_HOUR));
        }
        return clampPositive(maxElapsed);
        return maxElapsed;
    }

    // The RTC clock has moved arbitrarily, so we need to recalculate all the RTC alarm deliveries.
@@ -1593,6 +1593,18 @@ public class AlarmManagerService extends SystemService {
        return (val >= 0) ? val : Long.MAX_VALUE;
    }

    static long addClampPositive(long val1, long val2) {
        long val = val1 + val2;
        if (val >= 0) {
            return val;
        } else if (val1 >= 0 && val2 >= 0) {
            /* Both are +ve, so overflow happened. */
            return Long.MAX_VALUE;
        } else {
            return 0;
        }
    }

    /**
     * Sends alarms that were blocked due to user applied background restrictions - either because
     * the user lifted those or the uid came to foreground.