diff options
| author | 2016-02-04 11:54:17 +0000 | |
|---|---|---|
| committer | 2016-02-11 12:16:41 +0000 | |
| commit | 6b4736d604fd91aaedc6f3fe9be5a1e757aab86c (patch) | |
| tree | a1151abededb44eab9aa504cec9452ba1807357b | |
| parent | 4a70f09e39ac7c5f57b0f6dd44475641c68afafd (diff) | |
Apply 'used in last 7 days' filter to OTA package extraction
Bug: 26813999
Change-Id: I5f1eddb1d5e9f0bbaab62d86e6ccf3cc097c4edb
(cherry picked from commit e292175fbd495a63b48560439d2a84b239f91e18)
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 |