diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 914e81e64ef69..e5c48ccf5442b 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -336,7 +336,8 @@ public class BackgroundDexOptService extends JobService { int dexoptFlags = DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES | DexoptOptions.DEXOPT_BOOT_COMPLETE | - (downgrade ? DexoptOptions.DEXOPT_DOWNGRADE : 0); + (downgrade ? DexoptOptions.DEXOPT_DOWNGRADE : 0) | + DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB; if (is_for_primary_dex) { int result = pm.performDexOptWithStatus(new DexoptOptions(pkg, PackageManagerService.REASON_BACKGROUND_DEXOPT, diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 371b3ef5f5551..210eb13850353 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -56,6 +56,8 @@ public class Installer extends SystemService { public static final int DEXOPT_STORAGE_CE = 1 << 7; /** Indicates that the dex file passed to dexopt in on DE storage. */ public static final int DEXOPT_STORAGE_DE = 1 << 8; + /** Indicates that dexopt is invoked from the background service. */ + public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9; // NOTE: keep in sync with installd public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index fadc32aa27e36..dfa828df52366 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; import dalvik.system.DexFile; @@ -52,6 +53,7 @@ import static com.android.server.pm.Installer.DEXOPT_SECONDARY_DEX; import static com.android.server.pm.Installer.DEXOPT_FORCE; import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE; import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE; +import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB; import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; @@ -392,26 +394,60 @@ public class PackageDexOptimizer { /** * Dumps the dexopt state of the given package {@code pkg} to the given {@code PrintWriter}. */ - void dumpDexoptState(IndentingPrintWriter pw, PackageParser.Package pkg) { + void dumpDexoptState(IndentingPrintWriter pw, PackageParser.Package pkg, + PackageDexUsage.PackageUseInfo useInfo) { final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); final List paths = pkg.getAllCodePathsExcludingResourceOnly(); - for (String instructionSet : dexCodeInstructionSets) { - pw.println("Instruction Set: " + instructionSet); - pw.increaseIndent(); - for (String path : paths) { - String status = null; - try { - status = DexFile.getDexFileStatus(path, instructionSet); - } catch (IOException ioe) { - status = "[Exception]: " + ioe.getMessage(); - } - pw.println("path: " + path); - pw.println("status: " + status); - } - pw.decreaseIndent(); + for (String path : paths) { + pw.println("path: " + path); + pw.increaseIndent(); + + for (String isa : dexCodeInstructionSets) { + String status = null; + try { + status = DexFile.getDexFileStatus(path, isa); + } catch (IOException ioe) { + status = "[Exception]: " + ioe.getMessage(); + } + pw.println(isa + ": " + status); + } + + if (useInfo.isUsedByOtherApps(path)) { + pw.println("used be other apps: " + useInfo.getLoadingPackages(path)); + } + + Map dexUseInfoMap = useInfo.getDexUseInfoMap(); + + if (!dexUseInfoMap.isEmpty()) { + pw.println("known secondary dex files:"); + pw.increaseIndent(); + for (Map.Entry e : dexUseInfoMap.entrySet()) { + String dex = e.getKey(); + PackageDexUsage.DexUseInfo dexUseInfo = e.getValue(); + pw.println(dex); + pw.increaseIndent(); + for (String isa : dexUseInfo.getLoaderIsas()) { + String status = null; + try { + status = DexFile.getDexFileStatus(path, isa); + } catch (IOException ioe) { + status = "[Exception]: " + ioe.getMessage(); + } + pw.println(isa + ": " + status); + } + + pw.println("class loader context: " + dexUseInfo.getClassLoaderContext()); + if (dexUseInfo.isUsedByOtherApps()) { + pw.println("used be other apps: " + dexUseInfo.getLoadingPackages()); + } + pw.decreaseIndent(); + } + pw.decreaseIndent(); + } + pw.decreaseIndent(); } } @@ -568,6 +604,9 @@ public class PackageDexOptimizer { if ((flags & DEXOPT_STORAGE_DE) == DEXOPT_STORAGE_DE) { flagsList.add("storage_de"); } + if ((flags & DEXOPT_IDLE_BACKGROUND_JOB) == DEXOPT_IDLE_BACKGROUND_JOB) { + flagsList.add("idle_background_job"); + } return String.join(",", flagsList); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 317c73f8a88f7..a8ea4eaee4fd8 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -22555,7 +22555,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); for (PackageParser.Package pkg : packages) { ipw.println("[" + pkg.packageName + "]"); ipw.increaseIndent(); - mPackageDexOptimizer.dumpDexoptState(ipw, pkg); + mPackageDexOptimizer.dumpDexoptState(ipw, pkg, + mDexManager.getPackageUseInfoOrDefault(pkg.packageName)); ipw.decreaseIndent(); } } diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java index 4fa47b5d0165c..0966770d48979 100644 --- a/services/core/java/com/android/server/pm/dex/DexoptOptions.java +++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java @@ -56,6 +56,9 @@ public final class DexoptOptions { // actually shared at runtime. public static final int DEXOPT_AS_SHARED_LIBRARY = 1 << 6; + // When set, indicates that dexopt is invoked from the background service. + public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9; + // The name of package to optimize. private final String mPackageName; @@ -86,7 +89,8 @@ public final class DexoptOptions { DEXOPT_ONLY_SECONDARY_DEX | DEXOPT_ONLY_SHARED_DEX | DEXOPT_DOWNGRADE | - DEXOPT_AS_SHARED_LIBRARY; + DEXOPT_AS_SHARED_LIBRARY | + DEXOPT_IDLE_BACKGROUND_JOB; if ((flags & (~validityMask)) != 0) { throw new IllegalArgumentException("Invalid flags : " + Integer.toHexString(flags)); } @@ -133,6 +137,10 @@ public final class DexoptOptions { return (mFlags & DEXOPT_AS_SHARED_LIBRARY) != 0; } + public boolean isDexoptIdleBackgroundJob() { + return (mFlags & DEXOPT_IDLE_BACKGROUND_JOB) != 0; + } + public String getSplitName() { return mSplitName; } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java index b64716c614186..c2072df75bd88 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java @@ -52,6 +52,7 @@ public class DexoptOptionsTests { assertFalse(opt.isDexoptOnlySharedDex()); assertFalse(opt.isDowngrade()); assertFalse(opt.isForce()); + assertFalse(opt.isDexoptIdleBackgroundJob()); } @Test @@ -63,7 +64,8 @@ public class DexoptOptionsTests { DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | DexoptOptions.DEXOPT_ONLY_SHARED_DEX | DexoptOptions.DEXOPT_DOWNGRADE | - DexoptOptions.DEXOPT_AS_SHARED_LIBRARY; + DexoptOptions.DEXOPT_AS_SHARED_LIBRARY | + DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB; DexoptOptions opt = new DexoptOptions(mPackageName, mCompilerFilter, flags); assertEquals(mPackageName, opt.getPackageName()); @@ -76,6 +78,7 @@ public class DexoptOptionsTests { assertTrue(opt.isDowngrade()); assertTrue(opt.isForce()); assertTrue(opt.isDexoptAsSharedLibrary()); + assertTrue(opt.isDexoptIdleBackgroundJob()); } @Test @@ -137,4 +140,4 @@ public class DexoptOptionsTests { assertTrue(gotException); } -} \ No newline at end of file +}