Loading core/java/android/app/AlarmManager.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -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. * * Loading core/java/android/app/IAlarmManager.aidl +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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); } } Loading services/core/java/com/android/server/AlarmManagerService.java +77 −28 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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; } } Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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(), Loading Loading @@ -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: "); Loading Loading @@ -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(); } } Loading Loading @@ -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); } } Loading Loading @@ -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(); Loading Loading @@ -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. Loading Loading @@ -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); } } } } Loading Loading @@ -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; Loading Loading @@ -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++; Loading services/core/java/com/android/server/EventLogTags.logtags +7 −0 Original line number Original line Diff line number Diff line Loading @@ -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 Loading services/core/java/com/android/server/power/DeviceIdleController.java +26 −3 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -239,7 +245,7 @@ public class DeviceIdleController extends SystemService { becomeInactiveIfAppropriateLocked(); becomeInactiveIfAppropriateLocked(); } else if (screenOn) { } else if (screenOn) { mScreenOn = true; mScreenOn = true; becomeActiveLocked(); becomeActiveLocked("screen"); } } } } Loading @@ -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); Loading @@ -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 Loading @@ -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 Loading @@ -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); Loading @@ -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); Loading Loading @@ -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(); } } } } Loading Loading
core/java/android/app/AlarmManager.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -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. * * Loading
core/java/android/app/IAlarmManager.aidl +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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); } } Loading
services/core/java/com/android/server/AlarmManagerService.java +77 −28 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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; } } Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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(), Loading Loading @@ -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: "); Loading Loading @@ -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(); } } Loading Loading @@ -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); } } Loading Loading @@ -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(); Loading Loading @@ -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. Loading Loading @@ -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); } } } } Loading Loading @@ -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; Loading Loading @@ -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++; Loading
services/core/java/com/android/server/EventLogTags.logtags +7 −0 Original line number Original line Diff line number Diff line Loading @@ -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 Loading
services/core/java/com/android/server/power/DeviceIdleController.java +26 −3 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -239,7 +245,7 @@ public class DeviceIdleController extends SystemService { becomeInactiveIfAppropriateLocked(); becomeInactiveIfAppropriateLocked(); } else if (screenOn) { } else if (screenOn) { mScreenOn = true; mScreenOn = true; becomeActiveLocked(); becomeActiveLocked("screen"); } } } } Loading @@ -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); Loading @@ -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 Loading @@ -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 Loading @@ -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); Loading @@ -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); Loading Loading @@ -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(); } } } } Loading