From 3e308c62708443e24ba44ecac683a7fe4d9a7ac2 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Tue, 11 May 2021 11:21:27 -0700 Subject: [PATCH] Update the use of registerAppInfo Pass additional parameters to ART to assist with better profiling and debuggability. Test: m Bug: 182793486 Bug: 185979271 Change-Id: Iae0beab92194d75f191147578922c760f04470b9 --- core/java/android/app/DexLoadReporter.java | 17 +++++++--- core/java/android/app/LoadedApk.java | 32 +++++++++++-------- .../android/content/pm/dex/ArtManager.java | 10 ++++++ .../com/android/internal/os/ZygoteInit.java | 14 ++++++-- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java index 5bc999240a667..a172c058e0916 100644 --- a/core/java/android/app/DexLoadReporter.java +++ b/core/java/android/app/DexLoadReporter.java @@ -138,23 +138,25 @@ import java.util.Set; // NOTE: Keep this in sync with installd expectations. File dexPathFile = new File(dexPath); File secondaryProfileDir = new File(dexPathFile.getParent(), "oat"); - File secondaryProfile = new File(secondaryProfileDir, dexPathFile.getName() + ".cur.prof"); + File secondaryCurProfile = + new File(secondaryProfileDir, dexPathFile.getName() + ".cur.prof"); + File secondaryRefProfile = new File(secondaryProfileDir, dexPathFile.getName() + ".prof"); // Create the profile if not already there. // Returns true if the file was created, false if the file already exists. // or throws exceptions in case of errors. if (!secondaryProfileDir.exists()) { if (!secondaryProfileDir.mkdir()) { - Slog.e(TAG, "Could not create the profile directory: " + secondaryProfile); + Slog.e(TAG, "Could not create the profile directory: " + secondaryCurProfile); // Do not continue with registration if we could not create the oat dir. return; } } try { - boolean created = secondaryProfile.createNewFile(); + boolean created = secondaryCurProfile.createNewFile(); if (DEBUG && created) { - Slog.i(TAG, "Created profile for secondary dex: " + secondaryProfile); + Slog.i(TAG, "Created profile for secondary dex: " + secondaryCurProfile); } } catch (IOException ex) { Slog.e(TAG, "Failed to create profile for secondary dex " + dexPath @@ -165,7 +167,12 @@ import java.util.Set; // If we got here, the dex paths is a secondary dex and we were able to create the profile. // Register the path to the runtime. - VMRuntime.registerAppInfo(secondaryProfile.getPath(), new String[] { dexPath }); + VMRuntime.registerAppInfo( + ActivityThread.currentPackageName(), + secondaryCurProfile.getPath(), + secondaryRefProfile.getPath(), + new String[] { dexPath }, + VMRuntime.CODE_PATH_TYPE_SECONDARY_DEX); } // A dex file is a secondary dex file if it is in any of the registered app diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index b45f3893db8c1..5d2370db8e88f 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -884,7 +884,7 @@ public final class LoadedApk { if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + librarySearchPath); - boolean needToSetupJitProfiles = false; + boolean registerAppInfoToArt = false; if (mDefaultClassLoader == null) { // Temporarily disable logging of disk reads on the Looper thread // as this is early and necessary. @@ -902,7 +902,7 @@ public final class LoadedApk { setThreadPolicy(oldPolicy); // Setup the class loader paths for profiling. - needToSetupJitProfiles = true; + registerAppInfoToArt = true; } if (!libPaths.isEmpty()) { @@ -919,7 +919,7 @@ public final class LoadedApk { final String add = TextUtils.join(File.pathSeparator, addedPaths); ApplicationLoaders.getDefault().addPath(mDefaultClassLoader, add); // Setup the new code paths for profiling. - needToSetupJitProfiles = true; + registerAppInfoToArt = true; } // Setup jit profile support. @@ -933,8 +933,8 @@ public final class LoadedApk { // loads code from) so we explicitly disallow it there. // // It is not ok to call this in a zygote context where mActivityThread is null. - if (needToSetupJitProfiles && !ActivityThread.isSystem() && mActivityThread != null) { - setupJitProfileSupport(); + if (registerAppInfoToArt && !ActivityThread.isSystem() && mActivityThread != null) { + registerAppInfoToArt(); } // Call AppComponentFactory to select/create the main class loader of this app. @@ -984,12 +984,8 @@ public final class LoadedApk { } } - private void setupJitProfileSupport() { - if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) { - return; - } - - // If we use profiles, setup the dex reporter to notify package manager + private void registerAppInfoToArt() { + // Setup the dex reporter to notify package manager // of any relevant dex loads. The idle maintenance job will use the information // reported to optimize the loaded dex files. // Note that we only need one global reporter per app. @@ -1022,9 +1018,19 @@ public final class LoadedApk { for (int i = codePaths.size() - 1; i >= 0; i--) { String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1]; - String profileFile = ArtManager.getCurrentProfilePath( + String curProfileFile = ArtManager.getCurrentProfilePath( mPackageName, UserHandle.myUserId(), splitName); - VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)}); + String refProfileFile = ArtManager.getReferenceProfilePath( + mPackageName, UserHandle.myUserId(), splitName); + int codePathType = codePaths.get(i).equals(mApplicationInfo.sourceDir) + ? VMRuntime.CODE_PATH_TYPE_PRIMARY_APK + : VMRuntime.CODE_PATH_TYPE_SPLIT_APK; + VMRuntime.registerAppInfo( + mPackageName, + curProfileFile, + refProfileFile, + new String[] {codePaths.get(i)}, + codePathType); } // Register the app data directory with the reporter. It will diff --git a/core/java/android/content/pm/dex/ArtManager.java b/core/java/android/content/pm/dex/ArtManager.java index b0970f4878dbf..009ebb9b4b968 100644 --- a/core/java/android/content/pm/dex/ArtManager.java +++ b/core/java/android/content/pm/dex/ArtManager.java @@ -200,6 +200,16 @@ public class ArtManager { return new File(profileDir, getProfileName(splitName)).getAbsolutePath(); } + /** + * Return the path to the current profile corresponding to given package and split. + * + * @hide + */ + public static String getReferenceProfilePath(String packageName, int userId, String splitName) { + File profileDir = Environment.getDataRefProfilesDePackageDirectory(packageName); + return new File(profileDir, getProfileName(splitName)).getAbsolutePath(); + } + /** * Return the snapshot profile file for the given package and profile name. * diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index a541089577750..a9e8fbce91872 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -586,10 +586,18 @@ public class ZygoteInit { codePaths[0], /*dexMetadata*/ null); - File profileDir = Environment.getDataProfilesDePackageDirectory( + File curProfileDir = Environment.getDataProfilesDePackageDirectory( UserHandle.USER_SYSTEM, systemServerPackageName); - String profilePath = new File(profileDir, systemServerProfileName).getAbsolutePath(); - VMRuntime.registerAppInfo(profilePath, codePaths); + String curProfilePath = new File(curProfileDir, systemServerProfileName).getAbsolutePath(); + File refProfileDir = Environment.getDataProfilesDePackageDirectory( + UserHandle.USER_SYSTEM, systemServerPackageName); + String refProfilePath = new File(refProfileDir, systemServerProfileName).getAbsolutePath(); + VMRuntime.registerAppInfo( + systemServerPackageName, + curProfilePath, + refProfilePath, + codePaths, + VMRuntime.CODE_PATH_TYPE_PRIMARY_APK); } /**