Loading core/java/android/content/pm/IPackageManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -452,6 +452,9 @@ interface IPackageManager { */ boolean performDexOptIfNeeded(String packageName, String instructionSet); boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly, boolean force); void forceDexOpt(String packageName); /** Loading services/core/java/com/android/server/pm/BackgroundDexOptService.java +1 −1 Original line number Diff line number Diff line Loading @@ -94,7 +94,7 @@ public class BackgroundDexOptService extends JobService { continue; } if (!pm.performDexOpt(pkg, /* instruction set */ null, useJitProfiles, /* extractOnly */ false)) { /* extractOnly */ false, /* force */ false)) { // there was a problem running dexopt, // remember this so we do not keep retrying. sFailedPackageNames.add(pkg); Loading services/core/java/com/android/server/pm/PackageDexOptimizer.java +24 −20 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ final class PackageDexOptimizer { * {@link PackageManagerService#mInstallLock}. */ int performDexOpt(PackageParser.Package pkg, String[] instructionSets, boolean inclDependencies, boolean useProfiles, boolean extractOnly) { boolean inclDependencies, boolean useProfiles, boolean extractOnly, boolean force) { ArraySet<String> done; if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) { done = new ArraySet<String>(); Loading @@ -97,7 +97,7 @@ final class PackageDexOptimizer { } try { return performDexOptLI(pkg, instructionSets, done, useProfiles, extractOnly); extractOnly, force); } finally { if (useLock) { mDexoptWakeLock.release(); Loading @@ -107,7 +107,7 @@ final class PackageDexOptimizer { } private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets, ArraySet<String> done, boolean useProfiles, boolean extractOnly) { ArraySet<String> done, boolean useProfiles, boolean extractOnly, boolean force) { final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); Loading @@ -128,17 +128,26 @@ final class PackageDexOptimizer { final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0; final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (useProfiles) { // If we do a profile guided compilation then we might recompile // the same package if more profile information is available. force = true; } final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); boolean performedDexOpt = false; final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); for (String dexCodeInstructionSet : dexCodeInstructionSets) { if (!useProfiles && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { // Skip only if we do not use profiles since they might trigger a recompilation. if (!force && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { continue; } for (String path : paths) { int dexoptNeeded; if (force) { dexoptNeeded = DexFile.DEX2OAT_NEEDED; } else { try { dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName, dexCodeInstructionSet, /* defer */false); Loading @@ -146,17 +155,12 @@ final class PackageDexOptimizer { Slog.w(TAG, "IOException reading apk: " + path, ioe); return DEX_OPT_FAILED; } } if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) { if (useProfiles) { // If we do a profile guided compilation then we might recompile the same // package if more profile information is available. dexoptNeeded = DexFile.DEX2OAT_NEEDED; } else { // No dexopt needed and we don't use profiles. Nothing to do. continue; } } final String dexoptType; String oatDir = null; if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) { Loading Loading @@ -252,7 +256,7 @@ final class PackageDexOptimizer { // TODO: Analyze and investigate if we (should) profile libraries. // Currently this will do a full compilation of the library. performDexOptLI(libPkg, instructionSets, done, /*useProfiles*/ false, /* extractOnly */ false); /* extractOnly */ false, /* force */ false); } } } Loading services/core/java/com/android/server/pm/PackageManagerService.java +13 −11 Original line number Diff line number Diff line Loading @@ -6639,7 +6639,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkgs != null) { for (String pkg : pkgs) { performDexOpt(pkg, null /* instructionSet */, false /* useProfiles */, true /* extractOnly */); true /* extractOnly */, false /* force */); } } } Loading Loading @@ -6676,26 +6676,28 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean performDexOptIfNeeded(String packageName, String instructionSet) { return performDexOptTraced(packageName, instructionSet, false /* useProfiles */, false /* extractOnly */); false /* extractOnly */, false /* force */); } @Override public boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly) { return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly); boolean extractOnly, boolean force) { return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly, force); } private boolean performDexOptTraced(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly) { boolean useProfiles, boolean extractOnly, boolean force) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); try { return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly); return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly, force); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } private boolean performDexOptInternal(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly) { boolean useProfiles, boolean extractOnly, boolean force) { PackageParser.Package p; final String targetInstructionSet; synchronized (mPackages) { Loading @@ -6707,7 +6709,7 @@ public class PackageManagerService extends IPackageManager.Stub { targetInstructionSet = instructionSet != null ? instructionSet : getPrimaryInstructionSet(p.applicationInfo); if (!useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) { if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) { // Skip only if we do not use profiles since they might trigger a recompilation. return false; } Loading @@ -6717,7 +6719,7 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mInstallLock) { final String[] instructionSets = new String[] { targetInstructionSet }; int result = mPackageDexOptimizer.performDexOpt(p, instructionSets, true /* inclDependencies */, useProfiles, extractOnly); true /* inclDependencies */, useProfiles, extractOnly, force); return result == PackageDexOptimizer.DEX_OPT_PERFORMED; } } finally { Loading Loading @@ -6763,7 +6765,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Don't use profiles since that may cause compilation to be skipped. final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets, true /* inclDependencies */, false /* useProfiles */, false /* extractOnly */); false /* extractOnly */, true /* force */); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) { Loading Loading @@ -13031,7 +13033,7 @@ public class PackageManagerService extends IPackageManager.Stub { // method because `pkg` is not in `mPackages` yet. int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */, false /* inclDependencies */, false /* useProfiles */, true /* extractOnly */); true /* extractOnly */, false /* force */); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (result == PackageDexOptimizer.DEX_OPT_FAILED) { String msg = "Extracking package failed for " + pkgName; services/core/java/com/android/server/pm/PackageManagerShellCommand.java +70 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.os.Build; import android.os.Bundle; import android.os.RemoteException; import android.os.ShellCommand; import android.os.SystemProperties; import android.os.UserHandle; import android.text.TextUtils; import android.util.PrintWriterPrinter; Loading Loading @@ -96,6 +97,8 @@ class PackageManagerShellCommand extends ShellCommand { return runInstallCreate(); case "install-write": return runInstallWrite(); case "compile": return runCompile(); case "list": return runList(); case "uninstall": Loading Loading @@ -227,6 +230,67 @@ class PackageManagerShellCommand extends ShellCommand { return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); } private int runCompile() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); boolean useJitProfiles = false; boolean extractOnly = false; boolean forceCompilation = false; String compilationMode = "default"; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-m": compilationMode = getNextArgRequired(); break; case "-f": forceCompilation = true; break; default: pw.println("Error: Unknown option: " + opt); return 1; } } switch (compilationMode) { case "default": useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); extractOnly = false; break; case "all": useJitProfiles = false; extractOnly = false; break; case "profile": useJitProfiles = true; extractOnly = false; break; case "extract": useJitProfiles = false; extractOnly = true; break; default: pw.println("Error: Unknown compilation mode: " + compilationMode); return 1; } String packageName = getNextArg(); if (packageName == null) { pw.println("Error: package name not specified"); return 1; } boolean success = mInterface.performDexOpt(packageName, null /* instructionSet */, useJitProfiles, extractOnly, forceCompilation); if (success) { pw.println("Success"); return 0; } else { pw.println("Failure: package " + packageName + " could not be compiled"); return 1; } } private int runList() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final String type = getNextArg(); Loading Loading @@ -1069,6 +1133,12 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" help"); pw.println(" Print this help text."); pw.println(""); pw.println(" compile [-m MODE] [-f] TARGET-PACKAGE"); pw.println(" Trigger compilation of TARGET-PACKAGE."); pw.println(" Options:"); pw.println(" -m: select compilation mode"); pw.println(" MODE can be one of \"default\", \"all\", \"profile\", and \"extract\""); pw.println(" -f: force compilation even if not needed"); pw.println(" list features"); pw.println(" Prints all features of the system."); pw.println(" list instrumentation [-f] [TARGET-PACKAGE]"); Loading Loading
core/java/android/content/pm/IPackageManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -452,6 +452,9 @@ interface IPackageManager { */ boolean performDexOptIfNeeded(String packageName, String instructionSet); boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly, boolean force); void forceDexOpt(String packageName); /** Loading
services/core/java/com/android/server/pm/BackgroundDexOptService.java +1 −1 Original line number Diff line number Diff line Loading @@ -94,7 +94,7 @@ public class BackgroundDexOptService extends JobService { continue; } if (!pm.performDexOpt(pkg, /* instruction set */ null, useJitProfiles, /* extractOnly */ false)) { /* extractOnly */ false, /* force */ false)) { // there was a problem running dexopt, // remember this so we do not keep retrying. sFailedPackageNames.add(pkg); Loading
services/core/java/com/android/server/pm/PackageDexOptimizer.java +24 −20 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ final class PackageDexOptimizer { * {@link PackageManagerService#mInstallLock}. */ int performDexOpt(PackageParser.Package pkg, String[] instructionSets, boolean inclDependencies, boolean useProfiles, boolean extractOnly) { boolean inclDependencies, boolean useProfiles, boolean extractOnly, boolean force) { ArraySet<String> done; if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) { done = new ArraySet<String>(); Loading @@ -97,7 +97,7 @@ final class PackageDexOptimizer { } try { return performDexOptLI(pkg, instructionSets, done, useProfiles, extractOnly); extractOnly, force); } finally { if (useLock) { mDexoptWakeLock.release(); Loading @@ -107,7 +107,7 @@ final class PackageDexOptimizer { } private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets, ArraySet<String> done, boolean useProfiles, boolean extractOnly) { ArraySet<String> done, boolean useProfiles, boolean extractOnly, boolean force) { final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); Loading @@ -128,17 +128,26 @@ final class PackageDexOptimizer { final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0; final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (useProfiles) { // If we do a profile guided compilation then we might recompile // the same package if more profile information is available. force = true; } final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); boolean performedDexOpt = false; final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); for (String dexCodeInstructionSet : dexCodeInstructionSets) { if (!useProfiles && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { // Skip only if we do not use profiles since they might trigger a recompilation. if (!force && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { continue; } for (String path : paths) { int dexoptNeeded; if (force) { dexoptNeeded = DexFile.DEX2OAT_NEEDED; } else { try { dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName, dexCodeInstructionSet, /* defer */false); Loading @@ -146,17 +155,12 @@ final class PackageDexOptimizer { Slog.w(TAG, "IOException reading apk: " + path, ioe); return DEX_OPT_FAILED; } } if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) { if (useProfiles) { // If we do a profile guided compilation then we might recompile the same // package if more profile information is available. dexoptNeeded = DexFile.DEX2OAT_NEEDED; } else { // No dexopt needed and we don't use profiles. Nothing to do. continue; } } final String dexoptType; String oatDir = null; if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) { Loading Loading @@ -252,7 +256,7 @@ final class PackageDexOptimizer { // TODO: Analyze and investigate if we (should) profile libraries. // Currently this will do a full compilation of the library. performDexOptLI(libPkg, instructionSets, done, /*useProfiles*/ false, /* extractOnly */ false); /* extractOnly */ false, /* force */ false); } } } Loading
services/core/java/com/android/server/pm/PackageManagerService.java +13 −11 Original line number Diff line number Diff line Loading @@ -6639,7 +6639,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkgs != null) { for (String pkg : pkgs) { performDexOpt(pkg, null /* instructionSet */, false /* useProfiles */, true /* extractOnly */); true /* extractOnly */, false /* force */); } } } Loading Loading @@ -6676,26 +6676,28 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean performDexOptIfNeeded(String packageName, String instructionSet) { return performDexOptTraced(packageName, instructionSet, false /* useProfiles */, false /* extractOnly */); false /* extractOnly */, false /* force */); } @Override public boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly) { return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly); boolean extractOnly, boolean force) { return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly, force); } private boolean performDexOptTraced(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly) { boolean useProfiles, boolean extractOnly, boolean force) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); try { return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly); return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly, force); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } private boolean performDexOptInternal(String packageName, String instructionSet, boolean useProfiles, boolean extractOnly) { boolean useProfiles, boolean extractOnly, boolean force) { PackageParser.Package p; final String targetInstructionSet; synchronized (mPackages) { Loading @@ -6707,7 +6709,7 @@ public class PackageManagerService extends IPackageManager.Stub { targetInstructionSet = instructionSet != null ? instructionSet : getPrimaryInstructionSet(p.applicationInfo); if (!useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) { if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) { // Skip only if we do not use profiles since they might trigger a recompilation. return false; } Loading @@ -6717,7 +6719,7 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mInstallLock) { final String[] instructionSets = new String[] { targetInstructionSet }; int result = mPackageDexOptimizer.performDexOpt(p, instructionSets, true /* inclDependencies */, useProfiles, extractOnly); true /* inclDependencies */, useProfiles, extractOnly, force); return result == PackageDexOptimizer.DEX_OPT_PERFORMED; } } finally { Loading Loading @@ -6763,7 +6765,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Don't use profiles since that may cause compilation to be skipped. final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets, true /* inclDependencies */, false /* useProfiles */, false /* extractOnly */); false /* extractOnly */, true /* force */); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) { Loading Loading @@ -13031,7 +13033,7 @@ public class PackageManagerService extends IPackageManager.Stub { // method because `pkg` is not in `mPackages` yet. int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */, false /* inclDependencies */, false /* useProfiles */, true /* extractOnly */); true /* extractOnly */, false /* force */); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (result == PackageDexOptimizer.DEX_OPT_FAILED) { String msg = "Extracking package failed for " + pkgName;
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +70 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.os.Build; import android.os.Bundle; import android.os.RemoteException; import android.os.ShellCommand; import android.os.SystemProperties; import android.os.UserHandle; import android.text.TextUtils; import android.util.PrintWriterPrinter; Loading Loading @@ -96,6 +97,8 @@ class PackageManagerShellCommand extends ShellCommand { return runInstallCreate(); case "install-write": return runInstallWrite(); case "compile": return runCompile(); case "list": return runList(); case "uninstall": Loading Loading @@ -227,6 +230,67 @@ class PackageManagerShellCommand extends ShellCommand { return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); } private int runCompile() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); boolean useJitProfiles = false; boolean extractOnly = false; boolean forceCompilation = false; String compilationMode = "default"; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-m": compilationMode = getNextArgRequired(); break; case "-f": forceCompilation = true; break; default: pw.println("Error: Unknown option: " + opt); return 1; } } switch (compilationMode) { case "default": useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); extractOnly = false; break; case "all": useJitProfiles = false; extractOnly = false; break; case "profile": useJitProfiles = true; extractOnly = false; break; case "extract": useJitProfiles = false; extractOnly = true; break; default: pw.println("Error: Unknown compilation mode: " + compilationMode); return 1; } String packageName = getNextArg(); if (packageName == null) { pw.println("Error: package name not specified"); return 1; } boolean success = mInterface.performDexOpt(packageName, null /* instructionSet */, useJitProfiles, extractOnly, forceCompilation); if (success) { pw.println("Success"); return 0; } else { pw.println("Failure: package " + packageName + " could not be compiled"); return 1; } } private int runList() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final String type = getNextArg(); Loading Loading @@ -1069,6 +1133,12 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" help"); pw.println(" Print this help text."); pw.println(""); pw.println(" compile [-m MODE] [-f] TARGET-PACKAGE"); pw.println(" Trigger compilation of TARGET-PACKAGE."); pw.println(" Options:"); pw.println(" -m: select compilation mode"); pw.println(" MODE can be one of \"default\", \"all\", \"profile\", and \"extract\""); pw.println(" -f: force compilation even if not needed"); pw.println(" list features"); pw.println(" Prints all features of the system."); pw.println(" list instrumentation [-f] [TARGET-PACKAGE]"); Loading