From f138c7b6b68b2c3e53b69c1837e2954b1909fb1a Mon Sep 17 00:00:00 2001 From: Martin Stjernholm Date: Fri, 28 Oct 2022 01:48:42 +0100 Subject: [PATCH] Call through to ART Service in notifyDexLoad if it is enabled. Move the ArtManagerLocal initialization to a place where it can access PackageManagerLocal but still is early enough to precede binder calls to notifyDexLoad. Test: Build with dalvik.vm.useartservice=true, boot, launch an app, and check with temporary logging that ArtManagerLocal.notifyDexContainersLoaded gets called. Bug: 254043366 Change-Id: I97d59f9c15402648627006dde874a068b0706157 --- .../com/android/server/pm/DexOptHelper.java | 19 ++++- .../server/pm/PackageManagerService.java | 74 ++++++++++++++++--- .../java/com/android/server/SystemServer.java | 9 ++- 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index 0066592de8c4a..5661399c2ed7c 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -62,6 +62,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.server.LocalManagerRegistry; import com.android.server.art.ArtManagerLocal; +import com.android.server.art.DexUseManagerLocal; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.OptimizeParams; import com.android.server.art.model.OptimizeResult; @@ -932,9 +933,23 @@ public final class DexOptHelper { } /** - * Returns {@link ArtManagerLocal} if one is found and should be used for package optimization. + * Returns {@link DexUseManagerLocal} if ART Service should be used for package optimization. */ - private @Nullable ArtManagerLocal getArtManagerLocal() { + public static @Nullable DexUseManagerLocal getDexUseManagerLocal() { + if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { + return null; + } + try { + return LocalManagerRegistry.getManagerOrThrow(DexUseManagerLocal.class); + } catch (ManagerNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns {@link ArtManagerLocal} if ART Service should be used for package optimization. + */ + private static @Nullable ArtManagerLocal getArtManagerLocal() { if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { return null; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 91f7011c90c71..4b7cefac8d12d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -193,6 +193,7 @@ import com.android.server.ServiceThread; import com.android.server.SystemConfig; import com.android.server.Watchdog; import com.android.server.apphibernation.AppHibernationManagerInternal; +import com.android.server.art.DexUseManagerLocal; import com.android.server.compat.CompatChange; import com.android.server.compat.PlatformCompat; import com.android.server.pm.Installer.InstallerException; @@ -212,6 +213,7 @@ import com.android.server.pm.permission.LegacyPermissionManagerService; import com.android.server.pm.permission.PermissionManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.pm.pkg.AndroidPackage; +import com.android.server.pm.pkg.PackageState; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; @@ -5308,18 +5310,70 @@ public class PackageManagerService implements PackageSender, TestUtilityService return; } - // TODO(b/254043366): Call `ArtManagerLocal.notifyDexLoad`. + UserHandle user = Binder.getCallingUserHandle(); + int userId = user.getIdentifier(); - int userId = UserHandle.getCallingUserId(); - ApplicationInfo ai = - snapshot.getApplicationInfo(loadingPackageName, /*flags*/ 0, userId); - if (ai == null) { - Slog.w(PackageManagerService.TAG, "Loading a package that does not exist for the calling user. package=" - + loadingPackageName + ", user=" + userId); - return; + // Proxy the call to either ART Service or the legacy implementation. If the + // implementation is switched with the system property, the dex usage info will be + // incomplete, with these effects: + // + // - Shared dex files may temporarily get compiled for private use. + // - Secondary dex files may not get compiled at all. + // - Stale compiled artifacts for secondary dex files may not get cleaned up. + // + // This recovers in the first background dexopt after the depending apps have been + // loaded for the first time. + + DexUseManagerLocal dexUseManager = DexOptHelper.getDexUseManagerLocal(); + if (dexUseManager != null) { + // TODO(chiuwinson): Retrieve filtered snapshot from Computer instance instead. + try (PackageManagerLocal.FilteredSnapshot filteredSnapshot = + LocalManagerRegistry.getManager(PackageManagerLocal.class) + .withFilteredSnapshot(callingUid, user)) { + if (loaderIsa != null) { + // Check that loaderIsa agrees with the ISA that dexUseManager will + // determine. + PackageState loadingPkgState = + filteredSnapshot.getPackageState(loadingPackageName); + // If we don't find the loading package just pass it through and let + // dexUseManager throw on it. + if (loadingPkgState != null) { + String loadingPkgAbi = loadingPkgState.getPrimaryCpuAbi(); + if (loadingPkgAbi == null) { + loadingPkgAbi = Build.SUPPORTED_ABIS[0]; + } + String loadingPkgDexCodeIsa = InstructionSets.getDexCodeInstructionSet( + VMRuntime.getInstructionSet(loadingPkgAbi)); + if (!loaderIsa.equals(loadingPkgDexCodeIsa)) { + // TODO(b/251903639): Make this crash to surface this problem + // better. + Slog.w(PackageManagerService.TAG, + "Invalid loaderIsa in notifyDexLoad call from " + + loadingPackageName + ", uid " + callingUid + + ": expected " + loadingPkgDexCodeIsa + ", got " + + loaderIsa); + return; + } + } + } + + // This is called from binder, so exceptions thrown here are caught and handled + // by it. + dexUseManager.notifyDexContainersLoaded( + filteredSnapshot, loadingPackageName, classLoaderContextMap); + } + } else { + ApplicationInfo ai = + snapshot.getApplicationInfo(loadingPackageName, /*flags*/ 0, userId); + if (ai == null) { + Slog.w(PackageManagerService.TAG, + "Loading a package that does not exist for the calling user. package=" + + loadingPackageName + ", user=" + userId); + return; + } + mDexManager.notifyDexLoad(ai, classLoaderContextMap, loaderIsa, userId, + Process.isIsolated(callingUid)); } - mDexManager.notifyDexLoad(ai, classLoaderContextMap, loaderIsa, userId, - Process.isIsolated(callingUid)); } @Override diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index e41e781b7c222..9632fea4532ed 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -109,6 +109,7 @@ import com.android.server.ambientcontext.AmbientContextManagerService; import com.android.server.appbinding.AppBindingService; import com.android.server.art.ArtManagerLocal; import com.android.server.art.ArtModuleServiceInitializer; +import com.android.server.art.DexUseManagerLocal; import com.android.server.attention.AttentionManagerService; import com.android.server.audio.AudioService; import com.android.server.biometrics.AuthService; @@ -1220,6 +1221,13 @@ public final class SystemServer implements Dumpable { Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain"); } + // DexUseManagerLocal needs to be loaded after PackageManagerLocal has been registered, but + // before PackageManagerService starts processing binder calls to notifyDexLoad. + // DexUseManagerLocal may also call artd, so ensure ArtModuleServiceManager is instantiated. + ArtModuleServiceInitializer.setArtModuleServiceManager(new ArtModuleServiceManager()); + LocalManagerRegistry.addManager( + DexUseManagerLocal.class, DexUseManagerLocal.createInstance()); + mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); t.traceEnd(); @@ -2723,7 +2731,6 @@ public final class SystemServer implements Dumpable { t.traceEnd(); t.traceBegin("ArtManagerLocal"); - ArtModuleServiceInitializer.setArtModuleServiceManager(new ArtModuleServiceManager()); LocalManagerRegistry.addManager(ArtManagerLocal.class, new ArtManagerLocal(context)); t.traceEnd();