Call into ART Service for profile snapshotting when it is enabled.
Test: adb root
adb shell setprop dalvik.vm.profilebootclasspath true
adb shell pm snapshot-profile android
adb shell pm snapshot-profile com.android.egg
adb shell pm snapshot-profile com.android.egg \
--code-path /system/app/EasterEgg/EasterEgg.apk
with dalvik.vm.useartservice=true
Bug: 251903639
Change-Id: Id49c381162e6f73d77e6bb80af54b9cbe5f7d739
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index b4cedfb..d8b6cd5 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -50,11 +50,15 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
+import com.android.server.art.ArtManagerLocal;
+import com.android.server.pm.DexOptHelper;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
+import com.android.server.pm.PackageManagerLocal;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.PackageManagerServiceCompilerMapping;
+import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
@@ -210,20 +214,15 @@
Slog.d(TAG, "Requested snapshot for " + packageName + ":" + codePath);
}
- // TODO(b/251903639): Call into ART Service.
- try {
- if (bootImageProfile) {
- snapshotBootImageProfile(callback);
- } else {
- snapshotAppProfile(packageName, codePath, callback);
- }
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ if (bootImageProfile) {
+ snapshotBootImageProfile(callback);
+ } else {
+ snapshotAppProfile(packageName, codePath, callback);
}
}
- private void snapshotAppProfile(String packageName, String codePath,
- ISnapshotRuntimeProfileCallback callback) throws LegacyDexoptDisabledException {
+ private void snapshotAppProfile(
+ String packageName, String codePath, ISnapshotRuntimeProfileCallback callback) {
PackageInfo info = null;
try {
// Note that we use the default user 0 to retrieve the package info.
@@ -260,17 +259,45 @@
}
// All good, create the profile snapshot.
- int appId = UserHandle.getAppId(info.applicationInfo.uid);
- if (appId < 0) {
- postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
- Slog.wtf(TAG, "AppId is -1 for package: " + packageName);
- return;
- }
+ if (DexOptHelper.useArtService()) {
+ ParcelFileDescriptor fd;
- createProfileSnapshot(packageName, ArtManager.getProfileName(splitName), codePath,
- appId, callback);
- // Destroy the snapshot, we no longer need it.
- destroyProfileSnapshot(packageName, ArtManager.getProfileName(splitName));
+ try (PackageManagerLocal.FilteredSnapshot snapshot =
+ PackageManagerServiceUtils.getPackageManagerLocal()
+ .withFilteredSnapshot()) {
+ fd = DexOptHelper.getArtManagerLocal().snapshotAppProfile(
+ snapshot, packageName, splitName);
+ } catch (IllegalArgumentException e) {
+ // ArtManagerLocal.snapshotAppProfile couldn't find the package or split. Since
+ // we've checked them above this can only happen due to race, i.e. the package got
+ // removed. So let's report it as SNAPSHOT_FAILED_PACKAGE_NOT_FOUND even if it was
+ // for the split.
+ // TODO(mast): Reuse the same snapshot to avoid this race.
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_PACKAGE_NOT_FOUND);
+ return;
+ } catch (IllegalStateException | ArtManagerLocal.SnapshotProfileException e) {
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ return;
+ }
+
+ postSuccess(packageName, fd, callback);
+ } else {
+ int appId = UserHandle.getAppId(info.applicationInfo.uid);
+ if (appId < 0) {
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ Slog.wtf(TAG, "AppId is -1 for package: " + packageName);
+ return;
+ }
+
+ try {
+ createProfileSnapshot(packageName, ArtManager.getProfileName(splitName), codePath,
+ appId, callback);
+ // Destroy the snapshot, we no longer need it.
+ destroyProfileSnapshot(packageName, ArtManager.getProfileName(splitName));
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
private void createProfileSnapshot(String packageName, String profileName, String classpath,
@@ -340,23 +367,43 @@
}
}
- private void snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback)
- throws LegacyDexoptDisabledException {
- // Combine the profiles for boot classpath and system server classpath.
- // This avoids having yet another type of profiles and simplifies the processing.
- String classpath = String.join(":", Os.getenv("BOOTCLASSPATH"),
- Os.getenv("SYSTEMSERVERCLASSPATH"));
+ private void snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback) {
+ if (DexOptHelper.useArtService()) {
+ ParcelFileDescriptor fd;
- final String standaloneSystemServerJars = Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
- if (standaloneSystemServerJars != null) {
- classpath = String.join(":", classpath, standaloneSystemServerJars);
+ try (PackageManagerLocal.FilteredSnapshot snapshot =
+ PackageManagerServiceUtils.getPackageManagerLocal()
+ .withFilteredSnapshot()) {
+ fd = DexOptHelper.getArtManagerLocal().snapshotBootImageProfile(snapshot);
+ } catch (IllegalStateException | ArtManagerLocal.SnapshotProfileException e) {
+ postError(callback, BOOT_IMAGE_ANDROID_PACKAGE,
+ ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ return;
+ }
+
+ postSuccess(BOOT_IMAGE_ANDROID_PACKAGE, fd, callback);
+ } else {
+ // Combine the profiles for boot classpath and system server classpath.
+ // This avoids having yet another type of profiles and simplifies the processing.
+ String classpath = String.join(
+ ":", Os.getenv("BOOTCLASSPATH"), Os.getenv("SYSTEMSERVERCLASSPATH"));
+
+ final String standaloneSystemServerJars = Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
+ if (standaloneSystemServerJars != null) {
+ classpath = String.join(":", classpath, standaloneSystemServerJars);
+ }
+
+ try {
+ // Create the snapshot.
+ createProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME,
+ classpath,
+ /*appId*/ -1, callback);
+ // Destroy the snapshot, we no longer need it.
+ destroyProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
}
-
- // Create the snapshot.
- createProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME, classpath,
- /*appId*/ -1, callback);
- // Destroy the snapshot, we no longer need it.
- destroyProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME);
}
/**