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

Commit f45e16f2 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Work on issue #20401752: device idle and alarms."

parents 4b1ebb4f f70faed5
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -597,6 +597,15 @@ public class AlarmManager
        }
        }
    }
    }


    /** @hide */
    public long getNextWakeFromIdleTime() {
        try {
            return mService.getNextWakeFromIdleTime();
        } catch (RemoteException ex) {
            return Long.MAX_VALUE;
        }
    }

    /**
    /**
     * Gets information about the next alarm clock currently scheduled.
     * Gets information about the next alarm clock currently scheduled.
     *
     *
+1 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ interface IAlarmManager {
    boolean setTime(long millis);
    boolean setTime(long millis);
    void setTimeZone(String zone);
    void setTimeZone(String zone);
    void remove(in PendingIntent operation);
    void remove(in PendingIntent operation);
    long getNextWakeFromIdleTime();
    AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
    AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
}
}


+77 −28
Original line number Original line Diff line number Diff line
@@ -460,6 +460,7 @@ class AlarmManagerService extends SystemService {
    // set to null if in idle mode; while in this mode, any alarms we don't want
    // set to null if in idle mode; while in this mode, any alarms we don't want
    // to run during this time are placed in mPendingWhileIdleAlarms
    // to run during this time are placed in mPendingWhileIdleAlarms
    Alarm mPendingIdleUntil = null;
    Alarm mPendingIdleUntil = null;
    Alarm mNextWakeFromIdle = null;
    final ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
    final ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();


    public AlarmManagerService(Context context) {
    public AlarmManagerService(Context context) {
@@ -583,7 +584,7 @@ class AlarmManagerService extends SystemService {
        final int mAlarmType;
        final int mAlarmType;


        InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
        InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
                int alarmType, String tag) {
                int alarmType, String tag, long nowELAPSED) {
            mPendingIntent = pendingIntent;
            mPendingIntent = pendingIntent;
            mWorkSource = workSource;
            mWorkSource = workSource;
            mTag = tag;
            mTag = tag;
@@ -593,6 +594,7 @@ class AlarmManagerService extends SystemService {
                fs = new FilterStats(mBroadcastStats, mTag);
                fs = new FilterStats(mBroadcastStats, mTag);
                mBroadcastStats.filterStats.put(mTag, fs);
                mBroadcastStats.filterStats.put(mTag, fs);
            }
            }
            fs.lastTime = nowELAPSED;
            mFilterStats = fs;
            mFilterStats = fs;
            mAlarmType = alarmType;
            mAlarmType = alarmType;
        }
        }
@@ -602,6 +604,7 @@ class AlarmManagerService extends SystemService {
        final BroadcastStats mBroadcastStats;
        final BroadcastStats mBroadcastStats;
        final String mTag;
        final String mTag;


        long lastTime;
        long aggregateTime;
        long aggregateTime;
        int count;
        int count;
        int numWakeup;
        int numWakeup;
@@ -806,33 +809,38 @@ class AlarmManagerService extends SystemService {
        setImplLocked(a, false, doValidate);
        setImplLocked(a, false, doValidate);
    }
    }


    private void updateNextWakeFromIdleFuzzLocked() {
        if (mNextWakeFromIdle != null) {

        }
    }

    private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
    private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
        if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
        if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
            // This is a special alarm that will put the system idle until it goes off.
            // This is a special alarm that will put the system into idle until it goes off.
            // The caller has given the time they want this to happen at, however we need
            // The caller has given the time they want this to happen at, however we need
            // to pull that earlier if there are existing alarms that have requested to
            // to pull that earlier if there are existing alarms that have requested to
            // bring us out of idle.
            // bring us out of idle.
            final int N = mAlarmBatches.size();
            if (mNextWakeFromIdle != null) {
            for (int i = 0; i < N; i++) {
                a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
                Batch b = mAlarmBatches.get(i);
                if (a.whenElapsed > b.end) {
                    // There are no interesting things happening before our idle until,
                    // so keep the requested time.
                    break;
                }
                if ((b.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
                    a.when = a.whenElapsed = a.maxWhenElapsed = b.end;
                    break;
                }
            }
            }
            // Add fuzz to make the alarm go off some time before the actual desired time.
            // Add fuzz to make the alarm go off some time before the actual desired time.
            final long nowElapsed = SystemClock.elapsedRealtime();
            final long nowElapsed = SystemClock.elapsedRealtime();
            long fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
            final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
            if (fuzz > 0) {
            if (fuzz > 0) {
                if (mRandom == null) {
                if (mRandom == null) {
                    mRandom = new Random();
                    mRandom = new Random();
                }
                }
                a.whenElapsed -= mRandom.nextLong() % fuzz;
                final int delta = mRandom.nextInt(fuzz);
                a.whenElapsed -= delta;
                if (false) {
                    Slog.d(TAG, "Alarm when: " + a.whenElapsed);
                    Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
                    Slog.d(TAG, "Applied fuzz: " + fuzz);
                    Slog.d(TAG, "Final delta: " + delta);
                    Slog.d(TAG, "Final when: " + a.whenElapsed);
                }
                a.when = a.maxWhenElapsed = a.whenElapsed;
            }
            }


        } else if (mPendingIdleUntil != null) {
        } else if (mPendingIdleUntil != null) {
@@ -869,12 +877,17 @@ class AlarmManagerService extends SystemService {
        if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
        if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
            mPendingIdleUntil = a;
            mPendingIdleUntil = a;
            needRebatch = true;
            needRebatch = true;
        } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0 && mPendingIdleUntil != null) {
        } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
            // If we are adding an alarm that asks to wake from idle, and we are currently
            if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
            // idling, then we need to rebatch alarms in case the idle until time needs to
                mNextWakeFromIdle = a;
            // be updated.
                // If this wake from idle is earlier than whatever was previously scheduled,
                // and we are currently idling, then we need to rebatch alarms in case the idle
                // until time needs to be updated.
                if (mPendingIdleUntil != null) {
                    needRebatch = true;
                    needRebatch = true;
                }
                }
            }
        }


        if (!rebatching) {
        if (!rebatching) {
            if (DEBUG_VALIDATE) {
            if (DEBUG_VALIDATE) {
@@ -959,6 +972,11 @@ class AlarmManagerService extends SystemService {


        }
        }


        @Override
        public long getNextWakeFromIdleTime() {
            return getNextWakeFromIdleTimeImpl();
        }

        @Override
        @Override
        public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
        public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
            userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
            userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -1030,10 +1048,15 @@ class AlarmManagerService extends SystemService {
                pw.println();
                pw.println();
                pw.println("Idle mode state:");
                pw.println("Idle mode state:");
                pw.print("  Idling until: "); pw.println(mPendingIdleUntil);
                pw.print("  Idling until: "); pw.println(mPendingIdleUntil);
                mPendingIdleUntil.dump(pw, "    ", nowELAPSED, nowRTC, sdf);
                mPendingIdleUntil.dump(pw, "    ", nowRTC, nowELAPSED, sdf);
                pw.println("  Pending alarms:");
                pw.println("  Pending alarms:");
                dumpAlarmList(pw, mPendingWhileIdleAlarms, "    ", nowELAPSED, nowRTC, sdf);
                dumpAlarmList(pw, mPendingWhileIdleAlarms, "    ", nowELAPSED, nowRTC, sdf);
            }
            }
            if (mNextWakeFromIdle != null) {
                pw.println();
                pw.print("  Next wake from idle: "); pw.println(mNextWakeFromIdle);
                mNextWakeFromIdle.dump(pw, "    ", nowRTC, nowELAPSED, sdf);
            }


            pw.println();
            pw.println();
            pw.print("Past-due non-wakeup alarms: ");
            pw.print("Past-due non-wakeup alarms: ");
@@ -1140,7 +1163,10 @@ class AlarmManagerService extends SystemService {
                                TimeUtils.formatDuration(fs.aggregateTime, pw);
                                TimeUtils.formatDuration(fs.aggregateTime, pw);
                                pw.print(" "); pw.print(fs.numWakeup);
                                pw.print(" "); pw.print(fs.numWakeup);
                                pw.print(" wakes " ); pw.print(fs.count);
                                pw.print(" wakes " ); pw.print(fs.count);
                                pw.print(" alarms: ");
                                pw.print(" alarms, last ");
                                TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
                                pw.println(":");
                        pw.print("      ");
                                pw.print(fs.mTag);
                                pw.print(fs.mTag);
                                pw.println();
                                pw.println();
                    }
                    }
@@ -1216,7 +1242,13 @@ class AlarmManagerService extends SystemService {
        return null;
        return null;
    }
    }


    private AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
    long getNextWakeFromIdleTimeImpl() {
        synchronized (mLock) {
            return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
        }
    }

    AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
        synchronized (mLock) {
        synchronized (mLock) {
            return mNextAlarmClockForUser.get(userId);
            return mNextAlarmClockForUser.get(userId);
        }
        }
@@ -1398,6 +1430,9 @@ class AlarmManagerService extends SystemService {
                mPendingIdleUntil = null;
                mPendingIdleUntil = null;
                restorePending = true;
                restorePending = true;
            }
            }
            if (mNextWakeFromIdle != null && mNextWakeFromIdle.operation.equals(operation)) {
                mNextWakeFromIdle = null;
            }
            rebatchAllAlarmsLocked(true);
            rebatchAllAlarmsLocked(true);
            if (restorePending) {
            if (restorePending) {
                restorePendingWhileIdleAlarmsLocked();
                restorePendingWhileIdleAlarmsLocked();
@@ -1585,11 +1620,19 @@ class AlarmManagerService extends SystemService {
                Alarm alarm = batch.get(i);
                Alarm alarm = batch.get(i);
                alarm.count = 1;
                alarm.count = 1;
                triggerList.add(alarm);
                triggerList.add(alarm);
                if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
                    EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
                            alarm.tag);
                }
                if (mPendingIdleUntil == alarm) {
                if (mPendingIdleUntil == alarm) {
                    mPendingIdleUntil = null;
                    mPendingIdleUntil = null;
                    rebatchAllAlarmsLocked(false);
                    rebatchAllAlarmsLocked(false);
                    restorePendingWhileIdleAlarmsLocked();
                    restorePendingWhileIdleAlarmsLocked();
                }
                }
                if (mNextWakeFromIdle == alarm) {
                    mNextWakeFromIdle = null;
                    rebatchAllAlarmsLocked(false);
                }


                // Recurring alarms may have passed several alarm intervals while the
                // Recurring alarms may have passed several alarm intervals while the
                // phone was asleep or off, so pass a trigger count when sending them.
                // phone was asleep or off, so pass a trigger count when sending them.
@@ -1725,6 +1768,12 @@ class AlarmManagerService extends SystemService {
                    pw.print(" repeatInterval="); pw.print(repeatInterval);
                    pw.print(" repeatInterval="); pw.print(repeatInterval);
                    pw.print(" count="); pw.print(count);
                    pw.print(" count="); pw.print(count);
                    pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
                    pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
            if (alarmClock != null) {
                pw.print(prefix); pw.println("Alarm clock:");
                pw.print(prefix); pw.print("  triggerTime=");
                pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
                pw.print(prefix); pw.print("  showIntent="); pw.println(alarmClock.getShowIntent());
            }
            pw.print(prefix); pw.print("operation="); pw.println(operation);
            pw.print(prefix); pw.print("operation="); pw.println(operation);
        }
        }
    }
    }
@@ -1762,11 +1811,11 @@ class AlarmManagerService extends SystemService {
        }
        }
    }
    }


    static long fuzzForDuration(long duration) {
    static int fuzzForDuration(long duration) {
        if (duration < 15*60*1000) {
        if (duration < 15*60*1000) {
            // If the duration until the time is less than 15 minutes, the maximum fuzz
            // If the duration until the time is less than 15 minutes, the maximum fuzz
            // is the duration.
            // is the duration.
            return duration;
            return (int)duration;
        } else if (duration < 90*60*1000) {
        } else if (duration < 90*60*1000) {
            // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
            // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
            return 15*60*1000;
            return 15*60*1000;
@@ -1824,7 +1873,7 @@ class AlarmManagerService extends SystemService {
                    mWakeLock.acquire();
                    mWakeLock.acquire();
                }
                }
                final InFlight inflight = new InFlight(AlarmManagerService.this,
                final InFlight inflight = new InFlight(AlarmManagerService.this,
                        alarm.operation, alarm.workSource, alarm.type, alarm.tag);
                        alarm.operation, alarm.workSource, alarm.type, alarm.tag, nowELAPSED);
                mInFlight.add(inflight);
                mInFlight.add(inflight);
                mBroadcastRefCount++;
                mBroadcastRefCount++;


+7 −0
Original line number Original line Diff line number Diff line
@@ -173,6 +173,13 @@ option java_package com.android.server
# ---------------------------
# ---------------------------
33000 wp_wallpaper_crashed (component|3)
33000 wp_wallpaper_crashed (component|3)


# ---------------------------
# Device idle
# ---------------------------
34000 device_idle (state|1|5), (reason|3)
34001 device_idle_step
34002 device_idle_wake_from_idle (is_idle|1|5), (reason|3)



# ---------------------------
# ---------------------------
# ConnectivityService.java
# ConnectivityService.java
+26 −3
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@ import android.view.Display;
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.IBatteryStats;
import com.android.server.SystemService;
import com.android.server.SystemService;
import com.android.server.am.BatteryStatsService;
import com.android.server.am.BatteryStatsService;
import com.android.server.EventLogTags;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
@@ -100,6 +101,11 @@ public class DeviceIdleController extends SystemService {
     * Scaling factor to apply to current idle timeout each time we cycle through that state.
     * Scaling factor to apply to current idle timeout each time we cycle through that state.
     */
     */
    private static final float DEFAULT_IDLE_FACTOR = 2f;
    private static final float DEFAULT_IDLE_FACTOR = 2f;
    /**
     * This is the minimum time we will allow until the next upcoming alarm for us to
     * actually go in to idle mode.
     */
    private static final long DEFAULT_MIN_TIME_TO_ALARM = 60*60*1000L;


    private AlarmManager mAlarmManager;
    private AlarmManager mAlarmManager;
    private IBatteryStats mBatteryStats;
    private IBatteryStats mBatteryStats;
@@ -239,7 +245,7 @@ public class DeviceIdleController extends SystemService {
            becomeInactiveIfAppropriateLocked();
            becomeInactiveIfAppropriateLocked();
        } else if (screenOn) {
        } else if (screenOn) {
            mScreenOn = true;
            mScreenOn = true;
            becomeActiveLocked();
            becomeActiveLocked("screen");
        }
        }
    }
    }


@@ -249,12 +255,13 @@ public class DeviceIdleController extends SystemService {
            becomeInactiveIfAppropriateLocked();
            becomeInactiveIfAppropriateLocked();
        } else if (charging) {
        } else if (charging) {
            mCharging = charging;
            mCharging = charging;
            becomeActiveLocked();
            becomeActiveLocked("charging");
        }
        }
    }
    }


    void becomeActiveLocked() {
    void becomeActiveLocked(String reason) {
        if (mState != STATE_ACTIVE) {
        if (mState != STATE_ACTIVE) {
            EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason);
            mLocalPowerManager.setDeviceIdleMode(false);
            mLocalPowerManager.setDeviceIdleMode(false);
            try {
            try {
                mNetworkPolicyManager.setDeviceIdleMode(false);
                mNetworkPolicyManager.setDeviceIdleMode(false);
@@ -281,10 +288,22 @@ public class DeviceIdleController extends SystemService {
            mNextIdlePendingDelay = 0;
            mNextIdlePendingDelay = 0;
            mNextIdleDelay = 0;
            mNextIdleDelay = 0;
            scheduleAlarmLocked(mInactiveTimeout, false);
            scheduleAlarmLocked(mInactiveTimeout, false);
            EventLogTags.writeDeviceIdle(mState, "no activity");
        }
        }
    }
    }


    void stepIdleStateLocked() {
    void stepIdleStateLocked() {
        EventLogTags.writeDeviceIdleStep();

        final long now = SystemClock.elapsedRealtime();
        if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
            // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
            if (mState != STATE_ACTIVE) {
                becomeActiveLocked("alarm");
            }
            return;
        }

        switch (mState) {
        switch (mState) {
            case STATE_INACTIVE:
            case STATE_INACTIVE:
                // We have now been inactive long enough, it is time to start looking
                // We have now been inactive long enough, it is time to start looking
@@ -295,6 +314,7 @@ public class DeviceIdleController extends SystemService {
                mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT;
                mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT;
                mNextIdleDelay = DEFAULT_IDLE_TIMEOUT;
                mNextIdleDelay = DEFAULT_IDLE_TIMEOUT;
                mState = STATE_IDLE_PENDING;
                mState = STATE_IDLE_PENDING;
                EventLogTags.writeDeviceIdle(mState, "step");
                break;
                break;
            case STATE_IDLE_PENDING:
            case STATE_IDLE_PENDING:
                // We have been waiting to become idle, and now it is time!  This is the
                // We have been waiting to become idle, and now it is time!  This is the
@@ -307,6 +327,7 @@ public class DeviceIdleController extends SystemService {
                    mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT;
                    mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT;
                }
                }
                mState = STATE_IDLE;
                mState = STATE_IDLE;
                EventLogTags.writeDeviceIdle(mState, "step");
                mLocalPowerManager.setDeviceIdleMode(true);
                mLocalPowerManager.setDeviceIdleMode(true);
                try {
                try {
                    mNetworkPolicyManager.setDeviceIdleMode(true);
                    mNetworkPolicyManager.setDeviceIdleMode(true);
@@ -323,6 +344,7 @@ public class DeviceIdleController extends SystemService {
                    mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT;
                    mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT;
                }
                }
                mState = STATE_IDLE_PENDING;
                mState = STATE_IDLE_PENDING;
                EventLogTags.writeDeviceIdle(mState, "step");
                mLocalPowerManager.setDeviceIdleMode(false);
                mLocalPowerManager.setDeviceIdleMode(false);
                try {
                try {
                    mNetworkPolicyManager.setDeviceIdleMode(false);
                    mNetworkPolicyManager.setDeviceIdleMode(false);
@@ -352,6 +374,7 @@ public class DeviceIdleController extends SystemService {
            }
            }
            mState = STATE_ACTIVE;
            mState = STATE_ACTIVE;
            mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT;
            mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT;
            EventLogTags.writeDeviceIdle(mState, "motion");
            becomeInactiveIfAppropriateLocked();
            becomeInactiveIfAppropriateLocked();
        }
        }
    }
    }