Loading services/core/java/com/android/server/DeviceIdleController.java +17 −6 Original line number Diff line number Diff line Loading @@ -45,17 +45,20 @@ import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.TimeUtils; import android.util.Xml; import android.view.Display; import com.android.internal.app.IBatteryStats; import com.android.internal.os.AtomicFile; import com.android.internal.os.BackgroundThread; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; import com.android.server.am.BatteryStatsService; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -75,6 +78,8 @@ import java.io.PrintWriter; public class DeviceIdleController extends SystemService { private static final String TAG = "DeviceIdleController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final String SERVICE_NAME = "deviceidle"; private static final String ACTION_STEP_IDLE_STATE = Loading @@ -88,17 +93,20 @@ public class DeviceIdleController extends SystemService { * immediately after going inactive just because we don't want to be continually running * the significant motion sensor whenever the screen is off. */ private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; private static final long DEFAULT_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L : 2 * 60 * 1000L; /** * This is the time, after seeing motion, that we wait after becoming inactive from * that until we start looking for motion again. */ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !DEBUG ? 10*60*1000L : 60 * 1000L; /** * This is the time, after the inactive timeout elapses, that we will wait looking * for significant motion until we truly consider the device to be idle. */ private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L : 2 * 60 * 1000L; /** * This is the initial time, after being idle, that we will allow ourself to be back * in the IDLE_PENDING state allowing the system to run normally until we return to idle. Loading @@ -117,11 +125,13 @@ public class DeviceIdleController extends SystemService { * This is the initial time that we want to sit in the idle state before waking up * again to return to pending idle and allowing normal work to run. */ private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; private static final long DEFAULT_IDLE_TIMEOUT = !DEBUG ? 60*60*1000L : 5 * 60 * 1000L; /** * Maximum idle duration we will be allowed to use. */ private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; private static final long DEFAULT_MAX_IDLE_TIMEOUT = !DEBUG ? 6*60*60*1000L : 10 * 60 * 1000L; /** * Scaling factor to apply to current idle timeout each time we cycle through that state. */ Loading @@ -130,7 +140,8 @@ public class DeviceIdleController extends SystemService { * 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 static final long DEFAULT_MIN_TIME_TO_ALARM = !DEBUG ? 60*60*1000L : 5 * 60 * 1000L; private AlarmManager mAlarmManager; private IBatteryStats mBatteryStats; Loading services/usage/java/com/android/server/usage/UsageStatsService.java +103 −5 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.os.Handler; import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; Loading @@ -58,6 +59,7 @@ import android.os.UserManager; import android.provider.Settings; import android.util.ArraySet; import android.util.AtomicFile; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.view.Display; Loading Loading @@ -87,13 +89,21 @@ public class UsageStatsService extends SystemService implements static final String TAG = "UsageStatsService"; static final boolean DEBUG = false; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final long TEN_SECONDS = 10 * 1000; private static final long ONE_MINUTE = 60 * 1000; private static final long TWENTY_MINUTES = 20 * 60 * 1000; private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 2L * 24 * 60 * 60 * 1000; // 1 day static final long DEFAULT_CHECK_IDLE_INTERVAL = 8 * 3600 * 1000; // 8 hours static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = DEBUG ? ONE_MINUTE * 4 : 1L * 24 * 60 * 60 * 1000; // 1 day static final long DEFAULT_CHECK_IDLE_INTERVAL = DEBUG ? ONE_MINUTE : 8 * 3600 * 1000; // 8 hours static final long DEFAULT_PAROLE_INTERVAL = DEBUG ? ONE_MINUTE * 10 : 24 * 60 * 60 * 1000L; // 24 hours between paroles static final long DEFAULT_PAROLE_DURATION = DEBUG ? ONE_MINUTE * 2 : 10 * 60 * 1000L; // 10 minutes // Handler message types. static final int MSG_REPORT_EVENT = 0; Loading @@ -102,6 +112,8 @@ public class UsageStatsService extends SystemService implements static final int MSG_INFORM_LISTENERS = 3; static final int MSG_FORCE_IDLE_STATE = 4; static final int MSG_CHECK_IDLE_STATES = 5; static final int MSG_CHECK_PAROLE_TIMEOUT = 6; static final int MSG_PAROLE_END_TIMEOUT = 7; private final Object mLock = new Object(); Handler mHandler; Loading @@ -110,14 +122,16 @@ public class UsageStatsService extends SystemService implements AppWidgetManager mAppWidgetManager; IDeviceIdleController mDeviceIdleController; private DisplayManager mDisplayManager; private PowerManager mPowerManager; private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private File mUsageStatsDir; long mRealTimeSnapshot; long mSystemTimeSnapshot; boolean mAppIdleParoled; private boolean mScreenOn; private long mLastAppIdleParoledTime; long mAppIdleDurationMillis; long mCheckIdleIntervalMillis = DEFAULT_CHECK_IDLE_INTERVAL; long mScreenOnTime; Loading Loading @@ -152,6 +166,7 @@ public class UsageStatsService extends SystemService implements IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); getContext().registerReceiver(new DeviceStateReceiver(), deviceStates); synchronized (mLock) { cleanUpRemovedUsersLocked(); Loading Loading @@ -179,6 +194,8 @@ public class UsageStatsService extends SystemService implements ServiceManager.getService(DeviceIdleController.SERVICE_NAME)); mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); mScreenOnSystemTimeSnapshot = System.currentTimeMillis(); synchronized (this) { mScreenOnTime = readScreenOnTimeLocked(); Loading Loading @@ -216,6 +233,8 @@ public class UsageStatsService extends SystemService implements if (BatteryManager.ACTION_CHARGING.equals(action) || BatteryManager.ACTION_DISCHARGING.equals(action)) { setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action)); } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) { onDeviceIdleModeChanged(); } } } Loading Loading @@ -270,15 +289,41 @@ public class UsageStatsService extends SystemService implements } } /** Paroled here means temporary pardon from being inactive */ void setAppIdleParoled(boolean paroled) { synchronized (mLock) { if (mAppIdleParoled != paroled) { mAppIdleParoled = paroled; if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleParoled); if (paroled) { mLastAppIdleParoledTime = checkAndGetTimeLocked(); postNextParoleTimeout(); } postCheckIdleStates(); } } } private void postNextParoleTimeout() { if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT"); mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT); // Compute when the next parole needs to happen. We check more frequently than necessary // since the message handler delays are based on elapsedRealTime and not wallclock time. // The comparison is done in wallclock time. long timeLeft = (mLastAppIdleParoledTime + DEFAULT_PAROLE_INTERVAL) - checkAndGetTimeLocked(); if (timeLeft < 0) { timeLeft = 0; } mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft / 10); } private void postParoleEndTimeout() { if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT"); mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT); mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, DEFAULT_PAROLE_DURATION); } void postCheckIdleStates() { mHandler.removeMessages(MSG_CHECK_IDLE_STATES); mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES); Loading Loading @@ -313,6 +358,24 @@ public class UsageStatsService extends SystemService implements mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis); } /** Check if it's been a while since last parole and let idle apps do some work */ void checkParoleTimeout() { synchronized (mLock) { if (!mAppIdleParoled) { final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime; if (timeSinceLastParole > DEFAULT_PAROLE_INTERVAL) { if (DEBUG) Slog.d(TAG, "Crossed default parole interval"); setAppIdleParoled(true); // Make sure it ends at some point postParoleEndTimeout(); } else { if (DEBUG) Slog.d(TAG, "Not long enough to go to parole"); postNextParoleTimeout(); } } } } void updateDisplayLocked() { boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState() != Display.STATE_OFF; Loading Loading @@ -368,6 +431,23 @@ public class UsageStatsService extends SystemService implements } } void onDeviceIdleModeChanged() { final boolean deviceIdle = mPowerManager.isDeviceIdleMode(); if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle); synchronized (mLock) { final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime; if (!deviceIdle && timeSinceLastParole >= DEFAULT_PAROLE_INTERVAL) { if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false"); postNextParoleTimeout(); setAppIdleParoled(true); } else if (deviceIdle) { if (DEBUG) Slog.i(TAG, "Device idle, back to prison"); setAppIdleParoled(false); } } } private static void deleteRecursively(File f) { File[] files = f.listFiles(); if (files != null) { Loading Loading @@ -400,12 +480,20 @@ public class UsageStatsService extends SystemService implements final long actualSystemTime = System.currentTimeMillis(); final long actualRealtime = SystemClock.elapsedRealtime(); final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; boolean resetBeginIdleTime = false; if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { // The time has changed. // Check if it's severe enough a change to reset screenOnTime if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) { mScreenOnSystemTimeSnapshot = actualSystemTime; mScreenOnTime = 0; resetBeginIdleTime = true; } final int userCount = mUserState.size(); for (int i = 0; i < userCount; i++) { final UserUsageStatsService service = mUserState.valueAt(i); service.onTimeChanged(expectedSystemTime, actualSystemTime); service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime); } mRealTimeSnapshot = actualRealtime; mSystemTimeSnapshot = actualSystemTime; Loading Loading @@ -718,6 +806,16 @@ public class UsageStatsService extends SystemService implements case MSG_CHECK_IDLE_STATES: checkIdleStates(); break; case MSG_CHECK_PAROLE_TIMEOUT: checkParoleTimeout(); break; case MSG_PAROLE_END_TIMEOUT: if (DEBUG) Slog.d(TAG, "Ending parole"); setAppIdleParoled(false); break; default: super.handleMessage(msg); break; Loading services/usage/java/com/android/server/usage/UserUsageStatsService.java +12 −5 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ class UserUsageStatsService { // By calling loadActiveStats, we will // generate new stats for each bucket. loadActiveStats(currentTimeMillis, false); loadActiveStats(currentTimeMillis,/*force=*/ false, /*resetBeginIdleTime=*/ false); } else { // Set up the expiry date to be one day from the latest daily stat. // This may actually be today and we will rollover on the first event Loading Loading @@ -167,10 +167,10 @@ class UserUsageStatsService { persistActiveStats(); } void onTimeChanged(long oldTime, long newTime) { void onTimeChanged(long oldTime, long newTime, boolean resetBeginIdleTime) { persistActiveStats(); mDatabase.onTimeChanged(newTime - oldTime); loadActiveStats(newTime, true); loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime); } void reportEvent(UsageEvents.Event event, long deviceUsageTime) { Loading Loading @@ -431,7 +431,7 @@ class UserUsageStatsService { persistActiveStats(); mDatabase.prune(currentTimeMillis); loadActiveStats(currentTimeMillis, false); loadActiveStats(currentTimeMillis, /*force=*/ false, /*resetBeginIdleTime=*/ false); final int continueCount = continuePreviousDay.size(); for (int i = 0; i < continueCount; i++) { Loading Loading @@ -460,7 +460,8 @@ class UserUsageStatsService { /** * @param force To force all in-memory stats to be reloaded. */ private void loadActiveStats(final long currentTimeMillis, boolean force) { private void loadActiveStats(final long currentTimeMillis, boolean force, boolean resetBeginIdleTime) { final UnixCalendar tempCal = mDailyExpiryDate; for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) { tempCal.setTimeInMillis(currentTimeMillis); Loading Loading @@ -496,6 +497,12 @@ class UserUsageStatsService { mCurrentStats[intervalType].beginTime = tempCal.getTimeInMillis(); mCurrentStats[intervalType].endTime = currentTimeMillis; } if (resetBeginIdleTime) { for (UsageStats usageStats : mCurrentStats[intervalType].packageStats.values()) { usageStats.mBeginIdleTime = 0; } } } mStatsChanged = false; mDailyExpiryDate.setTimeInMillis(currentTimeMillis); Loading Loading
services/core/java/com/android/server/DeviceIdleController.java +17 −6 Original line number Diff line number Diff line Loading @@ -45,17 +45,20 @@ import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.TimeUtils; import android.util.Xml; import android.view.Display; import com.android.internal.app.IBatteryStats; import com.android.internal.os.AtomicFile; import com.android.internal.os.BackgroundThread; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; import com.android.server.am.BatteryStatsService; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -75,6 +78,8 @@ import java.io.PrintWriter; public class DeviceIdleController extends SystemService { private static final String TAG = "DeviceIdleController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final String SERVICE_NAME = "deviceidle"; private static final String ACTION_STEP_IDLE_STATE = Loading @@ -88,17 +93,20 @@ public class DeviceIdleController extends SystemService { * immediately after going inactive just because we don't want to be continually running * the significant motion sensor whenever the screen is off. */ private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; private static final long DEFAULT_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L : 2 * 60 * 1000L; /** * This is the time, after seeing motion, that we wait after becoming inactive from * that until we start looking for motion again. */ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !DEBUG ? 10*60*1000L : 60 * 1000L; /** * This is the time, after the inactive timeout elapses, that we will wait looking * for significant motion until we truly consider the device to be idle. */ private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L : 2 * 60 * 1000L; /** * This is the initial time, after being idle, that we will allow ourself to be back * in the IDLE_PENDING state allowing the system to run normally until we return to idle. Loading @@ -117,11 +125,13 @@ public class DeviceIdleController extends SystemService { * This is the initial time that we want to sit in the idle state before waking up * again to return to pending idle and allowing normal work to run. */ private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; private static final long DEFAULT_IDLE_TIMEOUT = !DEBUG ? 60*60*1000L : 5 * 60 * 1000L; /** * Maximum idle duration we will be allowed to use. */ private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; private static final long DEFAULT_MAX_IDLE_TIMEOUT = !DEBUG ? 6*60*60*1000L : 10 * 60 * 1000L; /** * Scaling factor to apply to current idle timeout each time we cycle through that state. */ Loading @@ -130,7 +140,8 @@ public class DeviceIdleController extends SystemService { * 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 static final long DEFAULT_MIN_TIME_TO_ALARM = !DEBUG ? 60*60*1000L : 5 * 60 * 1000L; private AlarmManager mAlarmManager; private IBatteryStats mBatteryStats; Loading
services/usage/java/com/android/server/usage/UsageStatsService.java +103 −5 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.os.Handler; import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; Loading @@ -58,6 +59,7 @@ import android.os.UserManager; import android.provider.Settings; import android.util.ArraySet; import android.util.AtomicFile; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.view.Display; Loading Loading @@ -87,13 +89,21 @@ public class UsageStatsService extends SystemService implements static final String TAG = "UsageStatsService"; static final boolean DEBUG = false; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final long TEN_SECONDS = 10 * 1000; private static final long ONE_MINUTE = 60 * 1000; private static final long TWENTY_MINUTES = 20 * 60 * 1000; private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 2L * 24 * 60 * 60 * 1000; // 1 day static final long DEFAULT_CHECK_IDLE_INTERVAL = 8 * 3600 * 1000; // 8 hours static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = DEBUG ? ONE_MINUTE * 4 : 1L * 24 * 60 * 60 * 1000; // 1 day static final long DEFAULT_CHECK_IDLE_INTERVAL = DEBUG ? ONE_MINUTE : 8 * 3600 * 1000; // 8 hours static final long DEFAULT_PAROLE_INTERVAL = DEBUG ? ONE_MINUTE * 10 : 24 * 60 * 60 * 1000L; // 24 hours between paroles static final long DEFAULT_PAROLE_DURATION = DEBUG ? ONE_MINUTE * 2 : 10 * 60 * 1000L; // 10 minutes // Handler message types. static final int MSG_REPORT_EVENT = 0; Loading @@ -102,6 +112,8 @@ public class UsageStatsService extends SystemService implements static final int MSG_INFORM_LISTENERS = 3; static final int MSG_FORCE_IDLE_STATE = 4; static final int MSG_CHECK_IDLE_STATES = 5; static final int MSG_CHECK_PAROLE_TIMEOUT = 6; static final int MSG_PAROLE_END_TIMEOUT = 7; private final Object mLock = new Object(); Handler mHandler; Loading @@ -110,14 +122,16 @@ public class UsageStatsService extends SystemService implements AppWidgetManager mAppWidgetManager; IDeviceIdleController mDeviceIdleController; private DisplayManager mDisplayManager; private PowerManager mPowerManager; private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private File mUsageStatsDir; long mRealTimeSnapshot; long mSystemTimeSnapshot; boolean mAppIdleParoled; private boolean mScreenOn; private long mLastAppIdleParoledTime; long mAppIdleDurationMillis; long mCheckIdleIntervalMillis = DEFAULT_CHECK_IDLE_INTERVAL; long mScreenOnTime; Loading Loading @@ -152,6 +166,7 @@ public class UsageStatsService extends SystemService implements IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); getContext().registerReceiver(new DeviceStateReceiver(), deviceStates); synchronized (mLock) { cleanUpRemovedUsersLocked(); Loading Loading @@ -179,6 +194,8 @@ public class UsageStatsService extends SystemService implements ServiceManager.getService(DeviceIdleController.SERVICE_NAME)); mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); mScreenOnSystemTimeSnapshot = System.currentTimeMillis(); synchronized (this) { mScreenOnTime = readScreenOnTimeLocked(); Loading Loading @@ -216,6 +233,8 @@ public class UsageStatsService extends SystemService implements if (BatteryManager.ACTION_CHARGING.equals(action) || BatteryManager.ACTION_DISCHARGING.equals(action)) { setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action)); } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) { onDeviceIdleModeChanged(); } } } Loading Loading @@ -270,15 +289,41 @@ public class UsageStatsService extends SystemService implements } } /** Paroled here means temporary pardon from being inactive */ void setAppIdleParoled(boolean paroled) { synchronized (mLock) { if (mAppIdleParoled != paroled) { mAppIdleParoled = paroled; if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleParoled); if (paroled) { mLastAppIdleParoledTime = checkAndGetTimeLocked(); postNextParoleTimeout(); } postCheckIdleStates(); } } } private void postNextParoleTimeout() { if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT"); mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT); // Compute when the next parole needs to happen. We check more frequently than necessary // since the message handler delays are based on elapsedRealTime and not wallclock time. // The comparison is done in wallclock time. long timeLeft = (mLastAppIdleParoledTime + DEFAULT_PAROLE_INTERVAL) - checkAndGetTimeLocked(); if (timeLeft < 0) { timeLeft = 0; } mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft / 10); } private void postParoleEndTimeout() { if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT"); mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT); mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, DEFAULT_PAROLE_DURATION); } void postCheckIdleStates() { mHandler.removeMessages(MSG_CHECK_IDLE_STATES); mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES); Loading Loading @@ -313,6 +358,24 @@ public class UsageStatsService extends SystemService implements mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis); } /** Check if it's been a while since last parole and let idle apps do some work */ void checkParoleTimeout() { synchronized (mLock) { if (!mAppIdleParoled) { final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime; if (timeSinceLastParole > DEFAULT_PAROLE_INTERVAL) { if (DEBUG) Slog.d(TAG, "Crossed default parole interval"); setAppIdleParoled(true); // Make sure it ends at some point postParoleEndTimeout(); } else { if (DEBUG) Slog.d(TAG, "Not long enough to go to parole"); postNextParoleTimeout(); } } } } void updateDisplayLocked() { boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState() != Display.STATE_OFF; Loading Loading @@ -368,6 +431,23 @@ public class UsageStatsService extends SystemService implements } } void onDeviceIdleModeChanged() { final boolean deviceIdle = mPowerManager.isDeviceIdleMode(); if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle); synchronized (mLock) { final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime; if (!deviceIdle && timeSinceLastParole >= DEFAULT_PAROLE_INTERVAL) { if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false"); postNextParoleTimeout(); setAppIdleParoled(true); } else if (deviceIdle) { if (DEBUG) Slog.i(TAG, "Device idle, back to prison"); setAppIdleParoled(false); } } } private static void deleteRecursively(File f) { File[] files = f.listFiles(); if (files != null) { Loading Loading @@ -400,12 +480,20 @@ public class UsageStatsService extends SystemService implements final long actualSystemTime = System.currentTimeMillis(); final long actualRealtime = SystemClock.elapsedRealtime(); final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; boolean resetBeginIdleTime = false; if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { // The time has changed. // Check if it's severe enough a change to reset screenOnTime if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) { mScreenOnSystemTimeSnapshot = actualSystemTime; mScreenOnTime = 0; resetBeginIdleTime = true; } final int userCount = mUserState.size(); for (int i = 0; i < userCount; i++) { final UserUsageStatsService service = mUserState.valueAt(i); service.onTimeChanged(expectedSystemTime, actualSystemTime); service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime); } mRealTimeSnapshot = actualRealtime; mSystemTimeSnapshot = actualSystemTime; Loading Loading @@ -718,6 +806,16 @@ public class UsageStatsService extends SystemService implements case MSG_CHECK_IDLE_STATES: checkIdleStates(); break; case MSG_CHECK_PAROLE_TIMEOUT: checkParoleTimeout(); break; case MSG_PAROLE_END_TIMEOUT: if (DEBUG) Slog.d(TAG, "Ending parole"); setAppIdleParoled(false); break; default: super.handleMessage(msg); break; Loading
services/usage/java/com/android/server/usage/UserUsageStatsService.java +12 −5 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ class UserUsageStatsService { // By calling loadActiveStats, we will // generate new stats for each bucket. loadActiveStats(currentTimeMillis, false); loadActiveStats(currentTimeMillis,/*force=*/ false, /*resetBeginIdleTime=*/ false); } else { // Set up the expiry date to be one day from the latest daily stat. // This may actually be today and we will rollover on the first event Loading Loading @@ -167,10 +167,10 @@ class UserUsageStatsService { persistActiveStats(); } void onTimeChanged(long oldTime, long newTime) { void onTimeChanged(long oldTime, long newTime, boolean resetBeginIdleTime) { persistActiveStats(); mDatabase.onTimeChanged(newTime - oldTime); loadActiveStats(newTime, true); loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime); } void reportEvent(UsageEvents.Event event, long deviceUsageTime) { Loading Loading @@ -431,7 +431,7 @@ class UserUsageStatsService { persistActiveStats(); mDatabase.prune(currentTimeMillis); loadActiveStats(currentTimeMillis, false); loadActiveStats(currentTimeMillis, /*force=*/ false, /*resetBeginIdleTime=*/ false); final int continueCount = continuePreviousDay.size(); for (int i = 0; i < continueCount; i++) { Loading Loading @@ -460,7 +460,8 @@ class UserUsageStatsService { /** * @param force To force all in-memory stats to be reloaded. */ private void loadActiveStats(final long currentTimeMillis, boolean force) { private void loadActiveStats(final long currentTimeMillis, boolean force, boolean resetBeginIdleTime) { final UnixCalendar tempCal = mDailyExpiryDate; for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) { tempCal.setTimeInMillis(currentTimeMillis); Loading Loading @@ -496,6 +497,12 @@ class UserUsageStatsService { mCurrentStats[intervalType].beginTime = tempCal.getTimeInMillis(); mCurrentStats[intervalType].endTime = currentTimeMillis; } if (resetBeginIdleTime) { for (UsageStats usageStats : mCurrentStats[intervalType].packageStats.values()) { usageStats.mBeginIdleTime = 0; } } } mStatsChanged = false; mDailyExpiryDate.setTimeInMillis(currentTimeMillis); Loading