Merge "Exclude the system server from background dexopt and remove the code that optimizes it."

This commit is contained in:
Martin Stjernholm
2023-01-10 19:03:18 +00:00
committed by Android (Google) Code Review
3 changed files with 10 additions and 150 deletions

View File

@@ -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.

View File

@@ -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 : "";

View File

@@ -564,89 +564,6 @@ public class DexManager {
return success;
}
/**
* Performs dexopt on system server dex files.
*
* <p>Verfifies that the package name is {@link PackageManagerService#PLATFORM_PACKAGE_NAME}.
*
* @return
* <p>PackageDexOptimizer.DEX_OPT_SKIPPED if dexopt was skipped because no system server
* files were recorded or if no dexopt was needed.
* <p>PackageDexOptimizer.DEX_OPT_FAILED if any dexopt operation failed.
* <p>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<String, DexUseInfo> 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