From dd63eba2d0794cfd2640103bc1d2d85d401697a8 Mon Sep 17 00:00:00 2001 From: Martin Stjernholm Date: Mon, 19 Dec 2022 02:48:10 +0000 Subject: [PATCH] Exclude the system server from background dexopt and remove the code that optimizes it. The system server can only be compiled and signed by odrefresh in early boot, so it is no use capturing dex load events for it. This complements commit 9789a45e19f653cf207c68e49b5f4dd36c43a9e3. Test: boot Bug: 254043366 Change-Id: Idda7957da72d72ddccccf95580d1bd85b520358f --- .../com/android/server/pm/DexOptHelper.java | 4 +- .../server/pm/PackageDexOptimizer.java | 73 ++-------------- .../com/android/server/pm/dex/DexManager.java | 83 ------------------- 3 files changed, 10 insertions(+), 150 deletions(-) diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index 39aa9c1bd7530..8757310cce746 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -555,9 +555,9 @@ public final class DexOptHelper { private int performDexOptInternalWithDependenciesLI( AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) throws LegacyDexoptDisabledException { - // System server gets a special path. if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) { - return mPm.getDexManager().dexoptSystemServer(options); + // This needs to be done in odrefresh in early boot, for security reasons. + throw new IllegalArgumentException("Cannot dexopt the system server"); } // Select the dex optimizer based on the force parameter. diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 0a7189231f602..f708fbb81dba3 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -59,7 +59,6 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.WorkSource; -import android.os.storage.StorageManager; import android.util.Log; import android.util.Slog; import android.util.SparseArray; @@ -184,10 +183,13 @@ public class PackageDexOptimizer { } boolean canOptimizePackage(@NonNull AndroidPackage pkg) { + // The system package has to be optimized during early boot by odrefresh instead. + if (PLATFORM_PACKAGE_NAME.equals(pkg.getPackageName())) { + return false; + } + // We do not dexopt a package with no code. - // Note that the system package is marked as having no code, however we can - // still optimize it via dexoptSystemServerPath. - if (!PLATFORM_PACKAGE_NAME.equals(pkg.getPackageName()) && !pkg.isHasCode()) { + if (!pkg.isHasCode()) { return false; } @@ -223,8 +225,8 @@ public class PackageDexOptimizer { PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) throws LegacyDexoptDisabledException { if (PLATFORM_PACKAGE_NAME.equals(pkg.getPackageName())) { - throw new IllegalArgumentException("System server dexopting should be done via " - + " DexManager and PackageDexOptimizer#dexoptSystemServerPath"); + throw new IllegalArgumentException( + "System server dexopting should be done via odrefresh"); } if (pkg.getUid() == -1) { throw new IllegalArgumentException("Dexopt for " + pkg.getPackageName() @@ -523,65 +525,6 @@ public class PackageDexOptimizer { } } - /** - * Perform dexopt (if needed) on a system server code path). - */ - @GuardedBy("mInstallLock") - @DexOptResult - public int dexoptSystemServerPath(String dexPath, PackageDexUsage.DexUseInfo dexUseInfo, - DexoptOptions options) throws LegacyDexoptDisabledException { - int dexoptFlags = DEXOPT_PUBLIC - | (options.isBootComplete() ? DEXOPT_BOOTCOMPLETE : 0) - | (options.isDexoptIdleBackgroundJob() ? DEXOPT_IDLE_BACKGROUND_JOB : 0); - - int result = DEX_OPT_SKIPPED; - for (String isa : dexUseInfo.getLoaderIsas()) { - int dexoptNeeded = getDexoptNeeded( - PackageManagerService.PLATFORM_PACKAGE_NAME, - dexPath, - isa, - options.getCompilerFilter(), - dexUseInfo.getClassLoaderContext(), - PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES, - /* downgrade= */ false, - dexoptFlags, - /* oatDir= */ null); - - if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) { - continue; - } - try { - synchronized (mInstallLock) { - boolean completed = getInstallerLI().dexopt( - dexPath, - android.os.Process.SYSTEM_UID, - /* pkgName= */ "android", - isa, - dexoptNeeded, - /* outputPath= */ null, - dexoptFlags, - options.getCompilerFilter(), - StorageManager.UUID_PRIVATE_INTERNAL, - dexUseInfo.getClassLoaderContext(), - /* seInfo= */ null, - /* downgrade= */ false, - /* targetSdkVersion= */ 0, - /* profileName= */ null, - /* dexMetadataPath= */ null, - getReasonName(options.getCompilationReason())); - if (!completed) { - return DEX_OPT_CANCELLED; - } - } - } catch (InstallerException e) { - Slog.w(TAG, "Failed to dexopt", e); - return DEX_OPT_FAILED; - } - result = DEX_OPT_PERFORMED; - } - return result; - } - private String getAugmentedReasonName(int compilationReason, boolean useDexMetadata) { String annotation = useDexMetadata ? ArtManagerService.DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : ""; diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index fbf7409a2e8b7..3d4f7b0e4ecc8 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -564,89 +564,6 @@ public class DexManager { return success; } - /** - * Performs dexopt on system server dex files. - * - *

Verfifies that the package name is {@link PackageManagerService#PLATFORM_PACKAGE_NAME}. - * - * @return - *

PackageDexOptimizer.DEX_OPT_SKIPPED if dexopt was skipped because no system server - * files were recorded or if no dexopt was needed. - *

PackageDexOptimizer.DEX_OPT_FAILED if any dexopt operation failed. - *

PackageDexOptimizer.DEX_OPT_PERFORMED if all dexopt operations succeeded. - */ - public int dexoptSystemServer(DexoptOptions options) throws LegacyDexoptDisabledException { - // TODO(b/254043366): Clean this up. - if (!isPlatformPackage(options.getPackageName())) { - Slog.wtf(TAG, "Non system server package used when trying to dexopt system server:" - + options.getPackageName()); - return PackageDexOptimizer.DEX_OPT_FAILED; - } - - // Override compiler filter for system server to the expected one. - // - // We could let the caller do this every time the invoke PackageManagerServer#dexopt. - // However, there are a few places were this will need to be done which creates - // redundancy and the danger of overlooking the config (and thus generating code that will - // waste storage and time). - DexoptOptions overriddenOptions = options.overrideCompilerFilter( - SYSTEM_SERVER_COMPILER_FILTER); - - PackageDexOptimizer pdo = getPackageDexOptimizer(overriddenOptions); - String packageName = overriddenOptions.getPackageName(); - PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName); - if (useInfo.getDexUseInfoMap().isEmpty()) { - if (DEBUG) { - Slog.d(TAG, "No dex files recorded for system server"); - } - // Nothing to compile, return true. - return PackageDexOptimizer.DEX_OPT_SKIPPED; - } - - boolean usageUpdated = false; - int result = PackageDexOptimizer.DEX_OPT_SKIPPED; - for (Map.Entry entry : useInfo.getDexUseInfoMap().entrySet()) { - String dexPath = entry.getKey(); - DexUseInfo dexUseInfo = entry.getValue(); - if (!Files.exists(Paths.get(dexPath))) { - if (DEBUG) { - Slog.w(TAG, "A dex file previously loaded by System Server does not exist " - + " anymore: " + dexPath); - } - usageUpdated = mPackageDexUsage.removeDexFile( - packageName, dexPath, dexUseInfo.getOwnerUserId()) || usageUpdated; - continue; - } - - if (dexUseInfo.isUnsupportedClassLoaderContext() - || dexUseInfo.isVariableClassLoaderContext()) { - String debugMsg = dexUseInfo.isUnsupportedClassLoaderContext() - ? "unsupported" - : "variable"; - Slog.w(TAG, "Skipping dexopt for system server path loaded with " + debugMsg - + " class loader context: " + dexPath); - continue; - } - - int newResult = pdo.dexoptSystemServerPath(dexPath, dexUseInfo, overriddenOptions); - - // The end result is: - // - FAILED if any path failed, - // - PERFORMED if at least one path needed compilation, - // - SKIPPED when all paths are up to date - if ((result != PackageDexOptimizer.DEX_OPT_FAILED) - && (newResult != PackageDexOptimizer.DEX_OPT_SKIPPED)) { - result = newResult; - } - } - - if (usageUpdated) { - mPackageDexUsage.maybeWriteAsync(); - } - - return result; - } - /** * Select the dex optimizer based on the force parameter. * Forced compilation is done through ForcedUpdatePackageDexOptimizer which will adjust