summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/Installer.java13
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java23
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java36
3 files changed, 64 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 9329f063aee5..0d417e457509 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -136,9 +136,7 @@ public class Installer extends SystemService {
}
/**
- * @param isolated indicates if this object should <em>not</em> connect to
- * the real {@code installd}. All remote calls will be ignored
- * unless you extend this class and intercept them.
+ * @param isolated Make the installer isolated. See {@link isIsolated}.
*/
public Installer(Context context, boolean isolated) {
super(context);
@@ -153,6 +151,15 @@ public class Installer extends SystemService {
mWarnIfHeld = warnIfHeld;
}
+ /**
+ * Returns true if the installer is isolated, i.e. if this object should <em>not</em> connect to
+ * the real {@code installd}. All remote calls will be ignored unless you extend this class and
+ * intercept them.
+ */
+ public boolean isIsolated() {
+ return mIsolated;
+ }
+
@Override
public void onStart() {
if (mIsolated) {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 767c0a73bc54..6a2ddc8f94b0 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import static com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -301,6 +302,15 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
throws InstallerException {
final StringBuilder builder = new StringBuilder();
+ if (useArtService()) {
+ if ((dexFlags & DEXOPT_SECONDARY_DEX) != 0) {
+ // installd may change the reference profile in place for secondary dex
+ // files, which isn't safe with the lock free approach in ART Service.
+ throw new IllegalArgumentException(
+ "Invalid OTA dexopt call for secondary dex");
+ }
+ }
+
// The current version. For v10, see b/115993344.
builder.append("10 ");
@@ -353,7 +363,6 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
collectingInstaller, mPackageManagerService.mInstallLock, mContext);
- // TODO(b/251903639): Allow this use of legacy dexopt code even when ART Service is enabled.
try {
optimizer.performDexOpt(pkg, pkgSetting, null /* ISAs */,
null /* CompilerStats.PackageStats */,
@@ -362,9 +371,19 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
new DexoptOptions(pkg.getPackageName(), compilationReason,
DexoptOptions.DEXOPT_BOOT_COMPLETE));
} catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ // OTA is still allowed to use the legacy dexopt code even when ART Service is enabled.
+ // The installer is isolated and won't call into installd, and the dexopt() method is
+ // overridden to only collect the command above. Hence we shouldn't go into any code
+ // path where this exception is thrown.
+ Slog.wtf(TAG, e);
}
+ // ART Service compat note: These commands are consumed by the otapreopt binary, which uses
+ // the same legacy dexopt code as installd to invoke dex2oat. It provides output path
+ // implementations (see calculate_odex_file_path and create_cache_path in
+ // frameworks/native/cmds/installd/otapreopt.cpp) to write to different odex files than
+ // those used by ART Service in its ordinary operations, so it doesn't interfere with ART
+ // Service even when dalvik.vm.useartservice is true.
return commands;
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 0a90e7a30db6..8a4080ff029d 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -18,6 +18,7 @@ package com.android.server.pm;
import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
+import static com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS;
@@ -329,8 +330,22 @@ public class PackageDexOptimizer {
String profileName = ArtManager.getProfileName(
i == 0 ? null : pkg.getSplitNames()[i - 1]);
- final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary()
- || packageUseInfo.isUsedByOtherApps(path);
+
+ final boolean isUsedByOtherApps;
+ if (options.isDexoptAsSharedLibrary()) {
+ isUsedByOtherApps = true;
+ } else if (useArtService()) {
+ // We get here when collecting dexopt commands in OTA preopt, even when ART Service
+ // is in use. packageUseInfo isn't useful in that case since the legacy dex use
+ // database hasn't been updated. So we'd have to query ART Service instead, but it
+ // doesn't provide that API. Just cop-out and bypass the cloud profile handling.
+ // That means such apps will get preopted wrong, and we'll leave it to a later
+ // background dexopt after reboot instead.
+ isUsedByOtherApps = false;
+ } else {
+ isUsedByOtherApps = packageUseInfo.isUsedByOtherApps(path);
+ }
+
String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter());
// If the app is used by other apps, we must not use the existing profile because it
// may contain user data, unless the profile is newly created on install.
@@ -446,6 +461,14 @@ public class PackageDexOptimizer {
private boolean prepareCloudProfile(AndroidPackage pkg, String profileName, String path,
@Nullable String dexMetadataPath) throws LegacyDexoptDisabledException {
if (dexMetadataPath != null) {
+ if (mInstaller.isIsolated()) {
+ // If the installer is isolated, the two calls to it below will return immediately,
+ // so this only short-circuits that a bit. We need to do it to avoid the
+ // LegacyDexoptDisabledException getting thrown first, when we get here during OTA
+ // preopt and ART Service is enabled.
+ return true;
+ }
+
try {
// Make sure we don't keep any existing contents.
mInstaller.deleteReferenceProfile(pkg.getPackageName(), profileName);
@@ -879,7 +902,12 @@ public class PackageDexOptimizer {
private int getDexoptNeeded(String packageName, String path, String isa, String compilerFilter,
String classLoaderContext, int profileAnalysisResult, boolean downgrade,
int dexoptFlags, String oatDir) throws LegacyDexoptDisabledException {
- Installer.checkLegacyDexoptDisabled();
+ // Allow calls from OtaDexoptService even when ART Service is in use. The installer is
+ // isolated in that case so later calls to it won't call into installd anyway.
+ if (!mInstaller.isIsolated()) {
+ Installer.checkLegacyDexoptDisabled();
+ }
+
final boolean shouldBePublic = (dexoptFlags & DEXOPT_PUBLIC) != 0;
final boolean isProfileGuidedFilter = (dexoptFlags & DEXOPT_PROFILE_GUIDED) != 0;
boolean newProfile = profileAnalysisResult == PROFILE_ANALYSIS_OPTIMIZE;
@@ -948,6 +976,8 @@ public class PackageDexOptimizer {
*/
private int analyseProfiles(AndroidPackage pkg, int uid, String profileName,
String compilerFilter) throws LegacyDexoptDisabledException {
+ Installer.checkLegacyDexoptDisabled();
+
// Check if we are allowed to merge and if the compiler filter is profile guided.
if (!isProfileGuidedCompilerFilter(compilerFilter)) {
return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;