Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b17969be authored by Calin Juravle's avatar Calin Juravle Committed by android-build-merger
Browse files

Merge changes from topic 'info-per-split' into oc-mr1-dev am: df421a8b

am: fe8ff821

Change-Id: I2ae4dd9455f34a10ddfdb368edd62f048b230d99
parents 066864a6 fe8ff821
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -318,7 +318,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
        optimizer.performDexOpt(pkg, libraryDependencies,
                null /* ISAs */,
                null /* CompilerStats.PackageStats */,
                mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName),
                mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName),
                new DexoptOptions(pkg.packageName, compilationReason,
                        DexoptOptions.DEXOPT_BOOT_COMPLETE));

+15 −11
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.DexoptUtils;
import com.android.server.pm.dex.PackageDexUsage;
@@ -112,7 +113,7 @@ public class PackageDexOptimizer {
     */
    int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
            String[] instructionSets, CompilerStats.PackageStats packageStats,
            boolean isUsedByOtherApps, DexoptOptions options) {
            PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
        if (!canOptimizePackage(pkg)) {
            return DEX_OPT_SKIPPED;
        }
@@ -120,7 +121,7 @@ public class PackageDexOptimizer {
            final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid);
            try {
                return performDexOptLI(pkg, sharedLibraries, instructionSets,
                        packageStats, isUsedByOtherApps, options);
                        packageStats, packageUseInfo, options);
            } finally {
                releaseWakeLockLI(acquireTime);
            }
@@ -134,21 +135,13 @@ public class PackageDexOptimizer {
    @GuardedBy("mInstallLock")
    private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
            String[] targetInstructionSets, CompilerStats.PackageStats packageStats,
            boolean isUsedByOtherApps, DexoptOptions options) {
            PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
        final String[] instructionSets = targetInstructionSets != null ?
                targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
        final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
        final List<String> paths = pkg.getAllCodePaths();
        final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);

        final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo,
                options.getCompilerFilter(), isUsedByOtherApps);
        final boolean profileUpdated = options.isCheckForProfileUpdates() &&
                isProfileUpdated(pkg, sharedGid, compilerFilter);

        // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags.
        final int dexoptFlags = getDexFlags(pkg, compilerFilter, options.isBootComplete());

        // Get the class loader context dependencies.
        // For each code path in the package, this array contains the class loader context that
        // needs to be passed to dexopt in order to ensure correct optimizations.
@@ -172,6 +165,17 @@ public class PackageDexOptimizer {
                }
            }

            final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary()
                    || packageUseInfo.isUsedByOtherApps(path);
            final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo,
                options.getCompilerFilter(), isUsedByOtherApps);
            final boolean profileUpdated = options.isCheckForProfileUpdates() &&
                isProfileUpdated(pkg, sharedGid, compilerFilter);

            // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
            // flags.
            final int dexoptFlags = getDexFlags(pkg, compilerFilter, options.isBootComplete());

            for (String dexCodeIsa : dexCodeInstructionSets) {
                int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter,
                        profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid,
+9 −7
Original line number Diff line number Diff line
@@ -9887,17 +9887,19 @@ public class PackageManagerService extends IPackageManager.Stub
        Collection<PackageParser.Package> deps = findSharedNonSystemLibraries(p);
        final String[] instructionSets = getAppDexInstructionSets(p.applicationInfo);
        if (!deps.isEmpty()) {
            DexoptOptions libraryOptions = new DexoptOptions(options.getPackageName(),
                    options.getCompilerFilter(), options.getSplitName(),
                    options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY);
            for (PackageParser.Package depPackage : deps) {
                // TODO: Analyze and investigate if we (should) profile libraries.
                pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets,
                        getOrCreateCompilerPackageStats(depPackage),
                        true /* isUsedByOtherApps */,
                        options);
                    mDexManager.getPackageUseInfoOrDefault(depPackage.packageName), libraryOptions);
            }
        }
        return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets,
                getOrCreateCompilerPackageStats(p),
                mDexManager.isUsedByOtherApps(p.packageName), options);
                mDexManager.getPackageUseInfoOrDefault(p.packageName), options);
    }
    /**
@@ -10023,7 +10025,7 @@ public class PackageManagerService extends IPackageManager.Stub
    public void shutdown() {
        mPackageUsage.writeNow(mPackages);
        mCompilerStats.writeNow();
        mDexManager.savePackageDexUsageNow();
        mDexManager.writePackageDexUsageNow();
    }
    @Override
@@ -18587,7 +18589,7 @@ public class PackageManagerService extends IPackageManager.Stub
                mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                        null /* instructionSets */,
                        getOrCreateCompilerPackageStats(pkg),
                        mDexManager.isUsedByOtherApps(pkg.packageName),
                        mDexManager.getPackageUseInfoOrDefault(pkg.packageName),
                        dexoptOptions);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
@@ -25424,8 +25426,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                if (ps == null) {
                    continue;
                }
                PackageDexUsage.PackageUseInfo packageUseInfo = getDexManager().getPackageUseInfo(
                        pkg.packageName);
                PackageDexUsage.PackageUseInfo packageUseInfo =
                      getDexManager().getPackageUseInfoOrDefault(pkg.packageName);
                if (PackageManagerServiceUtils
                        .isUnusedSinceTimeInMillis(ps.firstInstallTime, currentTimeInMillis,
                                downgradeTimeThresholdMillis, packageUseInfo,
+5 −6
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import static com.android.server.pm.PackageManagerService.TAG;
import android.annotation.NonNull;
import android.app.AppGlobals;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.content.pm.ResolveInfo;
import android.os.Build;
@@ -137,9 +136,11 @@ public class PackageManagerServiceUtils {
                sortTemp, packageManagerService);

        // Give priority to apps used by other apps.
        DexManager dexManager = packageManagerService.getDexManager();
        applyPackageFilter((pkg) ->
                packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result,
                remainingPkgs, sortTemp, packageManagerService);
                dexManager.getPackageUseInfoOrDefault(pkg.packageName)
                        .isAnyCodePathUsedByOtherApps(),
                result, remainingPkgs, sortTemp, packageManagerService);

        // Filter out packages that aren't recently used, add all remaining apps.
        // TODO: add a property to control this?
@@ -209,12 +210,10 @@ public class PackageManagerServiceUtils {

        // If the app was active in background during the threshold period and was used
        // by other packages.
        // If packageUseInfo is null, it can be said that the package was not used by other
        // packages.
        boolean isActiveInBackgroundAndUsedByOtherPackages = ((currentTimeInMillis
                - latestPackageUseTimeInMillis)
                < thresholdTimeinMillis)
                && (packageUseInfo != null && packageUseInfo.isUsedByOtherApps());
                && packageUseInfo.isAnyCodePathUsedByOtherApps();

        return !isActiveInBackgroundAndUsedByOtherPackages;
    }
+54 −26
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ import com.android.server.pm.PackageManagerServiceCompilerMapping;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.HashMap;
import java.util.HashSet;
@@ -81,6 +83,19 @@ public class DexManager {
    private static int DEX_SEARCH_FOUND_SPLIT = 2;  // dex file is a split apk
    private static int DEX_SEARCH_FOUND_SECONDARY = 3;  // dex file is a secondary dex

    /**
     * We do not record packages that have no secondary dex files or that are not used by other
     * apps. This is an optimization to reduce the amount of data that needs to be written to
     * disk (apps will not usually be shared so this trims quite a bit the number we record).
     *
     * To make this behaviour transparent to the callers which need use information on packages,
     * DexManager will return this DEFAULT instance from
     * {@link DexManager#getPackageUseInfoOrDefault}. It has no data about secondary dex files and
     * is marked as not being used by other apps. This reflects the intended behaviour when we don't
     * find the package in the underlying data file.
     */
    private final static PackageUseInfo DEFAULT_USE_INFO = new PackageUseInfo();

    public DexManager(IPackageManager pms, PackageDexOptimizer pdo,
            Installer installer, Object installLock) {
      mPackageCodeLocationsCache = new HashMap<>();
@@ -297,6 +312,8 @@ public class DexManager {

    private void loadInternal(Map<Integer, List<PackageInfo>> existingPackages) {
        Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
        Map<String, Set<String>> packageToCodePaths = new HashMap<>();

        // Cache the code locations for the installed packages. This allows for
        // faster lookups (no locks) when finding what package owns the dex file.
        for (Map.Entry<Integer, List<PackageInfo>> entry : existingPackages.entrySet()) {
@@ -306,25 +323,53 @@ public class DexManager {
                // Cache the code locations.
                cachePackageInfo(pi, userId);

                // Cache a map from package name to the set of user ids who installed the package.
                // Cache two maps:
                //   - from package name to the set of user ids who installed the package.
                //   - from package name to the set of code paths.
                // We will use it to sync the data and remove obsolete entries from
                // mPackageDexUsage.
                Set<Integer> users = putIfAbsent(
                        packageToUsersMap, pi.packageName, new HashSet<>());
                users.add(userId);

                Set<String> codePaths = putIfAbsent(
                    packageToCodePaths, pi.packageName, new HashSet<>());
                codePaths.add(pi.applicationInfo.sourceDir);
                if (pi.applicationInfo.splitSourceDirs != null) {
                    Collections.addAll(codePaths, pi.applicationInfo.splitSourceDirs);
                }
            }
        }

        mPackageDexUsage.read();
        mPackageDexUsage.syncData(packageToUsersMap);
        mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
    }

    /**
     * Get the package dex usage for the given package name.
     * @return the package data or null if there is no data available for this package.
     * If there is no usage info the method will return a default {@code PackageUseInfo} with
     * no data about secondary dex files and marked as not being used by other apps.
     *
     * Note that no use info means the package was not used or it was used but not by other apps.
     * Also, note that right now we might prune packages which are not used by other apps.
     * TODO(calin): maybe we should not (prune) so we can have an accurate view when we try
     * to access the package use.
     */
    public PackageUseInfo getPackageUseInfoOrDefault(String packageName) {
        PackageUseInfo useInfo = mPackageDexUsage.getPackageUseInfo(packageName);
        return useInfo == null ? DEFAULT_USE_INFO : useInfo;
    }

    /**
     * Return whether or not the manager has usage information on the give package.
     *
     * Note that no use info means the package was not used or it was used but not by other apps.
     * Also, note that right now we might prune packages which are not used by other apps.
     * TODO(calin): maybe we should not (prune) so we can have an accurate view when we try
     * to access the package use.
     */
    public PackageUseInfo getPackageUseInfo(String packageName) {
        return mPackageDexUsage.getPackageUseInfo(packageName);
    /*package*/ boolean hasInfoOnPackage(String packageName) {
        return mPackageDexUsage.getPackageUseInfo(packageName) != null;
    }

    /**
@@ -343,7 +388,7 @@ public class DexManager {
                ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer)
                : mPackageDexOptimizer;
        String packageName = options.getPackageName();
        PackageUseInfo useInfo = getPackageUseInfo(packageName);
        PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName);
        if (useInfo == null || useInfo.getDexUseInfoMap().isEmpty()) {
            if (DEBUG) {
                Slog.d(TAG, "No secondary dex use for package:" + packageName);
@@ -387,7 +432,7 @@ public class DexManager {
     * deleted, update the internal records and delete any generated oat files.
     */
    public void reconcileSecondaryDexFiles(String packageName) {
        PackageUseInfo useInfo = getPackageUseInfo(packageName);
        PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName);
        if (useInfo == null || useInfo.getDexUseInfoMap().isEmpty()) {
            if (DEBUG) {
                Slog.d(TAG, "No secondary dex use for package:" + packageName);
@@ -518,23 +563,6 @@ public class DexManager {
        return mPackageDexUsage.getAllPackagesWithSecondaryDexFiles();
    }

    /**
     * Return true if the profiling data collected for the given app indicate
     * that the apps's APK has been loaded by another app.
     * Note that this returns false for all apps without any collected profiling data.
    */
    public boolean isUsedByOtherApps(String packageName) {
        PackageUseInfo useInfo = getPackageUseInfo(packageName);
        if (useInfo == null) {
            // No use info, means the package was not used or it was used but not by other apps.
            // Note that right now we might prune packages which are not used by other apps.
            // TODO(calin): maybe we should not (prune) so we can have an accurate view when we try
            // to access the package use.
            return false;
        }
        return useInfo.isUsedByOtherApps();
    }

    /**
     * Retrieves the package which owns the given dexPath.
     */
@@ -593,9 +621,9 @@ public class DexManager {
    }

    /**
     * Saves the in-memory package dex usage to disk right away.
     * Writes the in-memory package dex usage to disk right away.
     */
    public void savePackageDexUsageNow() {
    public void writePackageDexUsageNow() {
        mPackageDexUsage.writeNow();
    }

Loading