Loading core/java/android/app/usage/UsageStatsManager.java +17 −9 Original line number Diff line number Diff line Loading @@ -184,6 +184,9 @@ public final class UsageStatsManager { /** @hide */ public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV = 0x000A; /** @hide */ public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001; /** @hide */ @IntDef(flag = false, prefix = { "STANDBY_BUCKET_" }, value = { STANDBY_BUCKET_EXEMPTED, Loading Loading @@ -620,36 +623,41 @@ public final class UsageStatsManager { break; case REASON_MAIN_PREDICTED: sb.append("p"); switch (standbyReason & REASON_SUB_MASK) { case REASON_SUB_PREDICTED_RESTORED: sb.append("-r"); break; } break; case REASON_MAIN_TIMEOUT: sb.append("t"); break; case REASON_MAIN_USAGE: sb.append("u-"); sb.append("u"); switch (standbyReason & REASON_SUB_MASK) { case REASON_SUB_USAGE_SYSTEM_INTERACTION: sb.append("si"); sb.append("-si"); break; case REASON_SUB_USAGE_NOTIFICATION_SEEN: sb.append("ns"); sb.append("-ns"); break; case REASON_SUB_USAGE_USER_INTERACTION: sb.append("ui"); sb.append("-ui"); break; case REASON_SUB_USAGE_MOVE_TO_FOREGROUND: sb.append("mf"); sb.append("-mf"); break; case REASON_SUB_USAGE_MOVE_TO_BACKGROUND: sb.append("mb"); sb.append("-mb"); break; case REASON_SUB_USAGE_SYSTEM_UPDATE: sb.append("su"); sb.append("-su"); break; case REASON_SUB_USAGE_ACTIVE_TIMEOUT: sb.append("at"); sb.append("-at"); break; case REASON_SUB_USAGE_SYNC_ADAPTER: sb.append("sa"); sb.append("-sa"); break; case REASON_SUB_USAGE_SLICE_PINNED: sb.append("slp"); Loading services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +35 −25 Original line number Diff line number Diff line Loading @@ -281,6 +281,7 @@ public class AppStandbyControllerTests { MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext()); mInjector = new MyInjector(myContext, Looper.getMainLooper()); mController = setupController(); setChargingState(mController, false); } @Test Loading Loading @@ -381,8 +382,6 @@ public class AppStandbyControllerTests { @Test public void testForcedIdle() throws Exception { setChargingState(mController, false); mController.forceIdleState(PACKAGE_1, USER_ID, true); assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); Loading @@ -395,8 +394,6 @@ public class AppStandbyControllerTests { @Test public void testNotificationEvent() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); mInjector.mElapsedRealtime = 1; Loading @@ -410,8 +407,6 @@ public class AppStandbyControllerTests { @Test public void testSlicePinnedEvent() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); mInjector.mElapsedRealtime = 1; Loading @@ -425,8 +420,6 @@ public class AppStandbyControllerTests { @Test public void testSlicePinnedPrivEvent() throws Exception { setChargingState(mController, false); mController.forceIdleState(PACKAGE_1, USER_ID, true); reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); Loading @@ -434,14 +427,13 @@ public class AppStandbyControllerTests { @Test public void testPredictionTimedout() throws Exception { setChargingState(mController, false); // Set it to timeout or usage, so that prediction can override it mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_TIMEOUT, 1 * HOUR_MS); REASON_MAIN_TIMEOUT, HOUR_MS); assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, REASON_MAIN_PREDICTED, 1 * HOUR_MS); REASON_MAIN_PREDICTED, HOUR_MS); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); // Fast forward 12 hours Loading @@ -464,7 +456,6 @@ public class AppStandbyControllerTests { @Test public void testOverrides() throws Exception { setChargingState(mController, false); // Can force to NEVER mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, REASON_MAIN_FORCED, 1 * HOUR_MS); Loading Loading @@ -494,8 +485,6 @@ public class AppStandbyControllerTests { @Test public void testTimeout() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading @@ -505,19 +494,19 @@ public class AppStandbyControllerTests { assertBucket(STANDBY_BUCKET_ACTIVE); // bucketing works after timeout mInjector.mElapsedRealtime = FREQUENT_THRESHOLD - 100; mInjector.mElapsedRealtime = mController.mPredictionTimeoutMillis - 100; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_WORKING_SET); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); // Use recent prediction assertBucket(STANDBY_BUCKET_FREQUENT); // Way past prediction timeout, use system thresholds mInjector.mElapsedRealtime = RARE_THRESHOLD * 4; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_RARE); } @Test public void testCascadingTimeouts() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading @@ -539,8 +528,6 @@ public class AppStandbyControllerTests { @Test public void testOverlappingTimeouts() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading Loading @@ -596,8 +583,6 @@ public class AppStandbyControllerTests { @Test public void testPredictionNotOverridden() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading @@ -622,6 +607,31 @@ public class AppStandbyControllerTests { assertBucket(STANDBY_BUCKET_ACTIVE); } @Test public void testPredictionStrikesBack() throws Exception { reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); // Predict to FREQUENT mInjector.mElapsedRealtime = RARE_THRESHOLD; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); assertBucket(STANDBY_BUCKET_FREQUENT); // Add a short timeout event mInjector.mElapsedRealtime += 1000; reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime); assertBucket(STANDBY_BUCKET_ACTIVE); mInjector.mElapsedRealtime += 1000; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_ACTIVE); // Verify it reverted to predicted mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD / 2; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_FREQUENT); } @Test public void testAddActiveDeviceAdmin() { assertActiveAdmins(USER_ID, (String[]) null); Loading services/usage/java/com/android/server/usage/AppIdleHistory.java +17 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ public class AppIdleHistory { private SparseArray<ArrayMap<String,AppUsageHistory>> mIdleHistory = new SparseArray<>(); private static final long ONE_MINUTE = 60 * 1000; private static final int STANDBY_BUCKET_UNKNOWN = -1; @VisibleForTesting static final String APP_IDLE_FILENAME = "app_idle_stats.xml"; private static final String TAG_PACKAGES = "packages"; Loading Loading @@ -111,6 +113,9 @@ public class AppIdleHistory { long lastUsedScreenTime; // Last predicted time using elapsed timebase long lastPredictedTime; // Last predicted bucket @UsageStatsManager.StandbyBuckets int lastPredictedBucket = STANDBY_BUCKET_UNKNOWN; // Standby bucket @UsageStatsManager.StandbyBuckets int currentBucket; Loading Loading @@ -342,6 +347,7 @@ public class AppIdleHistory { appUsageHistory.bucketingReason = reason; if ((reason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED) { appUsageHistory.lastPredictedTime = getElapsedTime(elapsedRealtime); appUsageHistory.lastPredictedBucket = bucket; } if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket Loading @@ -349,6 +355,17 @@ public class AppIdleHistory { } } /** * Update the prediction for the app but don't change the actual bucket * @param app The app for which the prediction was made * @param elapsedTimeAdjusted The elapsed time in the elapsed duration timebase * @param bucket The predicted bucket */ public void updateLastPrediction(AppUsageHistory app, long elapsedTimeAdjusted, int bucket) { app.lastPredictedTime = elapsedTimeAdjusted; app.lastPredictedBucket = bucket; } /** * Marks the last time a job was run, with the given elapsedRealtime. The time stored is * based on the elapsed timebase. Loading services/usage/java/com/android/server/usage/AppStandbyController.java +24 −9 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK; import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED; import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT; import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE; import static android.app.usage.UsageStatsManager.REASON_SUB_PREDICTED_RESTORED; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOUT; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND; Loading Loading @@ -539,12 +540,21 @@ public class AppStandbyController { } final int oldBucket = app.currentBucket; int newBucket = Math.max(oldBucket, STANDBY_BUCKET_ACTIVE); // Undo EXEMPTED boolean predictionLate = false; boolean predictionLate = predictionTimedOut(app, elapsedRealtime); // Compute age-based bucket if (oldMainReason == REASON_MAIN_DEFAULT || oldMainReason == REASON_MAIN_USAGE || oldMainReason == REASON_MAIN_TIMEOUT || (predictionLate = predictionTimedOut(app, elapsedRealtime))) { || predictionLate) { if (!predictionLate && app.lastPredictedBucket >= STANDBY_BUCKET_ACTIVE && app.lastPredictedBucket <= STANDBY_BUCKET_RARE) { newBucket = app.lastPredictedBucket; reason = REASON_MAIN_PREDICTED | REASON_SUB_PREDICTED_RESTORED; if (DEBUG) { Slog.d(TAG, "Restored predicted newBucket = " + newBucket); } } else { newBucket = getBucketForLocked(packageName, userId, elapsedRealtime); if (DEBUG) { Loading @@ -552,6 +562,8 @@ public class AppStandbyController { } reason = REASON_MAIN_TIMEOUT; } } // Check if the app is within one of the timeouts for forced bucket elevation final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime); if (newBucket >= STANDBY_BUCKET_ACTIVE Loading Loading @@ -588,8 +600,7 @@ public class AppStandbyController { /** Returns true if there hasn't been a prediction for the app in a while. */ private boolean predictionTimedOut(AppIdleHistory.AppUsageHistory app, long elapsedRealtime) { return (app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED && app.lastPredictedTime > 0 return app.lastPredictedTime > 0 && mAppIdleHistory.getElapsedTime(elapsedRealtime) - app.lastPredictedTime > mPredictionTimeoutMillis; } Loading Loading @@ -1035,6 +1046,10 @@ public class AppStandbyController { if (predicted) { // Check if the app is within one of the timeouts for forced bucket elevation final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime); // In case of not using the prediction, just keep track of it for applying after // ACTIVE or WORKING_SET timeout. mAppIdleHistory.updateLastPrediction(app, elapsedTimeAdjusted, newBucket); if (newBucket > STANDBY_BUCKET_ACTIVE && app.bucketActiveTimeoutTime > elapsedTimeAdjusted) { newBucket = STANDBY_BUCKET_ACTIVE; Loading Loading
core/java/android/app/usage/UsageStatsManager.java +17 −9 Original line number Diff line number Diff line Loading @@ -184,6 +184,9 @@ public final class UsageStatsManager { /** @hide */ public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV = 0x000A; /** @hide */ public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001; /** @hide */ @IntDef(flag = false, prefix = { "STANDBY_BUCKET_" }, value = { STANDBY_BUCKET_EXEMPTED, Loading Loading @@ -620,36 +623,41 @@ public final class UsageStatsManager { break; case REASON_MAIN_PREDICTED: sb.append("p"); switch (standbyReason & REASON_SUB_MASK) { case REASON_SUB_PREDICTED_RESTORED: sb.append("-r"); break; } break; case REASON_MAIN_TIMEOUT: sb.append("t"); break; case REASON_MAIN_USAGE: sb.append("u-"); sb.append("u"); switch (standbyReason & REASON_SUB_MASK) { case REASON_SUB_USAGE_SYSTEM_INTERACTION: sb.append("si"); sb.append("-si"); break; case REASON_SUB_USAGE_NOTIFICATION_SEEN: sb.append("ns"); sb.append("-ns"); break; case REASON_SUB_USAGE_USER_INTERACTION: sb.append("ui"); sb.append("-ui"); break; case REASON_SUB_USAGE_MOVE_TO_FOREGROUND: sb.append("mf"); sb.append("-mf"); break; case REASON_SUB_USAGE_MOVE_TO_BACKGROUND: sb.append("mb"); sb.append("-mb"); break; case REASON_SUB_USAGE_SYSTEM_UPDATE: sb.append("su"); sb.append("-su"); break; case REASON_SUB_USAGE_ACTIVE_TIMEOUT: sb.append("at"); sb.append("-at"); break; case REASON_SUB_USAGE_SYNC_ADAPTER: sb.append("sa"); sb.append("-sa"); break; case REASON_SUB_USAGE_SLICE_PINNED: sb.append("slp"); Loading
services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +35 −25 Original line number Diff line number Diff line Loading @@ -281,6 +281,7 @@ public class AppStandbyControllerTests { MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext()); mInjector = new MyInjector(myContext, Looper.getMainLooper()); mController = setupController(); setChargingState(mController, false); } @Test Loading Loading @@ -381,8 +382,6 @@ public class AppStandbyControllerTests { @Test public void testForcedIdle() throws Exception { setChargingState(mController, false); mController.forceIdleState(PACKAGE_1, USER_ID, true); assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); Loading @@ -395,8 +394,6 @@ public class AppStandbyControllerTests { @Test public void testNotificationEvent() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); mInjector.mElapsedRealtime = 1; Loading @@ -410,8 +407,6 @@ public class AppStandbyControllerTests { @Test public void testSlicePinnedEvent() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); mInjector.mElapsedRealtime = 1; Loading @@ -425,8 +420,6 @@ public class AppStandbyControllerTests { @Test public void testSlicePinnedPrivEvent() throws Exception { setChargingState(mController, false); mController.forceIdleState(PACKAGE_1, USER_ID, true); reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); Loading @@ -434,14 +427,13 @@ public class AppStandbyControllerTests { @Test public void testPredictionTimedout() throws Exception { setChargingState(mController, false); // Set it to timeout or usage, so that prediction can override it mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_TIMEOUT, 1 * HOUR_MS); REASON_MAIN_TIMEOUT, HOUR_MS); assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, REASON_MAIN_PREDICTED, 1 * HOUR_MS); REASON_MAIN_PREDICTED, HOUR_MS); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); // Fast forward 12 hours Loading @@ -464,7 +456,6 @@ public class AppStandbyControllerTests { @Test public void testOverrides() throws Exception { setChargingState(mController, false); // Can force to NEVER mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, REASON_MAIN_FORCED, 1 * HOUR_MS); Loading Loading @@ -494,8 +485,6 @@ public class AppStandbyControllerTests { @Test public void testTimeout() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading @@ -505,19 +494,19 @@ public class AppStandbyControllerTests { assertBucket(STANDBY_BUCKET_ACTIVE); // bucketing works after timeout mInjector.mElapsedRealtime = FREQUENT_THRESHOLD - 100; mInjector.mElapsedRealtime = mController.mPredictionTimeoutMillis - 100; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_WORKING_SET); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); // Use recent prediction assertBucket(STANDBY_BUCKET_FREQUENT); // Way past prediction timeout, use system thresholds mInjector.mElapsedRealtime = RARE_THRESHOLD * 4; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_RARE); } @Test public void testCascadingTimeouts() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading @@ -539,8 +528,6 @@ public class AppStandbyControllerTests { @Test public void testOverlappingTimeouts() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading Loading @@ -596,8 +583,6 @@ public class AppStandbyControllerTests { @Test public void testPredictionNotOverridden() throws Exception { setChargingState(mController, false); reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); Loading @@ -622,6 +607,31 @@ public class AppStandbyControllerTests { assertBucket(STANDBY_BUCKET_ACTIVE); } @Test public void testPredictionStrikesBack() throws Exception { reportEvent(mController, USER_INTERACTION, 0); assertBucket(STANDBY_BUCKET_ACTIVE); // Predict to FREQUENT mInjector.mElapsedRealtime = RARE_THRESHOLD; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); assertBucket(STANDBY_BUCKET_FREQUENT); // Add a short timeout event mInjector.mElapsedRealtime += 1000; reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime); assertBucket(STANDBY_BUCKET_ACTIVE); mInjector.mElapsedRealtime += 1000; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_ACTIVE); // Verify it reverted to predicted mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD / 2; mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_FREQUENT); } @Test public void testAddActiveDeviceAdmin() { assertActiveAdmins(USER_ID, (String[]) null); Loading
services/usage/java/com/android/server/usage/AppIdleHistory.java +17 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ public class AppIdleHistory { private SparseArray<ArrayMap<String,AppUsageHistory>> mIdleHistory = new SparseArray<>(); private static final long ONE_MINUTE = 60 * 1000; private static final int STANDBY_BUCKET_UNKNOWN = -1; @VisibleForTesting static final String APP_IDLE_FILENAME = "app_idle_stats.xml"; private static final String TAG_PACKAGES = "packages"; Loading Loading @@ -111,6 +113,9 @@ public class AppIdleHistory { long lastUsedScreenTime; // Last predicted time using elapsed timebase long lastPredictedTime; // Last predicted bucket @UsageStatsManager.StandbyBuckets int lastPredictedBucket = STANDBY_BUCKET_UNKNOWN; // Standby bucket @UsageStatsManager.StandbyBuckets int currentBucket; Loading Loading @@ -342,6 +347,7 @@ public class AppIdleHistory { appUsageHistory.bucketingReason = reason; if ((reason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED) { appUsageHistory.lastPredictedTime = getElapsedTime(elapsedRealtime); appUsageHistory.lastPredictedBucket = bucket; } if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket Loading @@ -349,6 +355,17 @@ public class AppIdleHistory { } } /** * Update the prediction for the app but don't change the actual bucket * @param app The app for which the prediction was made * @param elapsedTimeAdjusted The elapsed time in the elapsed duration timebase * @param bucket The predicted bucket */ public void updateLastPrediction(AppUsageHistory app, long elapsedTimeAdjusted, int bucket) { app.lastPredictedTime = elapsedTimeAdjusted; app.lastPredictedBucket = bucket; } /** * Marks the last time a job was run, with the given elapsedRealtime. The time stored is * based on the elapsed timebase. Loading
services/usage/java/com/android/server/usage/AppStandbyController.java +24 −9 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK; import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED; import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT; import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE; import static android.app.usage.UsageStatsManager.REASON_SUB_PREDICTED_RESTORED; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOUT; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND; Loading Loading @@ -539,12 +540,21 @@ public class AppStandbyController { } final int oldBucket = app.currentBucket; int newBucket = Math.max(oldBucket, STANDBY_BUCKET_ACTIVE); // Undo EXEMPTED boolean predictionLate = false; boolean predictionLate = predictionTimedOut(app, elapsedRealtime); // Compute age-based bucket if (oldMainReason == REASON_MAIN_DEFAULT || oldMainReason == REASON_MAIN_USAGE || oldMainReason == REASON_MAIN_TIMEOUT || (predictionLate = predictionTimedOut(app, elapsedRealtime))) { || predictionLate) { if (!predictionLate && app.lastPredictedBucket >= STANDBY_BUCKET_ACTIVE && app.lastPredictedBucket <= STANDBY_BUCKET_RARE) { newBucket = app.lastPredictedBucket; reason = REASON_MAIN_PREDICTED | REASON_SUB_PREDICTED_RESTORED; if (DEBUG) { Slog.d(TAG, "Restored predicted newBucket = " + newBucket); } } else { newBucket = getBucketForLocked(packageName, userId, elapsedRealtime); if (DEBUG) { Loading @@ -552,6 +562,8 @@ public class AppStandbyController { } reason = REASON_MAIN_TIMEOUT; } } // Check if the app is within one of the timeouts for forced bucket elevation final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime); if (newBucket >= STANDBY_BUCKET_ACTIVE Loading Loading @@ -588,8 +600,7 @@ public class AppStandbyController { /** Returns true if there hasn't been a prediction for the app in a while. */ private boolean predictionTimedOut(AppIdleHistory.AppUsageHistory app, long elapsedRealtime) { return (app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED && app.lastPredictedTime > 0 return app.lastPredictedTime > 0 && mAppIdleHistory.getElapsedTime(elapsedRealtime) - app.lastPredictedTime > mPredictionTimeoutMillis; } Loading Loading @@ -1035,6 +1046,10 @@ public class AppStandbyController { if (predicted) { // Check if the app is within one of the timeouts for forced bucket elevation final long elapsedTimeAdjusted = mAppIdleHistory.getElapsedTime(elapsedRealtime); // In case of not using the prediction, just keep track of it for applying after // ACTIVE or WORKING_SET timeout. mAppIdleHistory.updateLastPrediction(app, elapsedTimeAdjusted, newBucket); if (newBucket > STANDBY_BUCKET_ACTIVE && app.bucketActiveTimeoutTime > elapsedTimeAdjusted) { newBucket = STANDBY_BUCKET_ACTIVE; Loading