summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Brazdil <dbrazdil@google.com> 2016-02-04 11:54:17 +0000
committer David Brazdil <dbrazdil@google.com> 2016-02-11 12:16:41 +0000
commit6b4736d604fd91aaedc6f3fe9be5a1e757aab86c (patch)
treea1151abededb44eab9aa504cec9452ba1807357b
parent4a70f09e39ac7c5f57b0f6dd44475641c68afafd (diff)
Apply 'used in last 7 days' filter to OTA package extraction
Bug: 26813999 Change-Id: I5f1eddb1d5e9f0bbaab62d86e6ccf3cc097c4edb (cherry picked from commit e292175fbd495a63b48560439d2a84b239f91e18)
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java89
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java30
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java152
3 files changed, 163 insertions, 108 deletions
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index da62a2d6fc84..94b3b2d613cf 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -55,8 +55,6 @@ import static com.android.server.pm.Installer.DEXOPT_OTA;
public class OtaDexoptService extends IOtaDexopt.Stub {
private final static String TAG = "OTADexopt";
private final static boolean DEBUG_DEXOPT = true;
- // Apps used in the last 7 days.
- private final static long DEXOPT_LRU_THRESHOLD_IN_MINUTES = 7 * 24 * 60;
private final Context mContext;
private final PackageDexOptimizer mPackageDexOptimizer;
@@ -94,69 +92,9 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
if (mDexoptPackages != null) {
throw new IllegalStateException("already called prepare()");
}
-
- mDexoptPackages = new LinkedList<>();
-
- ArrayList<PackageParser.Package> pkgs;
synchronized (mPackageManagerService.mPackages) {
- pkgs = new ArrayList<PackageParser.Package>(mPackageManagerService.mPackages.values());
- }
-
- // Sort apps by importance for dexopt ordering. Important apps are given more priority
- // in case the device runs out of space.
-
- // Give priority to core apps.
- for (PackageParser.Package pkg : pkgs) {
- if (pkg.coreApp) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding core app " + mDexoptPackages.size() + ": " + pkg.packageName);
- }
- mDexoptPackages.add(pkg);
- }
- }
- pkgs.removeAll(mDexoptPackages);
-
- // 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 : pkgs) {
- if (pkgNames.contains(pkg.packageName)) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding pre boot system app " + mDexoptPackages.size() + ": " +
- pkg.packageName);
- }
- mDexoptPackages.add(pkg);
- }
- }
- pkgs.removeAll(mDexoptPackages);
-
- // Filter out packages that aren't recently used, add all remaining apps.
- // TODO: add a property to control this?
- if (mPackageManagerService.isHistoricalPackageUsageAvailable()) {
- filterRecentlyUsedApps(pkgs, DEXOPT_LRU_THRESHOLD_IN_MINUTES * 60 * 1000);
- }
- mDexoptPackages.addAll(pkgs);
-
- // 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 : mDexoptPackages) {
- dependencies.addAll(mPackageManagerService.findSharedNonSystemLibraries(p));
- }
- if (!dependencies.isEmpty()) {
- dependencies.removeAll(mDexoptPackages);
- }
- mDexoptPackages.addAll(dependencies);
-
- if (DEBUG_DEXOPT) {
- StringBuilder sb = new StringBuilder();
- for (PackageParser.Package pkg : mDexoptPackages) {
- if (sb.length() > 0) {
- sb.append(", ");
- }
- sb.append(pkg.packageName);
- }
- Log.i(TAG, "Packages to be optimized: " + sb.toString());
+ mDexoptPackages = PackageManagerServiceUtils.getPackagesForDexopt(
+ mPackageManagerService.mPackages.values(), mPackageManagerService);
}
}
@@ -228,29 +166,6 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
return pkgNames;
}
- private void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs,
- long dexOptLRUThresholdInMills) {
- // Filter out packages that aren't recently used.
- 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++;
- }
- }
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
- }
- }
-
private static class OTADexoptPackageDexOptimizer extends
PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 31d16cddee76..8a94ce5cb1bb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -282,6 +282,7 @@ 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.Map;
import java.util.Objects;
@@ -6778,30 +6779,17 @@ public class PackageManagerService extends IPackageManager.Stub {
// Extract pacakges only if profile-guided compilation is enabled because
// otherwise BackgroundDexOptService will not dexopt them later.
if (mUseJitProfiles) {
- ArraySet<String> pkgs = getOptimizablePackages();
- if (pkgs != null) {
- for (String pkg : pkgs) {
- performDexOpt(pkg, null /* instructionSet */, false /* useProfiles */,
- true /* extractOnly */, false /* force */);
- }
+ List<PackageParser.Package> pkgs;
+ synchronized (mPackages) {
+ pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
}
- }
- }
-
- private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
- List<ResolveInfo> ris = null;
- try {
- ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0, userId);
- } catch (RemoteException e) {
- }
- ArraySet<String> pkgNames = new ArraySet<String>();
- if (ris != null) {
- for (ResolveInfo ri : ris) {
- pkgNames.add(ri.activityInfo.packageName);
+ for (PackageParser.Package pkg : pkgs) {
+ if (PackageDexOptimizer.canOptimizePackage(pkg)) {
+ performDexOpt(pkg.packageName, null /* instructionSet */,
+ false /* useProfiles */, true /* extractOnly */, false /* force */);
+ }
}
}
- return pkgNames;
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
new file mode 100644
index 000000000000..2c6d2b69395e
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.app.AppGlobals;
+import android.content.Intent;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.Package;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+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 static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
+import static com.android.server.pm.PackageManagerService.TAG;
+
+/**
+ * Class containing helper methods for the PackageManagerService.
+ *
+ * {@hide}
+ */
+public class PackageManagerServiceUtils {
+ // Apps used in the last 7 days.
+ private final static long DEXOPT_LRU_THRESHOLD_IN_MINUTES = 7 * 24 * 60;
+
+ private static ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
+ List<ResolveInfo> ris = null;
+ try {
+ ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId);
+ } catch (RemoteException e) {
+ }
+ ArraySet<String> pkgNames = new ArraySet<String>();
+ if (ris != null) {
+ for (ResolveInfo ri : ris) {
+ pkgNames.add(ri.activityInfo.packageName);
+ }
+ }
+ return pkgNames;
+ }
+
+ private static void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs,
+ long dexOptLRUThresholdInMills) {
+ // Filter out packages that aren't recently used.
+ 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++;
+ }
+ }
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
+ }
+ }
+
+ // Sort apps by importance for dexopt ordering. Important apps are given
+ // more priority in case the device runs out of space.
+ public static List<PackageParser.Package> getPackagesForDexopt(
+ Collection<PackageParser.Package> packages,
+ PackageManagerService packageManagerService) {
+ ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages);
+ LinkedList<PackageParser.Package> result = new LinkedList<>();
+
+ // 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);
+
+ // 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);
+
+ // Filter out packages that aren't recently used, add all remaining apps.
+ // TODO: add a property to control this?
+ if (packageManagerService.isHistoricalPackageUsageAvailable()) {
+ filterRecentlyUsedApps(remainingPkgs, DEXOPT_LRU_THRESHOLD_IN_MINUTES * 60 * 1000);
+ }
+ 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()) {
+ dependencies.removeAll(result);
+ }
+ result.addAll(dependencies);
+
+ if (DEBUG_DEXOPT) {
+ StringBuilder sb = new StringBuilder();
+ for (PackageParser.Package pkg : result) {
+ if (sb.length() > 0) {
+ sb.append(", ");
+ }
+ sb.append(pkg.packageName);
+ }
+ Log.i(TAG, "Packages to be optimized: " + sb.toString());
+ }
+
+ return result;
+ }
+} \ No newline at end of file