summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java155
1 files changed, 107 insertions, 48 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 50cb5fc79f55..dd8e54ba9c85 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -80,6 +80,7 @@ import org.xmlpull.v1.XmlSerializer;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.admin.IDevicePolicyManager;
import android.app.backup.IBackupManager;
@@ -4389,62 +4390,120 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (pkgs != null) {
- // Filter out packages that aren't recently used.
- //
- // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
- // should do a full dexopt.
- if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
- // TODO: add a property to control this?
- long dexOptLRUThresholdInMinutes;
- if (mLazyDexOpt) {
- dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
- } else {
- dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
- }
- long dexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
-
- int total = pkgs.size();
- int skipped = 0;
- long now = System.currentTimeMillis();
- for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
- PackageParser.Package pkg = i.next();
- long then = pkg.mLastPackageUsageTimeInMills;
- if (then + dexOptLRUThresholdInMills < now) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
- ((then == 0) ? "never" : new Date(then)));
- }
- i.remove();
- skipped++;
- }
+ // Sort apps by importance for dexopt ordering. Important apps are given more priority
+ // in case the device runs out of space.
+ ArrayList<PackageParser.Package> sortedPkgs = new ArrayList<PackageParser.Package>();
+ // Give priority to system apps that listen for pre boot complete.
+ Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
+ HashSet<String> pkgNames = getPackageNamesForIntent(intent);
+ for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+ PackageParser.Package pkg = it.next();
+ if (pkgNames.contains(pkg.packageName)) {
+ sortedPkgs.add(pkg);
+ it.remove();
}
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
+ }
+ // Give priority to system apps.
+ for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+ PackageParser.Package pkg = it.next();
+ if (isSystemApp(pkg)) {
+ sortedPkgs.add(pkg);
+ it.remove();
+ }
+ }
+ // Give priority to apps that listen for boot complete.
+ intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
+ pkgNames = getPackageNamesForIntent(intent);
+ for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+ PackageParser.Package pkg = it.next();
+ if (pkgNames.contains(pkg.packageName)) {
+ sortedPkgs.add(pkg);
+ it.remove();
}
}
+ // Filter out packages that aren't recently used.
+ filterRecentlyUsedApps(pkgs);
+ // Add all remaining apps.
+ for (PackageParser.Package pkg : pkgs) {
+ sortedPkgs.add(pkg);
+ }
int i = 0;
- for (PackageParser.Package pkg : pkgs) {
- i++;
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Optimizing app " + i + " of " + pkgs.size()
- + ": " + pkg.packageName);
- }
- if (!isFirstBoot()) {
- try {
- ActivityManagerNative.getDefault().showBootMessage(
- mContext.getResources().getString(
- R.string.android_upgrading_apk,
- i, pkgs.size()), true);
- } catch (RemoteException e) {
+ int total = sortedPkgs.size();
+ for (PackageParser.Package pkg : sortedPkgs) {
+ performBootDexOpt(pkg, ++i, total);
+ }
+ }
+ }
+
+ private void filterRecentlyUsedApps(HashSet<PackageParser.Package> pkgs) {
+ // Filter out packages that aren't recently used.
+ //
+ // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
+ // should do a full dexopt.
+ if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
+ // TODO: add a property to control this?
+ long dexOptLRUThresholdInMinutes;
+ if (mLazyDexOpt) {
+ dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
+ } else {
+ dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
+ }
+ long dexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
+
+ int total = pkgs.size();
+ int skipped = 0;
+ long now = System.currentTimeMillis();
+ for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
+ PackageParser.Package pkg = i.next();
+ long then = pkg.mLastPackageUsageTimeInMills;
+ if (then + dexOptLRUThresholdInMills < now) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
+ ((then == 0) ? "never" : new Date(then)));
}
- }
- PackageParser.Package p = pkg;
- synchronized (mInstallLock) {
- performDexOptLI(p, null /* instruction sets */, false /* force dex */, false /* defer */,
- true /* include dependencies */);
+ i.remove();
+ skipped++;
}
}
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
+ }
+ }
+ }
+
+ private HashSet<String> getPackageNamesForIntent(Intent intent) {
+ List<ResolveInfo> ris = null;
+ try {
+ ris = AppGlobals.getPackageManager().queryIntentReceivers(
+ intent, null, 0, UserHandle.USER_OWNER);
+ } catch (RemoteException e) {
+ }
+ HashSet<String> pkgNames = new HashSet<String>();
+ if (ris != null) {
+ for (ResolveInfo ri : ris) {
+ pkgNames.add(ri.activityInfo.packageName);
+ }
+ }
+ return pkgNames;
+ }
+
+ private void performBootDexOpt(PackageParser.Package pkg, int curr, int total) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Optimizing app " + curr + " of " + total + ": " + pkg.packageName);
+ }
+ if (!isFirstBoot()) {
+ try {
+ ActivityManagerNative.getDefault().showBootMessage(
+ mContext.getResources().getString(R.string.android_upgrading_apk,
+ curr, total), true);
+ } catch (RemoteException e) {
+ }
+ }
+ PackageParser.Package p = pkg;
+ synchronized (mInstallLock) {
+ performDexOptLI(p, null /* instruction sets */, false /* force dex */,
+ false /* defer */, true /* include dependencies */);
}
}