Apply 'used in last 7 days' filter to OTA package extraction
Bug: 26813999 Change-Id: I5f1eddb1d5e9f0bbaab62d86e6ccf3cc097c4edb
This commit is contained in:
@@ -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 {
|
||||
|
||||
|
||||
@@ -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,32 +6779,19 @@ 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);
|
||||
}
|
||||
for (PackageParser.Package pkg : pkgs) {
|
||||
if (PackageDexOptimizer.canOptimizePackage(pkg)) {
|
||||
performDexOpt(pkg.packageName, null /* instructionSet */,
|
||||
false /* useProfiles */, true /* extractOnly */, false /* force */);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
return pkgNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPackageUse(String packageName) {
|
||||
synchronized (mPackages) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user