Loading apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,13 @@ public interface AppStandbyInternal { int getAppStandbyBucketReason(@NonNull String packageName, @UserIdInt int userId, @ElapsedRealtimeLong long elapsedRealtime); /** * Puts the list of apps in the {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RARE} * bucket. * @param restoredApps the list of restored apps */ void restoreAppsToRare(@NonNull Set<String> restoredApps, int userId); /** * Put the specified app in the * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} Loading apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +21 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,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_DEFAULT_APP_RESTORED; import static android.app.usage.UsageStatsManager.REASON_SUB_DEFAULT_APP_UPDATE; import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY; import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION; Loading Loading @@ -1604,6 +1605,26 @@ public class AppStandbyController setAppStandbyBucket(packageName, userId, bucket, reason, nowElapsed, false); } @Override public void restoreAppsToRare(Set<String> restoredApps, int userId) { final int reason = REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_APP_RESTORED; final long nowElapsed = mInjector.elapsedRealtime(); for (String packageName : restoredApps) { // If the package is not installed, don't allow the bucket to be set. if (!mInjector.isPackageInstalled(packageName, 0, userId)) { Slog.e(TAG, "Tried to restore bucket for uninstalled app: " + packageName); continue; } final int standbyBucket = getAppStandbyBucket(packageName, userId, nowElapsed, false); // Only update the standby bucket to RARE if the app is still in the NEVER bucket. if (standbyBucket == STANDBY_BUCKET_NEVER) { setAppStandbyBucket(packageName, userId, STANDBY_BUCKET_RARE, reason, nowElapsed, false); } } } @Override public void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId, int callingUid, int callingPid) { Loading core/java/android/app/usage/UsageStats.java +11 −0 Original line number Diff line number Diff line Loading @@ -292,6 +292,17 @@ public final class UsageStats implements Parcelable { return mLastTimeComponentUsed; } /** * Returns the last time the package was used - defined by the latest of * mLastTimeUsed, mLastTimeVisible, mLastTimeForegroundServiceUsed, or mLastTimeComponentUsed. * @hide */ public long getLastTimePackageUsed() { return Math.max(mLastTimeUsed, Math.max(mLastTimeVisible, Math.max(mLastTimeForegroundServiceUsed, mLastTimeComponentUsed))); } /** * Returns the number of times the app was launched as an activity from outside of the app. * Excludes intra-app activity transitions. Loading core/java/android/app/usage/UsageStatsManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -219,6 +219,11 @@ public final class UsageStatsManager { * @hide */ public static final int REASON_SUB_DEFAULT_APP_UPDATE = 0x0001; /** * The app was restored. * @hide */ public static final int REASON_SUB_DEFAULT_APP_RESTORED = 0x0002; /** * The app was interacted with in some way by the system. * @hide Loading Loading @@ -1209,6 +1214,9 @@ public final class UsageStatsManager { case REASON_SUB_DEFAULT_APP_UPDATE: sb.append("-au"); break; case REASON_SUB_DEFAULT_APP_RESTORED: sb.append("-ar"); break; } break; case REASON_MAIN_FORCED_BY_SYSTEM: Loading services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java +12 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static junit.framework.TestCase.fail; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import android.app.usage.TimeSparseArray; import android.app.usage.UsageEvents.Event; Loading Loading @@ -440,6 +441,7 @@ public class UsageStatsDatabaseTest { prevDB.readMappingsLocked(); prevDB.init(1); prevDB.putUsageStats(UsageStatsManager.INTERVAL_DAILY, mIntervalStats); Set<String> prevDBApps = mIntervalStats.packageStats.keySet(); // Create a backup with a specific version byte[] blob = prevDB.getBackupPayload(KEY_USAGE_STATS, version); if (version >= 1 && version <= 3) { Loading @@ -447,6 +449,11 @@ public class UsageStatsDatabaseTest { "UsageStatsDatabase shouldn't be able to write backups as XML"); return; } if (version < 1 || version > UsageStatsDatabase.BACKUP_VERSION) { assertFalse(blob != null && blob.length != 0, "UsageStatsDatabase shouldn't be able to write backups for unknown versions"); return; } clearUsageStatsFiles(); Loading @@ -454,9 +461,11 @@ public class UsageStatsDatabaseTest { newDB.readMappingsLocked(); newDB.init(1); // Attempt to restore the usage stats from the backup newDB.applyRestoredPayload(KEY_USAGE_STATS, blob); List<IntervalStats> stats = newDB.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, 0, mEndTime, mIntervalStatsVerifier); Set<String> restoredApps = newDB.applyRestoredPayload(KEY_USAGE_STATS, blob); assertTrue(restoredApps.containsAll(prevDBApps), "List of restored apps does not match list backed-up apps list."); List<IntervalStats> stats = newDB.queryUsageStats( UsageStatsManager.INTERVAL_DAILY, 0, mEndTime, mIntervalStatsVerifier); if (version > UsageStatsDatabase.BACKUP_VERSION || version < 1) { assertFalse(stats != null && !stats.isEmpty(), Loading Loading
apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,13 @@ public interface AppStandbyInternal { int getAppStandbyBucketReason(@NonNull String packageName, @UserIdInt int userId, @ElapsedRealtimeLong long elapsedRealtime); /** * Puts the list of apps in the {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RARE} * bucket. * @param restoredApps the list of restored apps */ void restoreAppsToRare(@NonNull Set<String> restoredApps, int userId); /** * Put the specified app in the * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} Loading
apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +21 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,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_DEFAULT_APP_RESTORED; import static android.app.usage.UsageStatsManager.REASON_SUB_DEFAULT_APP_UPDATE; import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY; import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION; Loading Loading @@ -1604,6 +1605,26 @@ public class AppStandbyController setAppStandbyBucket(packageName, userId, bucket, reason, nowElapsed, false); } @Override public void restoreAppsToRare(Set<String> restoredApps, int userId) { final int reason = REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_APP_RESTORED; final long nowElapsed = mInjector.elapsedRealtime(); for (String packageName : restoredApps) { // If the package is not installed, don't allow the bucket to be set. if (!mInjector.isPackageInstalled(packageName, 0, userId)) { Slog.e(TAG, "Tried to restore bucket for uninstalled app: " + packageName); continue; } final int standbyBucket = getAppStandbyBucket(packageName, userId, nowElapsed, false); // Only update the standby bucket to RARE if the app is still in the NEVER bucket. if (standbyBucket == STANDBY_BUCKET_NEVER) { setAppStandbyBucket(packageName, userId, STANDBY_BUCKET_RARE, reason, nowElapsed, false); } } } @Override public void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId, int callingUid, int callingPid) { Loading
core/java/android/app/usage/UsageStats.java +11 −0 Original line number Diff line number Diff line Loading @@ -292,6 +292,17 @@ public final class UsageStats implements Parcelable { return mLastTimeComponentUsed; } /** * Returns the last time the package was used - defined by the latest of * mLastTimeUsed, mLastTimeVisible, mLastTimeForegroundServiceUsed, or mLastTimeComponentUsed. * @hide */ public long getLastTimePackageUsed() { return Math.max(mLastTimeUsed, Math.max(mLastTimeVisible, Math.max(mLastTimeForegroundServiceUsed, mLastTimeComponentUsed))); } /** * Returns the number of times the app was launched as an activity from outside of the app. * Excludes intra-app activity transitions. Loading
core/java/android/app/usage/UsageStatsManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -219,6 +219,11 @@ public final class UsageStatsManager { * @hide */ public static final int REASON_SUB_DEFAULT_APP_UPDATE = 0x0001; /** * The app was restored. * @hide */ public static final int REASON_SUB_DEFAULT_APP_RESTORED = 0x0002; /** * The app was interacted with in some way by the system. * @hide Loading Loading @@ -1209,6 +1214,9 @@ public final class UsageStatsManager { case REASON_SUB_DEFAULT_APP_UPDATE: sb.append("-au"); break; case REASON_SUB_DEFAULT_APP_RESTORED: sb.append("-ar"); break; } break; case REASON_MAIN_FORCED_BY_SYSTEM: Loading
services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java +12 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static junit.framework.TestCase.fail; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import android.app.usage.TimeSparseArray; import android.app.usage.UsageEvents.Event; Loading Loading @@ -440,6 +441,7 @@ public class UsageStatsDatabaseTest { prevDB.readMappingsLocked(); prevDB.init(1); prevDB.putUsageStats(UsageStatsManager.INTERVAL_DAILY, mIntervalStats); Set<String> prevDBApps = mIntervalStats.packageStats.keySet(); // Create a backup with a specific version byte[] blob = prevDB.getBackupPayload(KEY_USAGE_STATS, version); if (version >= 1 && version <= 3) { Loading @@ -447,6 +449,11 @@ public class UsageStatsDatabaseTest { "UsageStatsDatabase shouldn't be able to write backups as XML"); return; } if (version < 1 || version > UsageStatsDatabase.BACKUP_VERSION) { assertFalse(blob != null && blob.length != 0, "UsageStatsDatabase shouldn't be able to write backups for unknown versions"); return; } clearUsageStatsFiles(); Loading @@ -454,9 +461,11 @@ public class UsageStatsDatabaseTest { newDB.readMappingsLocked(); newDB.init(1); // Attempt to restore the usage stats from the backup newDB.applyRestoredPayload(KEY_USAGE_STATS, blob); List<IntervalStats> stats = newDB.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, 0, mEndTime, mIntervalStatsVerifier); Set<String> restoredApps = newDB.applyRestoredPayload(KEY_USAGE_STATS, blob); assertTrue(restoredApps.containsAll(prevDBApps), "List of restored apps does not match list backed-up apps list."); List<IntervalStats> stats = newDB.queryUsageStats( UsageStatsManager.INTERVAL_DAILY, 0, mEndTime, mIntervalStatsVerifier); if (version > UsageStatsDatabase.BACKUP_VERSION || version < 1) { assertFalse(stats != null && !stats.isEmpty(), Loading