diff options
| author | 2017-11-02 18:24:12 +0000 | |
|---|---|---|
| committer | 2017-11-02 18:24:12 +0000 | |
| commit | 1c6eeaec1b09dbfdfdc045510a0eeeac00b1d214 (patch) | |
| tree | fde84e140f111e8e1a3548279206155a136e807e | |
| parent | c214d506d441713154361695c07d18dbe172cecb (diff) | |
| parent | 1ad0304e7db43f813787df734cb84fa6b65fbc3f (diff) | |
Merge "Ensure dexopt is executed only with consistent package data"
am: 1ad0304e7d
Change-Id: I32a9c3cf57d0726d7959eb331530fab7f79a7619
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageDexOptimizer.java | 12 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 74 | 
2 files changed, 56 insertions, 30 deletions
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 9c4e6c6b07ea..95b347c4fe14 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -40,6 +40,7 @@ import com.android.server.pm.dex.PackageDexUsage;  import java.io.File;  import java.io.IOException;  import java.util.ArrayList; +import java.util.Arrays;  import java.util.List;  import java.util.Map; @@ -161,6 +162,17 @@ public class PackageDexOptimizer {          String[] classLoaderContexts = DexoptUtils.getClassLoaderContexts(                  pkg.applicationInfo, sharedLibraries); +        // Sanity check that we do not call dexopt with inconsistent data. +        if (paths.size() != classLoaderContexts.length) { +            String[] splitCodePaths = pkg.applicationInfo.getSplitCodePaths(); +            throw new IllegalStateException("Inconsistent information " +                + "between PackageParser.Package and its ApplicationInfo. " +                + "pkg.getAllCodePaths=" + paths +                + " pkg.applicationInfo.getBaseCodePath=" + pkg.applicationInfo.getBaseCodePath() +                + " pkg.applicationInfo.getSplitCodePaths=" +                + (splitCodePaths == null ? "null" : Arrays.toString(splitCodePaths))); +        } +          int result = DEX_OPT_SKIPPED;          for (int i = 0; i < paths.size(); i++) {              // Skip paths that have no code. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a8ea4eaee4fd..2e34d9a13d2e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -18263,36 +18263,6 @@ public class PackageManagerService extends IPackageManager.Stub                      Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());                  }              } - -            // dexopt can take some time to complete, so, for instant apps, we skip this -            // step during installation. Instead, we'll take extra time the first time the -            // instant app starts. It's preferred to do it this way to provide continuous -            // progress to the user instead of mysteriously blocking somewhere in the -            // middle of running an instant app. The default behaviour can be overridden -            // via gservices. -            if (!instantApp || Global.getInt( -                        mContext.getContentResolver(), Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0) { -                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); -                // Do not run PackageDexOptimizer through the local performDexOpt -                // method because `pkg` may not be in `mPackages` yet. -                // -                // Also, don't fail application installs if the dexopt step fails. -                DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName, -                        REASON_INSTALL, -                        DexoptOptions.DEXOPT_BOOT_COMPLETE); -                mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, -                        null /* instructionSets */, -                        getOrCreateCompilerPackageStats(pkg), -                        mDexManager.getPackageUseInfoOrDefault(pkg.packageName), -                        dexoptOptions); -                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); -            } - -            // Notify BackgroundDexOptService that the package has been changed. -            // If this is an update of a package which used to fail to compile, -            // BDOS will remove it from its blacklist. -            // TODO: Layering violation -            BackgroundDexOptService.notifyPackageChanged(pkg.packageName);          }          if (!args.doRename(res.returnCode, pkg, oldCodePath)) { @@ -18300,6 +18270,50 @@ public class PackageManagerService extends IPackageManager.Stub              return;          } +        // Verify if we need to dexopt the app. +        // +        // NOTE: it is *important* to call dexopt after doRename which will sync the +        // package data from PackageParser.Package and its corresponding ApplicationInfo. +        // +        // We only need to dexopt if the package meets ALL of the following conditions: +        //   1) it is not forward locked. +        //   2) it is not on on an external ASEC container. +        //   3) it is not an instant app or if it is then dexopt is enabled via gservices. +        // +        // Note that we do not dexopt instant apps by default. dexopt can take some time to +        // complete, so we skip this step during installation. Instead, we'll take extra time +        // the first time the instant app starts. It's preferred to do it this way to provide +        // continuous progress to the useur instead of mysteriously blocking somewhere in the +        // middle of running an instant app. The default behaviour can be overridden +        // via gservices. +        final boolean performDexopt = !forwardLocked +            && !pkg.applicationInfo.isExternalAsec() +            && (!instantApp || Global.getInt(mContext.getContentResolver(), +                    Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0); + +        if (performDexopt) { +            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); +            // Do not run PackageDexOptimizer through the local performDexOpt +            // method because `pkg` may not be in `mPackages` yet. +            // +            // Also, don't fail application installs if the dexopt step fails. +            DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName, +                REASON_INSTALL, +                DexoptOptions.DEXOPT_BOOT_COMPLETE); +            mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, +                null /* instructionSets */, +                getOrCreateCompilerPackageStats(pkg), +                mDexManager.getPackageUseInfoOrDefault(pkg.packageName), +                dexoptOptions); +            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); +        } + +        // Notify BackgroundDexOptService that the package has been changed. +        // If this is an update of a package which used to fail to compile, +        // BackgroundDexOptService will remove it from its blacklist. +        // TODO: Layering violation +        BackgroundDexOptService.notifyPackageChanged(pkg.packageName); +          startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);          try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,  |