Merge "Update standby buckets for restored apps." into tm-qpr-dev am: 8d296990a6
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18916003 Change-Id: I6d3c7052c5a73da2df9520f146580ab3a9fa7dd4 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -163,6 +163,13 @@ public interface AppStandbyInternal {
|
|||||||
int getAppStandbyBucketReason(@NonNull String packageName, @UserIdInt int userId,
|
int getAppStandbyBucketReason(@NonNull String packageName, @UserIdInt int userId,
|
||||||
@ElapsedRealtimeLong long elapsedRealtime);
|
@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
|
* Put the specified app in the
|
||||||
* {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
|
* {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
|
||||||
|
|||||||
@@ -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_PREDICTED;
|
||||||
import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
|
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_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_DEFAULT_APP_UPDATE;
|
||||||
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY;
|
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY;
|
||||||
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION;
|
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION;
|
||||||
@@ -1604,6 +1605,26 @@ public class AppStandbyController
|
|||||||
setAppStandbyBucket(packageName, userId, bucket, reason, nowElapsed, false);
|
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
|
@Override
|
||||||
public void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId,
|
public void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId,
|
||||||
int callingUid, int callingPid) {
|
int callingUid, int callingPid) {
|
||||||
|
|||||||
@@ -292,6 +292,17 @@ public final class UsageStats implements Parcelable {
|
|||||||
return mLastTimeComponentUsed;
|
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.
|
* Returns the number of times the app was launched as an activity from outside of the app.
|
||||||
* Excludes intra-app activity transitions.
|
* Excludes intra-app activity transitions.
|
||||||
|
|||||||
@@ -219,6 +219,11 @@ public final class UsageStatsManager {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int REASON_SUB_DEFAULT_APP_UPDATE = 0x0001;
|
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.
|
* The app was interacted with in some way by the system.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -1209,6 +1214,9 @@ public final class UsageStatsManager {
|
|||||||
case REASON_SUB_DEFAULT_APP_UPDATE:
|
case REASON_SUB_DEFAULT_APP_UPDATE:
|
||||||
sb.append("-au");
|
sb.append("-au");
|
||||||
break;
|
break;
|
||||||
|
case REASON_SUB_DEFAULT_APP_RESTORED:
|
||||||
|
sb.append("-ar");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REASON_MAIN_FORCED_BY_SYSTEM:
|
case REASON_MAIN_FORCED_BY_SYSTEM:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static junit.framework.TestCase.fail;
|
|||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertFalse;
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import android.app.usage.TimeSparseArray;
|
import android.app.usage.TimeSparseArray;
|
||||||
import android.app.usage.UsageEvents.Event;
|
import android.app.usage.UsageEvents.Event;
|
||||||
@@ -440,6 +441,7 @@ public class UsageStatsDatabaseTest {
|
|||||||
prevDB.readMappingsLocked();
|
prevDB.readMappingsLocked();
|
||||||
prevDB.init(1);
|
prevDB.init(1);
|
||||||
prevDB.putUsageStats(UsageStatsManager.INTERVAL_DAILY, mIntervalStats);
|
prevDB.putUsageStats(UsageStatsManager.INTERVAL_DAILY, mIntervalStats);
|
||||||
|
Set<String> prevDBApps = mIntervalStats.packageStats.keySet();
|
||||||
// Create a backup with a specific version
|
// Create a backup with a specific version
|
||||||
byte[] blob = prevDB.getBackupPayload(KEY_USAGE_STATS, version);
|
byte[] blob = prevDB.getBackupPayload(KEY_USAGE_STATS, version);
|
||||||
if (version >= 1 && version <= 3) {
|
if (version >= 1 && version <= 3) {
|
||||||
@@ -447,6 +449,11 @@ public class UsageStatsDatabaseTest {
|
|||||||
"UsageStatsDatabase shouldn't be able to write backups as XML");
|
"UsageStatsDatabase shouldn't be able to write backups as XML");
|
||||||
return;
|
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();
|
clearUsageStatsFiles();
|
||||||
|
|
||||||
@@ -454,9 +461,11 @@ public class UsageStatsDatabaseTest {
|
|||||||
newDB.readMappingsLocked();
|
newDB.readMappingsLocked();
|
||||||
newDB.init(1);
|
newDB.init(1);
|
||||||
// Attempt to restore the usage stats from the backup
|
// Attempt to restore the usage stats from the backup
|
||||||
newDB.applyRestoredPayload(KEY_USAGE_STATS, blob);
|
Set<String> restoredApps = newDB.applyRestoredPayload(KEY_USAGE_STATS, blob);
|
||||||
List<IntervalStats> stats = newDB.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, 0, mEndTime,
|
assertTrue(restoredApps.containsAll(prevDBApps),
|
||||||
mIntervalStatsVerifier);
|
"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) {
|
if (version > UsageStatsDatabase.BACKUP_VERSION || version < 1) {
|
||||||
assertFalse(stats != null && !stats.isEmpty(),
|
assertFalse(stats != null && !stats.isEmpty(),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.usage;
|
package com.android.server.usage;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.usage.TimeSparseArray;
|
import android.app.usage.TimeSparseArray;
|
||||||
import android.app.usage.UsageEvents;
|
import android.app.usage.UsageEvents;
|
||||||
@@ -24,6 +25,7 @@ import android.app.usage.UsageStatsManager;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.AtomicFile;
|
import android.util.AtomicFile;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
@@ -55,8 +57,11 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an interface to query for UsageStat data from a Protocol Buffer database.
|
* Provides an interface to query for UsageStat data from a Protocol Buffer database.
|
||||||
@@ -1252,6 +1257,10 @@ public class UsageStatsDatabase {
|
|||||||
Slog.wtf(TAG, "Attempting to backup UsageStats as XML with version " + version);
|
Slog.wtf(TAG, "Attempting to backup UsageStats as XML with version " + version);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (version < 1 || version > BACKUP_VERSION) {
|
||||||
|
Slog.wtf(TAG, "Attempting to backup UsageStats with an unknown version: " + version);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
if (KEY_USAGE_STATS.equals(key)) {
|
if (KEY_USAGE_STATS.equals(key)) {
|
||||||
@@ -1300,14 +1309,26 @@ public class UsageStatsDatabase {
|
|||||||
}
|
}
|
||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the set of packages given to only include those that have been used within the
|
||||||
|
* given timeframe (as defined by {@link UsageStats#getLastTimePackageUsed()}).
|
||||||
|
*/
|
||||||
|
private void calculatePackagesUsedWithinTimeframe(
|
||||||
|
IntervalStats stats, Set<String> packagesList, long timeframeMs) {
|
||||||
|
for (UsageStats stat : stats.packageStats.values()) {
|
||||||
|
if (stat.getLastTimePackageUsed() > timeframeMs) {
|
||||||
|
packagesList.add(stat.mPackageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void applyRestoredPayload(String key, byte[] payload) {
|
public @NonNull Set<String> applyRestoredPayload(String key, byte[] payload) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (KEY_USAGE_STATS.equals(key)) {
|
if (KEY_USAGE_STATS.equals(key)) {
|
||||||
// Read stats files for the current device configs
|
// Read stats files for the current device configs
|
||||||
@@ -1320,12 +1341,15 @@ public class UsageStatsDatabase {
|
|||||||
IntervalStats yearlyConfigSource =
|
IntervalStats yearlyConfigSource =
|
||||||
getLatestUsageStats(UsageStatsManager.INTERVAL_YEARLY);
|
getLatestUsageStats(UsageStatsManager.INTERVAL_YEARLY);
|
||||||
|
|
||||||
|
final Set<String> packagesRestored = new ArraySet<>();
|
||||||
try {
|
try {
|
||||||
DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
|
DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
|
||||||
int backupDataVersion = in.readInt();
|
int backupDataVersion = in.readInt();
|
||||||
|
|
||||||
// Can't handle this backup set
|
// Can't handle this backup set
|
||||||
if (backupDataVersion < 1 || backupDataVersion > BACKUP_VERSION) return;
|
if (backupDataVersion < 1 || backupDataVersion > BACKUP_VERSION) {
|
||||||
|
return packagesRestored;
|
||||||
|
}
|
||||||
|
|
||||||
// Delete all stats files
|
// Delete all stats files
|
||||||
// Do this after reading version and before actually restoring
|
// Do this after reading version and before actually restoring
|
||||||
@@ -1333,10 +1357,14 @@ public class UsageStatsDatabase {
|
|||||||
deleteDirectoryContents(mIntervalDirs[i]);
|
deleteDirectoryContents(mIntervalDirs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 90 days before today in epoch
|
||||||
|
final long timeframe = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(90);
|
||||||
int fileCount = in.readInt();
|
int fileCount = in.readInt();
|
||||||
for (int i = 0; i < fileCount; i++) {
|
for (int i = 0; i < fileCount; i++) {
|
||||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||||
backupDataVersion);
|
backupDataVersion);
|
||||||
|
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||||
|
packagesRestored.addAll(stats.packageStats.keySet());
|
||||||
stats = mergeStats(stats, dailyConfigSource);
|
stats = mergeStats(stats, dailyConfigSource);
|
||||||
putUsageStats(UsageStatsManager.INTERVAL_DAILY, stats);
|
putUsageStats(UsageStatsManager.INTERVAL_DAILY, stats);
|
||||||
}
|
}
|
||||||
@@ -1345,6 +1373,7 @@ public class UsageStatsDatabase {
|
|||||||
for (int i = 0; i < fileCount; i++) {
|
for (int i = 0; i < fileCount; i++) {
|
||||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||||
backupDataVersion);
|
backupDataVersion);
|
||||||
|
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||||
stats = mergeStats(stats, weeklyConfigSource);
|
stats = mergeStats(stats, weeklyConfigSource);
|
||||||
putUsageStats(UsageStatsManager.INTERVAL_WEEKLY, stats);
|
putUsageStats(UsageStatsManager.INTERVAL_WEEKLY, stats);
|
||||||
}
|
}
|
||||||
@@ -1353,6 +1382,7 @@ public class UsageStatsDatabase {
|
|||||||
for (int i = 0; i < fileCount; i++) {
|
for (int i = 0; i < fileCount; i++) {
|
||||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||||
backupDataVersion);
|
backupDataVersion);
|
||||||
|
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||||
stats = mergeStats(stats, monthlyConfigSource);
|
stats = mergeStats(stats, monthlyConfigSource);
|
||||||
putUsageStats(UsageStatsManager.INTERVAL_MONTHLY, stats);
|
putUsageStats(UsageStatsManager.INTERVAL_MONTHLY, stats);
|
||||||
}
|
}
|
||||||
@@ -1361,6 +1391,7 @@ public class UsageStatsDatabase {
|
|||||||
for (int i = 0; i < fileCount; i++) {
|
for (int i = 0; i < fileCount; i++) {
|
||||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||||
backupDataVersion);
|
backupDataVersion);
|
||||||
|
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||||
stats = mergeStats(stats, yearlyConfigSource);
|
stats = mergeStats(stats, yearlyConfigSource);
|
||||||
putUsageStats(UsageStatsManager.INTERVAL_YEARLY, stats);
|
putUsageStats(UsageStatsManager.INTERVAL_YEARLY, stats);
|
||||||
}
|
}
|
||||||
@@ -1370,7 +1401,9 @@ public class UsageStatsDatabase {
|
|||||||
} finally {
|
} finally {
|
||||||
indexFilesLocked();
|
indexFilesLocked();
|
||||||
}
|
}
|
||||||
|
return packagesRestored;
|
||||||
}
|
}
|
||||||
|
return Collections.EMPTY_SET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3047,7 +3047,8 @@ public class UsageStatsService extends SystemService implements
|
|||||||
if (userStats == null) {
|
if (userStats == null) {
|
||||||
return; // user was stopped or removed
|
return; // user was stopped or removed
|
||||||
}
|
}
|
||||||
userStats.applyRestoredPayload(key, payload);
|
final Set<String> restoredApps = userStats.applyRestoredPayload(key, payload);
|
||||||
|
mAppStandby.restoreAppsToRare(restoredApps, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A per-user UsageStatsService. All methods are meant to be called with the main lock held
|
* A per-user UsageStatsService. All methods are meant to be called with the main lock held
|
||||||
@@ -1374,8 +1375,8 @@ class UserUsageStatsService {
|
|||||||
return mDatabase.getBackupPayload(key);
|
return mDatabase.getBackupPayload(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyRestoredPayload(String key, byte[] payload){
|
Set<String> applyRestoredPayload(String key, byte[] payload) {
|
||||||
checkAndGetTimeLocked();
|
checkAndGetTimeLocked();
|
||||||
mDatabase.applyRestoredPayload(key, payload);
|
return mDatabase.applyRestoredPayload(key, payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user