private static final boolean COMPRESS_TIME = false;
- private static final int EVENT_BUFFER_SIZE = 40;
+ private static final int EVENT_BUFFER_SIZE = 100;
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
private long mNextAlarmTime;
private long mNextIdlePendingDelay;
private long mNextIdleDelay;
+ private long mNextLightIdleDelay;
private long mNextLightAlarmTime;
private long mCurIdleBudget;
private long mMaintenanceStartTime;
}
};
+ private boolean mMaintenanceMinCheckScheduled;
+
private final BroadcastReceiver mIdleStartedDoneReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
decActiveIdleOps();
*/
private final class Constants extends ContentObserver {
// Key names stored in the settings value.
+ private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
+ = "light_after_inactive_to";
private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
+ private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
+ private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
= "light_idle_maintenance_min_budget";
private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
"sms_temp_app_whitelist_duration";
/**
- * This is the time, after becoming inactive, that we will start going
- * in to light-weight idle mode.
+ * This is the time, after becoming inactive, that we go in to the first
+ * light-weight idle mode.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
+ */
+ public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
+
+ /**
+ * This is the initial time that we will run in idle maintenance mode.
* @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_LIGHT_IDLE_TIMEOUT
*/
public long LIGHT_IDLE_TIMEOUT;
/**
+ * Scaling factor to apply to the light idle mode time each time we complete a cycle.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_LIGHT_IDLE_FACTOR
+ */
+ public float LIGHT_IDLE_FACTOR;
+
+ /**
+ * This is the maximum time we will run in idle maintenence mode.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
+ */
+ public long LIGHT_MAX_IDLE_TIMEOUT;
+
+ /**
* This is the minimum amount of time we want to make available for maintenance mode
* when lightly idling. That is, we will always have at least this amount of time
* available maintenance before timing out and cutting off maintenance mode.
Slog.e(TAG, "Bad device idle settings", e);
}
+ LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(
+ KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
+ !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT,
+ !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
+ LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
+ 2f);
+ LIGHT_MAX_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_MAX_IDLE_TIMEOUT,
!COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getLong(
KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
void dump(PrintWriter pw) {
pw.println(" Settings:");
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
+ TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw);
+ pw.println();
+
pw.print(" "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
pw.println();
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
+ pw.print(LIGHT_IDLE_FACTOR);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("=");
+ TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw);
+ pw.println();
+
pw.print(" "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); pw.print("=");
TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, pw);
pw.println();
mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
mCurIdleBudget = 0;
mMaintenanceStartTime = 0;
- mAlarmManager.cancel(mMaintenanceMinCheckListener);
+ if (mMaintenanceMinCheckScheduled) {
+ mAlarmManager.cancel(mMaintenanceMinCheckListener);
+ mMaintenanceMinCheckScheduled = false;
+ }
resetIdleManagementLocked();
resetLightIdleManagementLocked();
addEvent(EVENT_NORMAL);
mLightState = LIGHT_STATE_INACTIVE;
if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
resetLightIdleManagementLocked();
- scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
+ scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
}
}
void resetIdleManagementLocked() {
mNextIdlePendingDelay = 0;
mNextIdleDelay = 0;
+ mNextLightIdleDelay = 0;
cancelAlarmLocked();
cancelLocatingLocked();
stopMonitoringMotionLocked();
switch (mLightState) {
case LIGHT_STATE_INACTIVE:
mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
+ // Reset the upcoming idle delays.
+ mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
mMaintenanceStartTime = 0;
case LIGHT_STATE_IDLE_MAINTENANCE:
if (mMaintenanceStartTime != 0) {
}
}
mMaintenanceStartTime = 0;
- scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
+ scheduleLightAlarmLocked(mNextLightIdleDelay);
+ mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
+ (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
+ if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {
+ mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
+ }
if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
mLightState = LIGHT_STATE_IDLE;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
addEvent(EVENT_LIGHT_IDLE);
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
- mAlarmManager.cancel(mMaintenanceMinCheckListener);
+ if (mMaintenanceMinCheckScheduled) {
+ mAlarmManager.cancel(mMaintenanceMinCheckListener);
+ mMaintenanceMinCheckScheduled = false;
+ }
break;
case LIGHT_STATE_IDLE:
// We have been idling long enough, now it is time to do some work.
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME,
mMaintenanceStartTime + mConstants.MIN_LIGHT_MAINTENANCE_TIME,
"DeviceIdleController.maint-check", mMaintenanceMinCheckListener, mHandler);
+ mMaintenanceMinCheckScheduled = true;
break;
}
}
cancelAlarmLocked();
cancelLocatingLocked();
mAnyMotionDetector.stop();
+
case STATE_IDLE_MAINTENANCE:
scheduleAlarmLocked(mNextIdleDelay, true);
if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
+ if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
+ mNextIdleDelay = mConstants.IDLE_TIMEOUT;
+ }
mState = STATE_IDLE;
if (mLightState != LIGHT_STATE_OVERRIDE) {
mLightState = LIGHT_STATE_OVERRIDE;
EventLogTags.writeDeviceIdle(mState, reason);
addEvent(EVENT_DEEP_IDLE);
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
- mAlarmManager.cancel(mMaintenanceMinCheckListener);
+ if (mMaintenanceMinCheckScheduled) {
+ mAlarmManager.cancel(mMaintenanceMinCheckListener);
+ mMaintenanceMinCheckScheduled = false;
+ }
break;
case STATE_IDLE:
// We have been idling long enough, now it is time to do some work.
mMaintenanceStartTime = SystemClock.elapsedRealtime();
mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
(long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
+ if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
+ mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
+ }
mState = STATE_IDLE_MAINTENANCE;
EventLogTags.writeDeviceIdle(mState, reason);
addEvent(EVENT_DEEP_MAINTENANCE);
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME,
mMaintenanceStartTime + mConstants.MIN_DEEP_MAINTENANCE_TIME,
"DeviceIdleController.maint-check", mMaintenanceMinCheckListener, mHandler);
+ mMaintenanceMinCheckScheduled = true;
break;
}
}
TimeUtils.formatDuration(mNextIdleDelay, pw);
pw.println();
}
+ if (mNextLightIdleDelay != 0) {
+ pw.print(" mNextIdleDelay=");
+ TimeUtils.formatDuration(mNextLightIdleDelay, pw);
+ pw.println();
+ }
if (mNextLightAlarmTime != 0) {
pw.print(" mNextLightAlarmTime=");
TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw);
pw.println();
}
+ if (mMaintenanceMinCheckScheduled) {
+ pw.print(" mMaintenanceMinCheckScheduled=");
+ pw.println(mMaintenanceMinCheckScheduled);
+ }
if (mJobsActive) {
pw.print(" mJobsActive="); pw.println(mJobsActive);
}