Loading services/core/java/com/android/server/pm/PackageDexOptimizer.java +51 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.os.SystemClock; import android.os.SystemProperties; 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; Loading Loading @@ -79,7 +80,7 @@ import java.util.Map; * Helper class for running dexopt command on packages. */ public class PackageDexOptimizer { private static final String TAG = "PackageManager.DexOptimizer"; private static final String TAG = "PackageDexOptimizer"; static final String OAT_DIR_NAME = "oat"; // TODO b/19550105 Remove error codes and use exceptions public static final int DEX_OPT_SKIPPED = 0; Loading Loading @@ -307,6 +308,55 @@ public class PackageDexOptimizer { } } /** * Perform dexopt (if needed) on a system server code path). */ public int dexoptSystemServerPath( String dexPath, PackageDexUsage.DexUseInfo dexUseInfo, DexoptOptions options) { 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( dexPath, isa, options.getCompilerFilter(), dexUseInfo.getClassLoaderContext(), /* newProfile= */false, /* downgrade= */ false); if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) { continue; } try { mInstaller.dexopt( dexPath, android.os.Process.SYSTEM_UID, /* packageName= */ "android", isa, dexoptNeeded, /* oatDir= */ null, dexoptFlags, options.getCompilerFilter(), StorageManager.UUID_PRIVATE_INTERNAL, dexUseInfo.getClassLoaderContext(), /* seInfo= */ null, /* downgrade= */ false , /* targetSdk= */ 0, /* profileName */ null, /* dexMetadataPath */ null, getReasonName(options.getCompilationReason())); } 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 : ""; Loading services/core/java/com/android/server/pm/PackageManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -9855,6 +9855,11 @@ public class PackageManagerService extends IPackageManager.Stub private int performDexOptInternalWithDependenciesLI(AndroidPackage p, @NonNull PackageSetting pkgSetting, DexoptOptions options) { // System server gets a special path. if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) { return mDexManager.dexoptSystemServer(options); } // Select the dex optimizer based on the force parameter. // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to // allocate an object here. services/core/java/com/android/server/pm/dex/DexManager.java +80 −9 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; Loading Loading @@ -437,15 +439,7 @@ public class DexManager { * because they don't need to be compiled).. */ public boolean dexoptSecondaryDex(DexoptOptions options) { // Select the dex optimizer based on the force parameter. // Forced compilation is done through ForcedUpdatePackageDexOptimizer which will adjust // the necessary dexopt flags to make sure that compilation is not skipped. This avoid // passing the force flag through the multitude of layers. // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to // allocate an object here. PackageDexOptimizer pdo = options.isForce() ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; PackageDexOptimizer pdo = getPackageDexOptimizer(options); String packageName = options.getPackageName(); PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName); if (useInfo.getDexUseInfoMap().isEmpty()) { Loading Loading @@ -485,6 +479,83 @@ 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) { if (!PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) { Slog.wtf(TAG, "Non system server package used when trying to dexopt system server:" + options.getPackageName()); return PackageDexOptimizer.DEX_OPT_FAILED; } PackageDexOptimizer pdo = getPackageDexOptimizer(options); String packageName = options.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; } int newResult = pdo.dexoptSystemServerPath(dexPath, dexUseInfo, options); // 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 * the necessary dexopt flags to make sure that compilation is not skipped. This avoid * passing the force flag through the multitude of layers. * Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to * allocate an object here. */ private PackageDexOptimizer getPackageDexOptimizer(DexoptOptions options) { return options.isForce() ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; } /** * Reconcile the information we have about the secondary dex files belonging to * {@code packagName} and the actual dex files. For all dex files that were Loading Loading
services/core/java/com/android/server/pm/PackageDexOptimizer.java +51 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.os.SystemClock; import android.os.SystemProperties; 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; Loading Loading @@ -79,7 +80,7 @@ import java.util.Map; * Helper class for running dexopt command on packages. */ public class PackageDexOptimizer { private static final String TAG = "PackageManager.DexOptimizer"; private static final String TAG = "PackageDexOptimizer"; static final String OAT_DIR_NAME = "oat"; // TODO b/19550105 Remove error codes and use exceptions public static final int DEX_OPT_SKIPPED = 0; Loading Loading @@ -307,6 +308,55 @@ public class PackageDexOptimizer { } } /** * Perform dexopt (if needed) on a system server code path). */ public int dexoptSystemServerPath( String dexPath, PackageDexUsage.DexUseInfo dexUseInfo, DexoptOptions options) { 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( dexPath, isa, options.getCompilerFilter(), dexUseInfo.getClassLoaderContext(), /* newProfile= */false, /* downgrade= */ false); if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) { continue; } try { mInstaller.dexopt( dexPath, android.os.Process.SYSTEM_UID, /* packageName= */ "android", isa, dexoptNeeded, /* oatDir= */ null, dexoptFlags, options.getCompilerFilter(), StorageManager.UUID_PRIVATE_INTERNAL, dexUseInfo.getClassLoaderContext(), /* seInfo= */ null, /* downgrade= */ false , /* targetSdk= */ 0, /* profileName */ null, /* dexMetadataPath */ null, getReasonName(options.getCompilationReason())); } 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 : ""; Loading
services/core/java/com/android/server/pm/PackageManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -9855,6 +9855,11 @@ public class PackageManagerService extends IPackageManager.Stub private int performDexOptInternalWithDependenciesLI(AndroidPackage p, @NonNull PackageSetting pkgSetting, DexoptOptions options) { // System server gets a special path. if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) { return mDexManager.dexoptSystemServer(options); } // Select the dex optimizer based on the force parameter. // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to // allocate an object here.
services/core/java/com/android/server/pm/dex/DexManager.java +80 −9 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; Loading Loading @@ -437,15 +439,7 @@ public class DexManager { * because they don't need to be compiled).. */ public boolean dexoptSecondaryDex(DexoptOptions options) { // Select the dex optimizer based on the force parameter. // Forced compilation is done through ForcedUpdatePackageDexOptimizer which will adjust // the necessary dexopt flags to make sure that compilation is not skipped. This avoid // passing the force flag through the multitude of layers. // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to // allocate an object here. PackageDexOptimizer pdo = options.isForce() ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; PackageDexOptimizer pdo = getPackageDexOptimizer(options); String packageName = options.getPackageName(); PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName); if (useInfo.getDexUseInfoMap().isEmpty()) { Loading Loading @@ -485,6 +479,83 @@ 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) { if (!PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) { Slog.wtf(TAG, "Non system server package used when trying to dexopt system server:" + options.getPackageName()); return PackageDexOptimizer.DEX_OPT_FAILED; } PackageDexOptimizer pdo = getPackageDexOptimizer(options); String packageName = options.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; } int newResult = pdo.dexoptSystemServerPath(dexPath, dexUseInfo, options); // 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 * the necessary dexopt flags to make sure that compilation is not skipped. This avoid * passing the force flag through the multitude of layers. * Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to * allocate an object here. */ private PackageDexOptimizer getPackageDexOptimizer(DexoptOptions options) { return options.isForce() ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; } /** * Reconcile the information we have about the secondary dex files belonging to * {@code packagName} and the actual dex files. For all dex files that were Loading