PackageManagerServiceUtils.java revision 90e269917e1d8f9fadb12c3528b8c360b2271e82
15b539461dcc159bd89297443780d635ccc5e3564John Hoford/*
25b539461dcc159bd89297443780d635ccc5e3564John Hoford * Copyright (C) 2016 The Android Open Source Project
35b539461dcc159bd89297443780d635ccc5e3564John Hoford *
45b539461dcc159bd89297443780d635ccc5e3564John Hoford * Licensed under the Apache License, Version 2.0 (the "License");
55b539461dcc159bd89297443780d635ccc5e3564John Hoford * you may not use this file except in compliance with the License.
65b539461dcc159bd89297443780d635ccc5e3564John Hoford * You may obtain a copy of the License at
75b539461dcc159bd89297443780d635ccc5e3564John Hoford *
85b539461dcc159bd89297443780d635ccc5e3564John Hoford *      http://www.apache.org/licenses/LICENSE-2.0
95b539461dcc159bd89297443780d635ccc5e3564John Hoford *
105b539461dcc159bd89297443780d635ccc5e3564John Hoford * Unless required by applicable law or agreed to in writing, software
115b539461dcc159bd89297443780d635ccc5e3564John Hoford * distributed under the License is distributed on an "AS IS" BASIS,
125b539461dcc159bd89297443780d635ccc5e3564John Hoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135b539461dcc159bd89297443780d635ccc5e3564John Hoford * See the License for the specific language governing permissions and
145b539461dcc159bd89297443780d635ccc5e3564John Hoford * limitations under the License.
155b539461dcc159bd89297443780d635ccc5e3564John Hoford */
165b539461dcc159bd89297443780d635ccc5e3564John Hoford
175b539461dcc159bd89297443780d635ccc5e3564John Hofordpackage com.android.server.pm;
185b539461dcc159bd89297443780d635ccc5e3564John Hoford
195b539461dcc159bd89297443780d635ccc5e3564John Hofordimport static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
205b539461dcc159bd89297443780d635ccc5e3564John Hofordimport static com.android.server.pm.PackageManagerService.TAG;
215b539461dcc159bd89297443780d635ccc5e3564John Hoford
225b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.app.AppGlobals;
235b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.content.Intent;
245b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.content.pm.PackageParser;
255b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.content.pm.ResolveInfo;
265b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.os.RemoteException;
275b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.os.UserHandle;
285b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.util.ArraySet;
295b539461dcc159bd89297443780d635ccc5e3564John Hofordimport android.util.Log;
305b539461dcc159bd89297443780d635ccc5e3564John Hoford
315b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.ArrayList;
325b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.Collection;
335b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.Date;
345b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.HashSet;
355b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.Iterator;
365b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.LinkedList;
375b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.List;
385b539461dcc159bd89297443780d635ccc5e3564John Hofordimport java.util.Set;
395b539461dcc159bd89297443780d635ccc5e3564John Hoford
405b539461dcc159bd89297443780d635ccc5e3564John Hoford/**
415b539461dcc159bd89297443780d635ccc5e3564John Hoford * Class containing helper methods for the PackageManagerService.
425b539461dcc159bd89297443780d635ccc5e3564John Hoford *
435b539461dcc159bd89297443780d635ccc5e3564John Hoford * {@hide}
445b539461dcc159bd89297443780d635ccc5e3564John Hoford */
455b539461dcc159bd89297443780d635ccc5e3564John Hofordpublic class PackageManagerServiceUtils {
465b539461dcc159bd89297443780d635ccc5e3564John Hoford    private final static long SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;
475b539461dcc159bd89297443780d635ccc5e3564John Hoford
485b539461dcc159bd89297443780d635ccc5e3564John Hoford    private static ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
495b539461dcc159bd89297443780d635ccc5e3564John Hoford        List<ResolveInfo> ris = null;
505b539461dcc159bd89297443780d635ccc5e3564John Hoford        try {
515b539461dcc159bd89297443780d635ccc5e3564John Hoford            ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId)
525b539461dcc159bd89297443780d635ccc5e3564John Hoford                    .getList();
535b539461dcc159bd89297443780d635ccc5e3564John Hoford        } catch (RemoteException e) {
545b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
555b539461dcc159bd89297443780d635ccc5e3564John Hoford        ArraySet<String> pkgNames = new ArraySet<String>();
565b539461dcc159bd89297443780d635ccc5e3564John Hoford        if (ris != null) {
575b539461dcc159bd89297443780d635ccc5e3564John Hoford            for (ResolveInfo ri : ris) {
585b539461dcc159bd89297443780d635ccc5e3564John Hoford                pkgNames.add(ri.activityInfo.packageName);
595b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
605b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
615b539461dcc159bd89297443780d635ccc5e3564John Hoford        return pkgNames;
625b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
635b539461dcc159bd89297443780d635ccc5e3564John Hoford
645b539461dcc159bd89297443780d635ccc5e3564John Hoford    private static void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs,
655b539461dcc159bd89297443780d635ccc5e3564John Hoford            long dexOptLRUThresholdInMills) {
665b539461dcc159bd89297443780d635ccc5e3564John Hoford        // Filter out packages that aren't recently used.
675b539461dcc159bd89297443780d635ccc5e3564John Hoford        int total = pkgs.size();
685b539461dcc159bd89297443780d635ccc5e3564John Hoford        int skipped = 0;
695b539461dcc159bd89297443780d635ccc5e3564John Hoford        long now = System.currentTimeMillis();
705b539461dcc159bd89297443780d635ccc5e3564John Hoford        for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
715b539461dcc159bd89297443780d635ccc5e3564John Hoford            PackageParser.Package pkg = i.next();
725b539461dcc159bd89297443780d635ccc5e3564John Hoford            long then = pkg.getLatestForegroundPackageUseTimeInMills();
735b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (then + dexOptLRUThresholdInMills < now) {
745b539461dcc159bd89297443780d635ccc5e3564John Hoford                if (DEBUG_DEXOPT) {
755b539461dcc159bd89297443780d635ccc5e3564John Hoford                    Log.i(TAG, "Skipping dexopt of " + pkg.packageName +
765b539461dcc159bd89297443780d635ccc5e3564John Hoford                            " last used in foreground: " +
775b539461dcc159bd89297443780d635ccc5e3564John Hoford                            ((then == 0) ? "never" : new Date(then)));
785b539461dcc159bd89297443780d635ccc5e3564John Hoford                }
795b539461dcc159bd89297443780d635ccc5e3564John Hoford                i.remove();
805b539461dcc159bd89297443780d635ccc5e3564John Hoford                skipped++;
815b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
825b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
835b539461dcc159bd89297443780d635ccc5e3564John Hoford        if (DEBUG_DEXOPT) {
845b539461dcc159bd89297443780d635ccc5e3564John Hoford            Log.i(TAG, "Skipped dexopt " + skipped + " of " + total);
855b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
865b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
875b539461dcc159bd89297443780d635ccc5e3564John Hoford
885b539461dcc159bd89297443780d635ccc5e3564John Hoford    // Sort apps by importance for dexopt ordering. Important apps are given
895b539461dcc159bd89297443780d635ccc5e3564John Hoford    // more priority in case the device runs out of space.
905b539461dcc159bd89297443780d635ccc5e3564John Hoford    public static List<PackageParser.Package> getPackagesForDexopt(
915b539461dcc159bd89297443780d635ccc5e3564John Hoford            Collection<PackageParser.Package> packages,
925b539461dcc159bd89297443780d635ccc5e3564John Hoford            PackageManagerService packageManagerService) {
935b539461dcc159bd89297443780d635ccc5e3564John Hoford        ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages);
945b539461dcc159bd89297443780d635ccc5e3564John Hoford        LinkedList<PackageParser.Package> result = new LinkedList<>();
955b539461dcc159bd89297443780d635ccc5e3564John Hoford
965b539461dcc159bd89297443780d635ccc5e3564John Hoford        // Give priority to core apps.
975b539461dcc159bd89297443780d635ccc5e3564John Hoford        for (PackageParser.Package pkg : remainingPkgs) {
985b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (pkg.coreApp) {
995b539461dcc159bd89297443780d635ccc5e3564John Hoford                if (DEBUG_DEXOPT) {
1005b539461dcc159bd89297443780d635ccc5e3564John Hoford                    Log.i(TAG, "Adding core app " + result.size() + ": " + pkg.packageName);
1015b539461dcc159bd89297443780d635ccc5e3564John Hoford                }
1025b539461dcc159bd89297443780d635ccc5e3564John Hoford                result.add(pkg);
1035b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
1045b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1055b539461dcc159bd89297443780d635ccc5e3564John Hoford        remainingPkgs.removeAll(result);
1065b539461dcc159bd89297443780d635ccc5e3564John Hoford
1075b539461dcc159bd89297443780d635ccc5e3564John Hoford        // Give priority to system apps that listen for pre boot complete.
1085b539461dcc159bd89297443780d635ccc5e3564John Hoford        Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
1095b539461dcc159bd89297443780d635ccc5e3564John Hoford        ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
1105b539461dcc159bd89297443780d635ccc5e3564John Hoford        for (PackageParser.Package pkg : remainingPkgs) {
1115b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (pkgNames.contains(pkg.packageName)) {
1125b539461dcc159bd89297443780d635ccc5e3564John Hoford                if (DEBUG_DEXOPT) {
1135b539461dcc159bd89297443780d635ccc5e3564John Hoford                    Log.i(TAG, "Adding pre boot system app " + result.size() + ": " +
1145b539461dcc159bd89297443780d635ccc5e3564John Hoford                            pkg.packageName);
1155b539461dcc159bd89297443780d635ccc5e3564John Hoford                }
1165b539461dcc159bd89297443780d635ccc5e3564John Hoford                result.add(pkg);
1175b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
1185b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1195b539461dcc159bd89297443780d635ccc5e3564John Hoford        remainingPkgs.removeAll(result);
1205b539461dcc159bd89297443780d635ccc5e3564John Hoford
1215b539461dcc159bd89297443780d635ccc5e3564John Hoford        // Give priority to apps used by other apps.
1225b539461dcc159bd89297443780d635ccc5e3564John Hoford        for (PackageParser.Package pkg : remainingPkgs) {
1235b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (PackageDexOptimizer.isUsedByOtherApps(pkg)) {
1245b539461dcc159bd89297443780d635ccc5e3564John Hoford                if (DEBUG_DEXOPT) {
1255b539461dcc159bd89297443780d635ccc5e3564John Hoford                    Log.i(TAG, "Adding app used by other apps " + result.size() + ": " +
1265b539461dcc159bd89297443780d635ccc5e3564John Hoford                            pkg.packageName);
1275b539461dcc159bd89297443780d635ccc5e3564John Hoford                }
1285b539461dcc159bd89297443780d635ccc5e3564John Hoford                result.add(pkg);
1295b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
1305b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1315b539461dcc159bd89297443780d635ccc5e3564John Hoford        remainingPkgs.removeAll(result);
1325b539461dcc159bd89297443780d635ccc5e3564John Hoford
1335b539461dcc159bd89297443780d635ccc5e3564John Hoford        // Filter out packages that aren't recently used, add all remaining apps.
1345b539461dcc159bd89297443780d635ccc5e3564John Hoford        // TODO: add a property to control this?
1355b539461dcc159bd89297443780d635ccc5e3564John Hoford        if (packageManagerService.isHistoricalPackageUsageAvailable()) {
1365b539461dcc159bd89297443780d635ccc5e3564John Hoford            filterRecentlyUsedApps(remainingPkgs, SEVEN_DAYS_IN_MILLISECONDS);
1375b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1385b539461dcc159bd89297443780d635ccc5e3564John Hoford        result.addAll(remainingPkgs);
1395b539461dcc159bd89297443780d635ccc5e3564John Hoford
1405b539461dcc159bd89297443780d635ccc5e3564John Hoford        // Now go ahead and also add the libraries required for these packages.
1415b539461dcc159bd89297443780d635ccc5e3564John Hoford        // TODO: Think about interleaving things.
1425b539461dcc159bd89297443780d635ccc5e3564John Hoford        Set<PackageParser.Package> dependencies = new HashSet<>();
1435b539461dcc159bd89297443780d635ccc5e3564John Hoford        for (PackageParser.Package p : result) {
1445b539461dcc159bd89297443780d635ccc5e3564John Hoford            dependencies.addAll(packageManagerService.findSharedNonSystemLibraries(p));
1455b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1465b539461dcc159bd89297443780d635ccc5e3564John Hoford        if (!dependencies.isEmpty()) {
1475b539461dcc159bd89297443780d635ccc5e3564John Hoford            // We might have packages already in `result` that are dependencies
1485b539461dcc159bd89297443780d635ccc5e3564John Hoford            // of other packages. Make sure we don't add those to the list twice.
1495b539461dcc159bd89297443780d635ccc5e3564John Hoford            dependencies.removeAll(result);
1505b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1515b539461dcc159bd89297443780d635ccc5e3564John Hoford        result.addAll(dependencies);
1525b539461dcc159bd89297443780d635ccc5e3564John Hoford
153        if (DEBUG_DEXOPT) {
154            StringBuilder sb = new StringBuilder();
155            for (PackageParser.Package pkg : result) {
156                if (sb.length() > 0) {
157                    sb.append(", ");
158                }
159                sb.append(pkg.packageName);
160            }
161            Log.i(TAG, "Packages to be dexopted: " + sb.toString());
162        }
163
164        return result;
165    }
166}