Merge "Update standby buckets for restored apps." into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8d296990a6
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -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();
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.usage;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.usage.TimeSparseArray;
|
||||
import android.app.usage.UsageEvents;
|
||||
@@ -24,6 +25,7 @@ import android.app.usage.UsageStatsManager;
|
||||
import android.os.Build;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@@ -55,8 +57,11 @@ import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
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.
|
||||
@@ -1252,6 +1257,10 @@ public class UsageStatsDatabase {
|
||||
Slog.wtf(TAG, "Attempting to backup UsageStats as XML with version " + version);
|
||||
return null;
|
||||
}
|
||||
if (version < 1 || version > BACKUP_VERSION) {
|
||||
Slog.wtf(TAG, "Attempting to backup UsageStats with an unknown version: " + version);
|
||||
return null;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
if (KEY_USAGE_STATS.equals(key)) {
|
||||
@@ -1300,14 +1309,26 @@ public class UsageStatsDatabase {
|
||||
}
|
||||
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
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public void applyRestoredPayload(String key, byte[] payload) {
|
||||
public @NonNull Set<String> applyRestoredPayload(String key, byte[] payload) {
|
||||
synchronized (mLock) {
|
||||
if (KEY_USAGE_STATS.equals(key)) {
|
||||
// Read stats files for the current device configs
|
||||
@@ -1320,12 +1341,15 @@ public class UsageStatsDatabase {
|
||||
IntervalStats yearlyConfigSource =
|
||||
getLatestUsageStats(UsageStatsManager.INTERVAL_YEARLY);
|
||||
|
||||
final Set<String> packagesRestored = new ArraySet<>();
|
||||
try {
|
||||
DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
|
||||
int backupDataVersion = in.readInt();
|
||||
|
||||
// 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
|
||||
// Do this after reading version and before actually restoring
|
||||
@@ -1333,10 +1357,14 @@ public class UsageStatsDatabase {
|
||||
deleteDirectoryContents(mIntervalDirs[i]);
|
||||
}
|
||||
|
||||
// 90 days before today in epoch
|
||||
final long timeframe = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(90);
|
||||
int fileCount = in.readInt();
|
||||
for (int i = 0; i < fileCount; i++) {
|
||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||
backupDataVersion);
|
||||
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||
packagesRestored.addAll(stats.packageStats.keySet());
|
||||
stats = mergeStats(stats, dailyConfigSource);
|
||||
putUsageStats(UsageStatsManager.INTERVAL_DAILY, stats);
|
||||
}
|
||||
@@ -1345,6 +1373,7 @@ public class UsageStatsDatabase {
|
||||
for (int i = 0; i < fileCount; i++) {
|
||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||
backupDataVersion);
|
||||
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||
stats = mergeStats(stats, weeklyConfigSource);
|
||||
putUsageStats(UsageStatsManager.INTERVAL_WEEKLY, stats);
|
||||
}
|
||||
@@ -1353,6 +1382,7 @@ public class UsageStatsDatabase {
|
||||
for (int i = 0; i < fileCount; i++) {
|
||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||
backupDataVersion);
|
||||
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||
stats = mergeStats(stats, monthlyConfigSource);
|
||||
putUsageStats(UsageStatsManager.INTERVAL_MONTHLY, stats);
|
||||
}
|
||||
@@ -1361,6 +1391,7 @@ public class UsageStatsDatabase {
|
||||
for (int i = 0; i < fileCount; i++) {
|
||||
IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in),
|
||||
backupDataVersion);
|
||||
calculatePackagesUsedWithinTimeframe(stats, packagesRestored, timeframe);
|
||||
stats = mergeStats(stats, yearlyConfigSource);
|
||||
putUsageStats(UsageStatsManager.INTERVAL_YEARLY, stats);
|
||||
}
|
||||
@@ -1370,7 +1401,9 @@ public class UsageStatsDatabase {
|
||||
} finally {
|
||||
indexFilesLocked();
|
||||
}
|
||||
return packagesRestored;
|
||||
}
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3034,7 +3034,8 @@ public class UsageStatsService extends SystemService implements
|
||||
if (userStats == null) {
|
||||
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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
void applyRestoredPayload(String key, byte[] payload){
|
||||
Set<String> applyRestoredPayload(String key, byte[] payload) {
|
||||
checkAndGetTimeLocked();
|
||||
mDatabase.applyRestoredPayload(key, payload);
|
||||
return mDatabase.applyRestoredPayload(key, payload);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user