PackageManagerServiceUtils.java revision 6d99f796711882ba60977c211d0f92252fe7ad4a
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.pm; 18 19import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT; 20import static com.android.server.pm.PackageManagerService.TAG; 21 22import android.app.AppGlobals; 23import android.content.Intent; 24import android.content.pm.PackageParser; 25import android.content.pm.ResolveInfo; 26import android.os.RemoteException; 27import android.os.UserHandle; 28import android.system.ErrnoException; 29import android.util.ArraySet; 30import android.util.Log; 31import libcore.io.Libcore; 32 33import java.io.File; 34import java.io.IOException; 35import java.util.ArrayList; 36import java.util.Collection; 37import java.util.Date; 38import java.util.HashSet; 39import java.util.Iterator; 40import java.util.LinkedList; 41import java.util.List; 42import java.util.Set; 43 44/** 45 * Class containing helper methods for the PackageManagerService. 46 * 47 * {@hide} 48 */ 49public class PackageManagerServiceUtils { 50 private final static long SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000; 51 52 private static ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) { 53 List<ResolveInfo> ris = null; 54 try { 55 ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId) 56 .getList(); 57 } catch (RemoteException e) { 58 } 59 ArraySet<String> pkgNames = new ArraySet<String>(); 60 if (ris != null) { 61 for (ResolveInfo ri : ris) { 62 pkgNames.add(ri.activityInfo.packageName); 63 } 64 } 65 return pkgNames; 66 } 67 68 private static void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs, 69 long dexOptLRUThresholdInMills) { 70 // Filter out packages that aren't recently used. 71 int total = pkgs.size(); 72 int skipped = 0; 73 long now = System.currentTimeMillis(); 74 for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) { 75 PackageParser.Package pkg = i.next(); 76 long then = pkg.getLatestForegroundPackageUseTimeInMills(); 77 if (then + dexOptLRUThresholdInMills < now) { 78 if (DEBUG_DEXOPT) { 79 Log.i(TAG, "Skipping dexopt of " + pkg.packageName + 80 " last used in foreground: " + 81 ((then == 0) ? "never" : new Date(then))); 82 } 83 i.remove(); 84 skipped++; 85 } 86 } 87 if (DEBUG_DEXOPT) { 88 Log.i(TAG, "Skipped dexopt " + skipped + " of " + total); 89 } 90 } 91 92 // Sort apps by importance for dexopt ordering. Important apps are given 93 // more priority in case the device runs out of space. 94 public static List<PackageParser.Package> getPackagesForDexopt( 95 Collection<PackageParser.Package> packages, 96 PackageManagerService packageManagerService) { 97 ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages); 98 LinkedList<PackageParser.Package> result = new LinkedList<>(); 99 100 // Give priority to core apps. 101 for (PackageParser.Package pkg : remainingPkgs) { 102 if (pkg.coreApp) { 103 if (DEBUG_DEXOPT) { 104 Log.i(TAG, "Adding core app " + result.size() + ": " + pkg.packageName); 105 } 106 result.add(pkg); 107 } 108 } 109 remainingPkgs.removeAll(result); 110 111 // Give priority to system apps that listen for pre boot complete. 112 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); 113 ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM); 114 for (PackageParser.Package pkg : remainingPkgs) { 115 if (pkgNames.contains(pkg.packageName)) { 116 if (DEBUG_DEXOPT) { 117 Log.i(TAG, "Adding pre boot system app " + result.size() + ": " + 118 pkg.packageName); 119 } 120 result.add(pkg); 121 } 122 } 123 remainingPkgs.removeAll(result); 124 125 // Give priority to apps used by other apps. 126 for (PackageParser.Package pkg : remainingPkgs) { 127 if (PackageDexOptimizer.isUsedByOtherApps(pkg)) { 128 if (DEBUG_DEXOPT) { 129 Log.i(TAG, "Adding app used by other apps " + result.size() + ": " + 130 pkg.packageName); 131 } 132 result.add(pkg); 133 } 134 } 135 remainingPkgs.removeAll(result); 136 137 // Filter out packages that aren't recently used, add all remaining apps. 138 // TODO: add a property to control this? 139 if (packageManagerService.isHistoricalPackageUsageAvailable()) { 140 filterRecentlyUsedApps(remainingPkgs, SEVEN_DAYS_IN_MILLISECONDS); 141 } 142 result.addAll(remainingPkgs); 143 144 // Now go ahead and also add the libraries required for these packages. 145 // TODO: Think about interleaving things. 146 Set<PackageParser.Package> dependencies = new HashSet<>(); 147 for (PackageParser.Package p : result) { 148 dependencies.addAll(packageManagerService.findSharedNonSystemLibraries(p)); 149 } 150 if (!dependencies.isEmpty()) { 151 // We might have packages already in `result` that are dependencies 152 // of other packages. Make sure we don't add those to the list twice. 153 dependencies.removeAll(result); 154 } 155 result.addAll(dependencies); 156 157 if (DEBUG_DEXOPT) { 158 StringBuilder sb = new StringBuilder(); 159 for (PackageParser.Package pkg : result) { 160 if (sb.length() > 0) { 161 sb.append(", "); 162 } 163 sb.append(pkg.packageName); 164 } 165 Log.i(TAG, "Packages to be dexopted: " + sb.toString()); 166 } 167 168 return result; 169 } 170 171 /** 172 * Returns the canonicalized path of {@code path} as per {@code realpath(3)} 173 * semantics. 174 */ 175 public static String realpath(File path) throws IOException { 176 try { 177 return Libcore.os.realpath(path.getAbsolutePath()); 178 } catch (ErrnoException ee) { 179 throw ee.rethrowAsIOException(); 180 } 181 } 182} 183