diff options
| author | 2016-09-08 00:04:03 +0000 | |
|---|---|---|
| committer | 2016-09-08 00:04:03 +0000 | |
| commit | c6340e7020d40a967f6007b34ec4fcce0b0a1c11 (patch) | |
| tree | a61e33cb5f13b187b674979f09cb3c7b3cddf1a3 | |
| parent | d1e10f4cc1b073036adec3552736f0e808a7fd2f (diff) | |
| parent | d3e07d46d41e8411def67c2150a0bae064e900dc (diff) | |
Package Manager: Sort list of packages to dexopt
am: d3e07d46d4
Change-Id: Id6ab3949141247255b91551b8a1027fad6082073
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerServiceUtils.java | 150 |
1 files changed, 74 insertions, 76 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 751c5858446b..9a8ebedf105e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -19,6 +19,7 @@ package com.android.server.pm; import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT; import static com.android.server.pm.PackageManagerService.TAG; +import android.annotation.NonNull; import android.app.AppGlobals; import android.content.Intent; import android.content.pm.PackageParser; @@ -35,13 +36,9 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Set; +import java.util.function.Predicate; /** * Class containing helper methods for the PackageManagerService. @@ -67,34 +64,51 @@ public class PackageManagerServiceUtils { return pkgNames; } - private static void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs, - long estimatedPreviousSystemUseTime, - long dexOptLRUThresholdInMills) { - // Filter out packages that aren't recently used. - int total = pkgs.size(); - int skipped = 0; - for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) { - PackageParser.Package pkg = i.next(); - long then = pkg.getLatestForegroundPackageUseTimeInMills(); - if (then < estimatedPreviousSystemUseTime - dexOptLRUThresholdInMills) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Skipping dexopt of " + pkg.packageName + - " last used in foreground: " + - ((then == 0) ? "never" : new Date(then))); - } - i.remove(); - skipped++; - } else { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Will dexopt " + pkg.packageName + - " last used in foreground: " + - ((then == 0) ? "never" : new Date(then))); - } + // Sort a list of apps by their last usage, most recently used apps first. The order of + // packages without usage data is undefined (but they will be sorted after the packages + // that do have usage data). + public static void sortPackagesByUsageDate(List<PackageParser.Package> pkgs, + PackageManagerService packageManagerService) { + if (!packageManagerService.isHistoricalPackageUsageAvailable()) { + return; + } + + Collections.sort(pkgs, (pkg1, pkg2) -> + Long.compare(pkg2.getLatestForegroundPackageUseTimeInMills(), + pkg1.getLatestForegroundPackageUseTimeInMills())); + } + + // Apply the given {@code filter} to all packages in {@code packages}. If tested positive, the + // package will be removed from {@code packages} and added to {@code result} with its + // dependencies. If usage data is available, the positive packages will be sorted by usage + // data (with {@code sortTemp} as temporary storage). + private static void applyPackageFilter(Predicate<PackageParser.Package> filter, + Collection<PackageParser.Package> result, + Collection<PackageParser.Package> packages, + @NonNull List<PackageParser.Package> sortTemp, + PackageManagerService packageManagerService) { + for (PackageParser.Package pkg : packages) { + if (filter.test(pkg)) { + sortTemp.add(pkg); } } - if (DEBUG_DEXOPT) { - Log.i(TAG, "Skipped dexopt " + skipped + " of " + total); + + sortPackagesByUsageDate(sortTemp, packageManagerService); + packages.removeAll(sortTemp); + + for (PackageParser.Package pkg : sortTemp) { + result.add(pkg); + + Collection<PackageParser.Package> deps = + packageManagerService.findSharedNonSystemLibraries(pkg); + if (!deps.isEmpty()) { + deps.removeAll(result); + result.addAll(deps); + packages.removeAll(deps); + } } + + sortTemp.clear(); } // Sort apps by importance for dexopt ordering. Important apps are given @@ -104,46 +118,25 @@ public class PackageManagerServiceUtils { PackageManagerService packageManagerService) { ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages); LinkedList<PackageParser.Package> result = new LinkedList<>(); + ArrayList<PackageParser.Package> sortTemp = new ArrayList<>(remainingPkgs.size()); // Give priority to core apps. - for (PackageParser.Package pkg : remainingPkgs) { - if (pkg.coreApp) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Adding core app " + result.size() + ": " + pkg.packageName); - } - result.add(pkg); - } - } - remainingPkgs.removeAll(result); + applyPackageFilter((pkg) -> pkg.coreApp, result, remainingPkgs, sortTemp, + packageManagerService); // Give priority to system apps that listen for pre boot complete. Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); - ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM); - for (PackageParser.Package pkg : remainingPkgs) { - if (pkgNames.contains(pkg.packageName)) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Adding pre boot system app " + result.size() + ": " + - pkg.packageName); - } - result.add(pkg); - } - } - remainingPkgs.removeAll(result); + final ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM); + applyPackageFilter((pkg) -> pkgNames.contains(pkg.packageName), result, remainingPkgs, + sortTemp, packageManagerService); // Give priority to apps used by other apps. - for (PackageParser.Package pkg : remainingPkgs) { - if (PackageDexOptimizer.isUsedByOtherApps(pkg)) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Adding app used by other apps " + result.size() + ": " + - pkg.packageName); - } - result.add(pkg); - } - } - remainingPkgs.removeAll(result); + applyPackageFilter((pkg) -> PackageDexOptimizer.isUsedByOtherApps(pkg), result, + remainingPkgs, sortTemp, packageManagerService); // Filter out packages that aren't recently used, add all remaining apps. // TODO: add a property to control this? + Predicate<PackageParser.Package> remainingPredicate; if (!remainingPkgs.isEmpty() && packageManagerService.isHistoricalPackageUsageAvailable()) { if (DEBUG_DEXOPT) { Log.i(TAG, "Looking at historical package use"); @@ -159,24 +152,20 @@ public class PackageManagerServiceUtils { lastUsed.getLatestForegroundPackageUseTimeInMills(); // Be defensive if for some reason package usage has bogus data. if (estimatedPreviousSystemUseTime != 0) { - filterRecentlyUsedApps(remainingPkgs, estimatedPreviousSystemUseTime, - SEVEN_DAYS_IN_MILLISECONDS); + final long cutoffTime = estimatedPreviousSystemUseTime - SEVEN_DAYS_IN_MILLISECONDS; + remainingPredicate = + (pkg) -> pkg.getLatestForegroundPackageUseTimeInMills() >= cutoffTime; + } else { + // No meaningful historical info. Take all. + remainingPredicate = (pkg) -> true; } + sortPackagesByUsageDate(remainingPkgs, packageManagerService); + } else { + // No historical info. Take all. + remainingPredicate = (pkg) -> true; } - result.addAll(remainingPkgs); - - // Now go ahead and also add the libraries required for these packages. - // TODO: Think about interleaving things. - Set<PackageParser.Package> dependencies = new HashSet<>(); - for (PackageParser.Package p : result) { - dependencies.addAll(packageManagerService.findSharedNonSystemLibraries(p)); - } - if (!dependencies.isEmpty()) { - // We might have packages already in `result` that are dependencies - // of other packages. Make sure we don't add those to the list twice. - dependencies.removeAll(result); - } - result.addAll(dependencies); + applyPackageFilter(remainingPredicate, result, remainingPkgs, sortTemp, + packageManagerService); if (DEBUG_DEXOPT) { StringBuilder sb = new StringBuilder(); @@ -187,6 +176,15 @@ public class PackageManagerServiceUtils { sb.append(pkg.packageName); } Log.i(TAG, "Packages to be dexopted: " + sb.toString()); + + sb.setLength(0); + for (PackageParser.Package pkg : remainingPkgs) { + if (sb.length() > 0) { + sb.append(", "); + } + sb.append(pkg.packageName); + } + Log.i(TAG, "Packages skipped from dexopt: " + sb.toString()); } return result; |