Loading core/java/android/os/BatteryStats.java +8 −3 Original line number Diff line number Diff line Loading @@ -1177,8 +1177,13 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_ALARM = 0x000e; // Record that we have decided we need to collect new stats data. public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f; // Event for a package becoming inactive due to being unused for a period of time. public static final int EVENT_PACKAGE_INACTIVE = 0x0010; // Event for a package becoming active due to an interaction. public static final int EVENT_PACKAGE_ACTIVE = 0x0011; // Number of event types. public static final int EVENT_COUNT = 0x0010; public static final int EVENT_COUNT = 0x0012; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); Loading Loading @@ -1835,12 +1840,12 @@ public abstract class BatteryStats implements Parcelable { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", "motion", "active", "pkginst", "pkgunin", "alarm", "stats" "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", "Esm", "Eac", "Epi", "Epu", "Eal", "Est" "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa" }; /** Loading services/usage/java/com/android/server/usage/AppIdleHistory.java +33 −16 Original line number Diff line number Diff line Loading @@ -27,34 +27,27 @@ import com.android.internal.util.IndentingPrintWriter; */ public class AppIdleHistory { private SparseArray<ArrayMap<String,byte[]>> idleHistory = new SparseArray<>(); private SparseArray<ArrayMap<String,byte[]>> mIdleHistory = new SparseArray<>(); private long lastPeriod = 0; private static final long ONE_MINUTE = 60 * 1000; private static final int HISTORY_SIZE = 100; private static final int FLAG_LAST_STATE = 2; private static final int FLAG_PARTIAL_ACTIVE = 1; private static final long PERIOD_DURATION = UsageStatsService.DEBUG ? ONE_MINUTE private static final long PERIOD_DURATION = UsageStatsService.COMPRESS_TIME ? ONE_MINUTE : 60 * ONE_MINUTE; public void addEntry(String packageName, int userId, boolean idle, long timeNow) { ArrayMap<String, byte[]> userHistory = idleHistory.get(userId); if (userHistory == null) { userHistory = new ArrayMap<>(); idleHistory.put(userId, userHistory); } byte[] packageHistory = userHistory.get(packageName); if (packageHistory == null) { packageHistory = new byte[HISTORY_SIZE]; userHistory.put(packageName, packageHistory); } ArrayMap<String, byte[]> userHistory = getUserHistory(userId); byte[] packageHistory = getPackageHistory(userHistory, packageName); long thisPeriod = timeNow / PERIOD_DURATION; // Has the period switched over? Slide all users' package histories if (lastPeriod != 0 && lastPeriod < thisPeriod && (thisPeriod - lastPeriod) < HISTORY_SIZE - 1) { int diff = (int) (thisPeriod - lastPeriod); final int NUSERS = idleHistory.size(); final int NUSERS = mIdleHistory.size(); for (int u = 0; u < NUSERS; u++) { userHistory = idleHistory.valueAt(u); userHistory = mIdleHistory.valueAt(u); for (byte[] history : userHistory.values()) { // Shift left System.arraycopy(history, diff, history, 0, HISTORY_SIZE - diff); Loading @@ -74,12 +67,36 @@ public class AppIdleHistory { } } private ArrayMap<String, byte[]> getUserHistory(int userId) { ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId); if (userHistory == null) { userHistory = new ArrayMap<>(); mIdleHistory.put(userId, userHistory); } return userHistory; } private byte[] getPackageHistory(ArrayMap<String, byte[]> userHistory, String packageName) { byte[] packageHistory = userHistory.get(packageName); if (packageHistory == null) { packageHistory = new byte[HISTORY_SIZE]; userHistory.put(packageName, packageHistory); } return packageHistory; } public void removeUser(int userId) { idleHistory.remove(userId); mIdleHistory.remove(userId); } public boolean isIdle(int userId, String packageName) { ArrayMap<String, byte[]> userHistory = getUserHistory(userId); byte[] packageHistory = getPackageHistory(userHistory, packageName); return (packageHistory[HISTORY_SIZE - 1] & FLAG_LAST_STATE) == 0; } public void dump(IndentingPrintWriter idpw, int userId) { ArrayMap<String, byte[]> userHistory = idleHistory.get(userId); ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId); if (userHistory == null) return; final int P = userHistory.size(); for (int p = 0; p < P; p++) { Loading services/usage/java/com/android/server/usage/UsageStatsService.java +73 −30 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.database.ContentObserver; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.Binder; import android.os.Environment; import android.os.Handler; Loading @@ -65,6 +66,7 @@ import android.util.SparseArray; import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import com.android.server.DeviceIdleController; Loading @@ -91,7 +93,7 @@ public class UsageStatsService extends SystemService implements static final String TAG = "UsageStatsService"; static final boolean DEBUG = false; private static final boolean COMPRESS_TIME = false; static final boolean COMPRESS_TIME = false; private static final long TEN_SECONDS = 10 * 1000; private static final long ONE_MINUTE = 60 * 1000; Loading Loading @@ -128,6 +130,7 @@ public class UsageStatsService extends SystemService implements IDeviceIdleController mDeviceIdleController; private DisplayManager mDisplayManager; private PowerManager mPowerManager; private IBatteryStats mBatteryStats; private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private File mUsageStatsDir; Loading Loading @@ -200,6 +203,8 @@ public class UsageStatsService extends SystemService implements mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class); mDeviceIdleController = IDeviceIdleController.Stub.asInterface( ServiceManager.getService(DeviceIdleController.SERVICE_NAME)); mBatteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); Loading Loading @@ -228,7 +233,7 @@ public class UsageStatsService extends SystemService implements } } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { if (userId >=0) { postCheckIdleStates(); postCheckIdleStates(userId); } } } Loading Loading @@ -307,7 +312,7 @@ public class UsageStatsService extends SystemService implements mLastAppIdleParoledTime = checkAndGetTimeLocked(); postNextParoleTimeout(); } postCheckIdleStates(); postCheckIdleStates(UserHandle.USER_ALL); } } } Loading @@ -332,22 +337,25 @@ public class UsageStatsService extends SystemService implements mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, DEFAULT_PAROLE_DURATION); } void postCheckIdleStates() { mHandler.removeMessages(MSG_CHECK_IDLE_STATES); mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES); void postCheckIdleStates(int userId) { mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); } /** Check all running users' apps to see if they enter an idle state. */ void checkIdleStates() { final int[] runningUsers; /** Check all running users' or specified user's apps to see if they enter an idle state. */ void checkIdleStates(int checkUserId) { final int[] userIds; try { runningUsers = ActivityManagerNative.getDefault().getRunningUserIds(); if (checkUserId == UserHandle.USER_ALL) { userIds = ActivityManagerNative.getDefault().getRunningUserIds(); } else { userIds = new int[] { checkUserId }; } } catch (RemoteException re) { return; } for (int i = 0; i < runningUsers.length; i++) { final int userId = runningUsers[i]; for (int i = 0; i < userIds.length; i++) { final int userId = userIds[i]; List<PackageInfo> packages = getContext().getPackageManager().getInstalledPackages( PackageManager.GET_DISABLED_COMPONENTS Loading @@ -355,17 +363,22 @@ public class UsageStatsService extends SystemService implements userId); synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); final long screenOnTime = getScreenOnTimeLocked(timeNow); UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); final int packageCount = packages.size(); for (int p = 0; p < packageCount; p++) { final String packageName = packages.get(p).packageName; final boolean isIdle = isAppIdleFiltered(packageName, userId, timeNow); final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow, screenOnTime); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, isIdle ? 1 : 0, packageName)); mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow); } } } mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0), mCheckIdleIntervalMillis); } /** Check if it's been a while since last parole and let idle apps do some work */ Loading @@ -386,6 +399,20 @@ public class UsageStatsService extends SystemService implements } } private void notifyBatteryStats(String packageName, int userId, boolean idle) { try { int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId); if (idle) { mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE, packageName, uid); } else { mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE, packageName, uid); } } catch (RemoteException re) { } } void updateDisplayLocked() { boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState() == Display.STATE_ON; Loading Loading @@ -545,7 +572,7 @@ public class UsageStatsService extends SystemService implements final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage); final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); service.reportEvent(event, getScreenOnTimeLocked(timeNow)); service.reportEvent(event, screenOnTime); // Inform listeners if necessary if ((event.mEventType == Event.MOVE_TO_FOREGROUND || event.mEventType == Event.MOVE_TO_BACKGROUND Loading @@ -555,6 +582,7 @@ public class UsageStatsService extends SystemService implements // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ 0, event.mPackage)); notifyBatteryStats(event.mPackage, userId, false); mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow); } } Loading Loading @@ -586,6 +614,9 @@ public class UsageStatsService extends SystemService implements // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ idle ? 1 : 0, packageName)); if (!idle) { notifyBatteryStats(packageName, userId, idle); } mAppIdleHistory.addEntry(packageName, userId, idle, timeNow); } } Loading Loading @@ -660,19 +691,20 @@ public class UsageStatsService extends SystemService implements } } private boolean isAppIdleUnfiltered(String packageName, int userId, long timeNow) { private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService, long timeNow, long screenOnTime) { synchronized (mLock) { final long screenOnTime = getScreenOnTimeLocked(timeNow); final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); long beginIdleTime = service.getBeginIdleTime(packageName); long lastUsedTime = service.getSystemLastUsedTime(packageName); return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); long beginIdleTime = userService.getBeginIdleTime(packageName); long lastUsedTime = userService.getSystemLastUsedTime(packageName); return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); } } /** * @param timestamp when the app was last used in device usage timebase * @param beginIdleTime when the app was last used in device usage timebase * @param lastUsedTime wallclock time of when the app was last used * @param screenOnTime screen-on timebase time * @param currentTime current time in device usage timebase * @return whether it's been used far enough in the past to be considered inactive */ Loading @@ -696,18 +728,29 @@ public class UsageStatsService extends SystemService implements } } boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { final UserUsageStatsService userService; final long screenOnTime; synchronized (mLock) { if (timeNow == -1) { timeNow = checkAndGetTimeLocked(); } userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); screenOnTime = getScreenOnTimeLocked(timeNow); } return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime); } /** * Checks if an app has been idle for a while and filters out apps that are excluded. * It returns false if the current system state allows all apps to be considered active. * This happens if the device is plugged in or temporarily allowed to make exceptions. * Called by interface impls. */ boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { private boolean isAppIdleFiltered(String packageName, int userId, UserUsageStatsService userService, long timeNow, long screenOnTime) { if (packageName == null) return false; synchronized (mLock) { if (timeNow == -1) { timeNow = checkAndGetTimeLocked(); } // Temporary exemption, probably due to device charging or occasional allowance to // be allowed to sync, etc. if (mAppIdleParoled) { Loading Loading @@ -735,7 +778,7 @@ public class UsageStatsService extends SystemService implements return false; } return isAppIdleUnfiltered(packageName, userId, timeNow); return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime); } void setAppIdle(String packageName, boolean idle, int userId) { Loading Loading @@ -844,7 +887,7 @@ public class UsageStatsService extends SystemService implements break; case MSG_CHECK_IDLE_STATES: checkIdleStates(); checkIdleStates(msg.arg1); break; case MSG_CHECK_PAROLE_TIMEOUT: Loading Loading @@ -884,7 +927,7 @@ public class UsageStatsService extends SystemService implements UserHandle.USER_OWNER); mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL, mAppIdleDurationMillis / 4); postCheckIdleStates(); postCheckIdleStates(UserHandle.USER_ALL); } } Loading Loading
core/java/android/os/BatteryStats.java +8 −3 Original line number Diff line number Diff line Loading @@ -1177,8 +1177,13 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_ALARM = 0x000e; // Record that we have decided we need to collect new stats data. public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f; // Event for a package becoming inactive due to being unused for a period of time. public static final int EVENT_PACKAGE_INACTIVE = 0x0010; // Event for a package becoming active due to an interaction. public static final int EVENT_PACKAGE_ACTIVE = 0x0011; // Number of event types. public static final int EVENT_COUNT = 0x0010; public static final int EVENT_COUNT = 0x0012; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); Loading Loading @@ -1835,12 +1840,12 @@ public abstract class BatteryStats implements Parcelable { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", "motion", "active", "pkginst", "pkgunin", "alarm", "stats" "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", "Esm", "Eac", "Epi", "Epu", "Eal", "Est" "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa" }; /** Loading
services/usage/java/com/android/server/usage/AppIdleHistory.java +33 −16 Original line number Diff line number Diff line Loading @@ -27,34 +27,27 @@ import com.android.internal.util.IndentingPrintWriter; */ public class AppIdleHistory { private SparseArray<ArrayMap<String,byte[]>> idleHistory = new SparseArray<>(); private SparseArray<ArrayMap<String,byte[]>> mIdleHistory = new SparseArray<>(); private long lastPeriod = 0; private static final long ONE_MINUTE = 60 * 1000; private static final int HISTORY_SIZE = 100; private static final int FLAG_LAST_STATE = 2; private static final int FLAG_PARTIAL_ACTIVE = 1; private static final long PERIOD_DURATION = UsageStatsService.DEBUG ? ONE_MINUTE private static final long PERIOD_DURATION = UsageStatsService.COMPRESS_TIME ? ONE_MINUTE : 60 * ONE_MINUTE; public void addEntry(String packageName, int userId, boolean idle, long timeNow) { ArrayMap<String, byte[]> userHistory = idleHistory.get(userId); if (userHistory == null) { userHistory = new ArrayMap<>(); idleHistory.put(userId, userHistory); } byte[] packageHistory = userHistory.get(packageName); if (packageHistory == null) { packageHistory = new byte[HISTORY_SIZE]; userHistory.put(packageName, packageHistory); } ArrayMap<String, byte[]> userHistory = getUserHistory(userId); byte[] packageHistory = getPackageHistory(userHistory, packageName); long thisPeriod = timeNow / PERIOD_DURATION; // Has the period switched over? Slide all users' package histories if (lastPeriod != 0 && lastPeriod < thisPeriod && (thisPeriod - lastPeriod) < HISTORY_SIZE - 1) { int diff = (int) (thisPeriod - lastPeriod); final int NUSERS = idleHistory.size(); final int NUSERS = mIdleHistory.size(); for (int u = 0; u < NUSERS; u++) { userHistory = idleHistory.valueAt(u); userHistory = mIdleHistory.valueAt(u); for (byte[] history : userHistory.values()) { // Shift left System.arraycopy(history, diff, history, 0, HISTORY_SIZE - diff); Loading @@ -74,12 +67,36 @@ public class AppIdleHistory { } } private ArrayMap<String, byte[]> getUserHistory(int userId) { ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId); if (userHistory == null) { userHistory = new ArrayMap<>(); mIdleHistory.put(userId, userHistory); } return userHistory; } private byte[] getPackageHistory(ArrayMap<String, byte[]> userHistory, String packageName) { byte[] packageHistory = userHistory.get(packageName); if (packageHistory == null) { packageHistory = new byte[HISTORY_SIZE]; userHistory.put(packageName, packageHistory); } return packageHistory; } public void removeUser(int userId) { idleHistory.remove(userId); mIdleHistory.remove(userId); } public boolean isIdle(int userId, String packageName) { ArrayMap<String, byte[]> userHistory = getUserHistory(userId); byte[] packageHistory = getPackageHistory(userHistory, packageName); return (packageHistory[HISTORY_SIZE - 1] & FLAG_LAST_STATE) == 0; } public void dump(IndentingPrintWriter idpw, int userId) { ArrayMap<String, byte[]> userHistory = idleHistory.get(userId); ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId); if (userHistory == null) return; final int P = userHistory.size(); for (int p = 0; p < P; p++) { Loading
services/usage/java/com/android/server/usage/UsageStatsService.java +73 −30 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.database.ContentObserver; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.BatteryManager; import android.os.BatteryStats; import android.os.Binder; import android.os.Environment; import android.os.Handler; Loading @@ -65,6 +66,7 @@ import android.util.SparseArray; import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import com.android.server.DeviceIdleController; Loading @@ -91,7 +93,7 @@ public class UsageStatsService extends SystemService implements static final String TAG = "UsageStatsService"; static final boolean DEBUG = false; private static final boolean COMPRESS_TIME = false; static final boolean COMPRESS_TIME = false; private static final long TEN_SECONDS = 10 * 1000; private static final long ONE_MINUTE = 60 * 1000; Loading Loading @@ -128,6 +130,7 @@ public class UsageStatsService extends SystemService implements IDeviceIdleController mDeviceIdleController; private DisplayManager mDisplayManager; private PowerManager mPowerManager; private IBatteryStats mBatteryStats; private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private File mUsageStatsDir; Loading Loading @@ -200,6 +203,8 @@ public class UsageStatsService extends SystemService implements mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class); mDeviceIdleController = IDeviceIdleController.Stub.asInterface( ServiceManager.getService(DeviceIdleController.SERVICE_NAME)); mBatteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); Loading Loading @@ -228,7 +233,7 @@ public class UsageStatsService extends SystemService implements } } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { if (userId >=0) { postCheckIdleStates(); postCheckIdleStates(userId); } } } Loading Loading @@ -307,7 +312,7 @@ public class UsageStatsService extends SystemService implements mLastAppIdleParoledTime = checkAndGetTimeLocked(); postNextParoleTimeout(); } postCheckIdleStates(); postCheckIdleStates(UserHandle.USER_ALL); } } } Loading @@ -332,22 +337,25 @@ public class UsageStatsService extends SystemService implements mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, DEFAULT_PAROLE_DURATION); } void postCheckIdleStates() { mHandler.removeMessages(MSG_CHECK_IDLE_STATES); mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES); void postCheckIdleStates(int userId) { mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); } /** Check all running users' apps to see if they enter an idle state. */ void checkIdleStates() { final int[] runningUsers; /** Check all running users' or specified user's apps to see if they enter an idle state. */ void checkIdleStates(int checkUserId) { final int[] userIds; try { runningUsers = ActivityManagerNative.getDefault().getRunningUserIds(); if (checkUserId == UserHandle.USER_ALL) { userIds = ActivityManagerNative.getDefault().getRunningUserIds(); } else { userIds = new int[] { checkUserId }; } } catch (RemoteException re) { return; } for (int i = 0; i < runningUsers.length; i++) { final int userId = runningUsers[i]; for (int i = 0; i < userIds.length; i++) { final int userId = userIds[i]; List<PackageInfo> packages = getContext().getPackageManager().getInstalledPackages( PackageManager.GET_DISABLED_COMPONENTS Loading @@ -355,17 +363,22 @@ public class UsageStatsService extends SystemService implements userId); synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); final long screenOnTime = getScreenOnTimeLocked(timeNow); UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); final int packageCount = packages.size(); for (int p = 0; p < packageCount; p++) { final String packageName = packages.get(p).packageName; final boolean isIdle = isAppIdleFiltered(packageName, userId, timeNow); final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow, screenOnTime); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, isIdle ? 1 : 0, packageName)); mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow); } } } mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0), mCheckIdleIntervalMillis); } /** Check if it's been a while since last parole and let idle apps do some work */ Loading @@ -386,6 +399,20 @@ public class UsageStatsService extends SystemService implements } } private void notifyBatteryStats(String packageName, int userId, boolean idle) { try { int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId); if (idle) { mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE, packageName, uid); } else { mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE, packageName, uid); } } catch (RemoteException re) { } } void updateDisplayLocked() { boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState() == Display.STATE_ON; Loading Loading @@ -545,7 +572,7 @@ public class UsageStatsService extends SystemService implements final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage); final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); service.reportEvent(event, getScreenOnTimeLocked(timeNow)); service.reportEvent(event, screenOnTime); // Inform listeners if necessary if ((event.mEventType == Event.MOVE_TO_FOREGROUND || event.mEventType == Event.MOVE_TO_BACKGROUND Loading @@ -555,6 +582,7 @@ public class UsageStatsService extends SystemService implements // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ 0, event.mPackage)); notifyBatteryStats(event.mPackage, userId, false); mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow); } } Loading Loading @@ -586,6 +614,9 @@ public class UsageStatsService extends SystemService implements // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ idle ? 1 : 0, packageName)); if (!idle) { notifyBatteryStats(packageName, userId, idle); } mAppIdleHistory.addEntry(packageName, userId, idle, timeNow); } } Loading Loading @@ -660,19 +691,20 @@ public class UsageStatsService extends SystemService implements } } private boolean isAppIdleUnfiltered(String packageName, int userId, long timeNow) { private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService, long timeNow, long screenOnTime) { synchronized (mLock) { final long screenOnTime = getScreenOnTimeLocked(timeNow); final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); long beginIdleTime = service.getBeginIdleTime(packageName); long lastUsedTime = service.getSystemLastUsedTime(packageName); return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); long beginIdleTime = userService.getBeginIdleTime(packageName); long lastUsedTime = userService.getSystemLastUsedTime(packageName); return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); } } /** * @param timestamp when the app was last used in device usage timebase * @param beginIdleTime when the app was last used in device usage timebase * @param lastUsedTime wallclock time of when the app was last used * @param screenOnTime screen-on timebase time * @param currentTime current time in device usage timebase * @return whether it's been used far enough in the past to be considered inactive */ Loading @@ -696,18 +728,29 @@ public class UsageStatsService extends SystemService implements } } boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { final UserUsageStatsService userService; final long screenOnTime; synchronized (mLock) { if (timeNow == -1) { timeNow = checkAndGetTimeLocked(); } userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); screenOnTime = getScreenOnTimeLocked(timeNow); } return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime); } /** * Checks if an app has been idle for a while and filters out apps that are excluded. * It returns false if the current system state allows all apps to be considered active. * This happens if the device is plugged in or temporarily allowed to make exceptions. * Called by interface impls. */ boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { private boolean isAppIdleFiltered(String packageName, int userId, UserUsageStatsService userService, long timeNow, long screenOnTime) { if (packageName == null) return false; synchronized (mLock) { if (timeNow == -1) { timeNow = checkAndGetTimeLocked(); } // Temporary exemption, probably due to device charging or occasional allowance to // be allowed to sync, etc. if (mAppIdleParoled) { Loading Loading @@ -735,7 +778,7 @@ public class UsageStatsService extends SystemService implements return false; } return isAppIdleUnfiltered(packageName, userId, timeNow); return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime); } void setAppIdle(String packageName, boolean idle, int userId) { Loading Loading @@ -844,7 +887,7 @@ public class UsageStatsService extends SystemService implements break; case MSG_CHECK_IDLE_STATES: checkIdleStates(); checkIdleStates(msg.arg1); break; case MSG_CHECK_PAROLE_TIMEOUT: Loading Loading @@ -884,7 +927,7 @@ public class UsageStatsService extends SystemService implements UserHandle.USER_OWNER); mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL, mAppIdleDurationMillis / 4); postCheckIdleStates(); postCheckIdleStates(UserHandle.USER_ALL); } } Loading