Revert "Prune obsolete UsageStats data on upgrade."
This reverts commit 5228cc20bb.
Reason for revert: b/144982898
Change-Id: Ia28e2daff5a5904f4a75d6fb0ea1e3c855d68616
This commit is contained in:
@@ -52,7 +52,6 @@ import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -123,7 +122,6 @@ public class UsageStatsDatabase {
|
||||
private int mCurrentVersion;
|
||||
private boolean mFirstUpdate;
|
||||
private boolean mNewUpdate;
|
||||
private boolean mUpgradePerformed;
|
||||
|
||||
// The obfuscated packages to tokens mappings file
|
||||
private final File mPackageMappingsFile;
|
||||
@@ -327,13 +325,6 @@ public class UsageStatsDatabase {
|
||||
return mNewUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was an upgrade performed when this database was initialized?
|
||||
*/
|
||||
boolean wasUpgradePerformed() {
|
||||
return mUpgradePerformed;
|
||||
}
|
||||
|
||||
private void checkVersionAndBuildLocked() {
|
||||
int version;
|
||||
String buildFingerprint;
|
||||
@@ -406,8 +397,6 @@ public class UsageStatsDatabase {
|
||||
if (mUpdateBreadcrumb.exists()) {
|
||||
// Files should be up to date with current version. Clear the version update breadcrumb
|
||||
mUpdateBreadcrumb.delete();
|
||||
// update mUpgradePerformed after breadcrumb is deleted to indicate a successful upgrade
|
||||
mUpgradePerformed = true;
|
||||
}
|
||||
|
||||
if (mBackupsDir.exists() && !KEEP_BACKUP_DIR) {
|
||||
@@ -605,70 +594,6 @@ public class UsageStatsDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through all the files on disk and prunes any data that belongs to packages that have
|
||||
* been uninstalled (packages that are not in the given list).
|
||||
* Note: this should only be called once, when there has been a database upgrade.
|
||||
*
|
||||
* @param installedPackages map of installed packages (package_name:package_install_time)
|
||||
*/
|
||||
void prunePackagesDataOnUpgrade(HashMap<String, Long> installedPackages) {
|
||||
if (installedPackages == null || installedPackages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
for (int i = 0; i < mIntervalDirs.length; i++) {
|
||||
final File[] files = mIntervalDirs[i].listFiles();
|
||||
if (files == null) {
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < files.length; j++) {
|
||||
try {
|
||||
final IntervalStats stats = new IntervalStats();
|
||||
final AtomicFile atomicFile = new AtomicFile(files[j]);
|
||||
readLocked(atomicFile, stats, mCurrentVersion, mPackagesTokenData);
|
||||
if (!pruneStats(installedPackages, stats)) {
|
||||
continue; // no stats were pruned so no need to rewrite
|
||||
}
|
||||
writeLocked(atomicFile, stats, mCurrentVersion, mPackagesTokenData);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Failed to prune data from: " + files[j].toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean pruneStats(HashMap<String, Long> installedPackages, IntervalStats stats) {
|
||||
boolean dataPruned = false;
|
||||
|
||||
// prune old package usage stats
|
||||
for (int i = stats.packageStats.size() - 1; i >= 0; i--) {
|
||||
final UsageStats usageStats = stats.packageStats.valueAt(i);
|
||||
final Long timeInstalled = installedPackages.get(usageStats.mPackageName);
|
||||
if (timeInstalled == null || timeInstalled > usageStats.mEndTimeStamp) {
|
||||
stats.packageStats.removeAt(i);
|
||||
dataPruned = true;
|
||||
}
|
||||
}
|
||||
if (dataPruned) {
|
||||
// ensure old stats don't linger around during the obfuscation step on write
|
||||
stats.packageStatsObfuscated.clear();
|
||||
}
|
||||
|
||||
// prune old events
|
||||
for (int i = stats.events.size() - 1; i >= 0; i--) {
|
||||
final UsageEvents.Event event = stats.events.get(i);
|
||||
final Long timeInstalled = installedPackages.get(event.mPackage);
|
||||
if (timeInstalled == null || timeInstalled > event.mTimeStamp) {
|
||||
stats.events.remove(i);
|
||||
dataPruned = true;
|
||||
}
|
||||
}
|
||||
|
||||
return dataPruned;
|
||||
}
|
||||
|
||||
public void onTimeChanged(long timeDiffMillis) {
|
||||
synchronized (mLock) {
|
||||
StringBuilder logBuilder = new StringBuilder();
|
||||
|
||||
@@ -34,9 +34,10 @@ import android.app.usage.UsageEvents.Event;
|
||||
import android.app.usage.UsageStats;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.ArrayMap;
|
||||
@@ -46,6 +47,7 @@ import android.util.Slog;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.usage.UsageStatsDatabase.StatCombiner;
|
||||
|
||||
import java.io.File;
|
||||
@@ -53,7 +55,7 @@ import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -113,9 +115,6 @@ class UserUsageStatsService {
|
||||
void init(final long currentTimeMillis) {
|
||||
readPackageMappingsLocked();
|
||||
mDatabase.init(currentTimeMillis);
|
||||
if (mDatabase.wasUpgradePerformed()) {
|
||||
mDatabase.prunePackagesDataOnUpgrade(getInstalledPackages());
|
||||
}
|
||||
|
||||
int nullCount = 0;
|
||||
for (int i = 0; i < mCurrentStats.length; i++) {
|
||||
@@ -185,6 +184,7 @@ class UserUsageStatsService {
|
||||
private void readPackageMappingsLocked() {
|
||||
mDatabase.readMappingsLocked();
|
||||
updatePackageMappingsLocked();
|
||||
cleanUpPackageMappingsLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,24 +216,42 @@ class UserUsageStatsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a map of package names to their install times. This includes all installed packages,
|
||||
* including those packages which have been uninstalled with the DONT_DELETE_DATA flag.
|
||||
* Note: this is supposed be a helper method which is only used on database upgrades - it should
|
||||
* not be called otherwise since it's implementation performs a heavy query to package manager.
|
||||
* Queries Package Manager for a list of installed packages and removes those packages from
|
||||
* mPackagesTokenData which are not installed any more.
|
||||
* This will only happen once per device boot, when the user is unlocked for the first time.
|
||||
*/
|
||||
private HashMap<String, Long> getInstalledPackages() {
|
||||
final PackageManager packageManager = mContext.getPackageManager();
|
||||
if (packageManager == null) {
|
||||
return null;
|
||||
private void cleanUpPackageMappingsLocked() {
|
||||
final long timeNow = System.currentTimeMillis();
|
||||
/*
|
||||
Note (b/142501248): PackageManagerInternal#getInstalledApplications is not lightweight.
|
||||
Once its implementation is updated, or it's replaced with a better alternative, update
|
||||
the call here to use it. For now, using the heavy #getInstalledApplications is okay since
|
||||
this clean-up is only performed once every boot.
|
||||
*/
|
||||
final PackageManagerInternal packageManagerInternal =
|
||||
LocalServices.getService(PackageManagerInternal.class);
|
||||
if (packageManagerInternal == null) {
|
||||
return;
|
||||
}
|
||||
final List<PackageInfo> installedPackages = packageManager.getInstalledPackagesAsUser(
|
||||
PackageManager.MATCH_UNINSTALLED_PACKAGES, mUserId);
|
||||
final HashMap<String, Long> packagesMap = new HashMap<>();
|
||||
final List<ApplicationInfo> installedPackages =
|
||||
packageManagerInternal.getInstalledApplications(0, mUserId, Process.SYSTEM_UID);
|
||||
// convert the package list to a set for easy look-ups
|
||||
final HashSet<String> packagesSet = new HashSet<>(installedPackages.size());
|
||||
for (int i = installedPackages.size() - 1; i >= 0; i--) {
|
||||
final PackageInfo packageInfo = installedPackages.get(i);
|
||||
packagesMap.put(packageInfo.packageName, packageInfo.firstInstallTime);
|
||||
packagesSet.add(installedPackages.get(i).packageName);
|
||||
}
|
||||
final List<String> removedPackages = new ArrayList<>();
|
||||
// populate list of packages that are found in the mappings but not in the installed list
|
||||
for (int i = mDatabase.mPackagesTokenData.packagesToTokensMap.size() - 1; i >= 0; i--) {
|
||||
if (!packagesSet.contains(mDatabase.mPackagesTokenData.packagesToTokensMap.keyAt(i))) {
|
||||
removedPackages.add(mDatabase.mPackagesTokenData.packagesToTokensMap.keyAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
// remove packages in the mappings that are no longer installed
|
||||
for (int i = removedPackages.size() - 1; i >= 0; i--) {
|
||||
mDatabase.mPackagesTokenData.removePackage(removedPackages.get(i), timeNow);
|
||||
}
|
||||
return packagesMap;
|
||||
}
|
||||
|
||||
boolean pruneUninstalledPackagesData() {
|
||||
|
||||
Reference in New Issue
Block a user