summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <treehugger-gerrit@google.com> 2017-11-02 18:10:42 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2017-11-02 18:10:42 +0000
commit1ad0304e7db43f813787df734cb84fa6b65fbc3f (patch)
treefde84e140f111e8e1a3548279206155a136e807e
parentdfe472ecae7783040491b2fadc5a14ad8e9bff6c (diff)
parent563a5cad666555b8bed26fb4eb01c9bd20c2421a (diff)
Merge "Ensure dexopt is executed only with consistent package data"
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java74
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,