From 6ae39fc2e5b4692d092a042816939fd0a5f3e3b8 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Fri, 19 Jan 2018 20:32:47 -0800 Subject: [framework] Extend profile operations to take the profile name Extend the installd profile interface to take the profile name as argument. This shifts the responsibility for choosing the names of profiles for primary apks completely to PackageManager. Each of the application code paths will get an unique profile name based on their split name. All the profile operations will now work on a specific profile name rather than assuming a default global name. Also, move dumpProfiles and clearProfiles functionality to the ArtManagerService so that we can re-use profileName computations easier. Test: manual (dexopt apps, merge profiles, clear profiles) gts GtsAndroidRuntimeManagerHostTestCases Bug: 30934496 Change-Id: Ie65d45eed7de0844edf4b7af918d7eaa74ec1f2c --- core/java/android/app/LoadedApk.java | 23 ++++---- core/java/android/content/pm/dex/ArtManager.java | 28 ++++++++++ core/java/android/os/Environment.java | 5 +- core/java/com/android/internal/os/ZygoteInit.java | 2 +- .../core/java/com/android/server/pm/Installer.java | 33 ++++++------ .../com/android/server/pm/OtaDexoptService.java | 7 +-- .../com/android/server/pm/PackageDexOptimizer.java | 20 ++++--- .../android/server/pm/PackageManagerService.java | 33 ++++-------- .../android/server/pm/dex/ArtManagerService.java | 63 +++++++++++++++++----- 9 files changed, 135 insertions(+), 79 deletions(-) diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 26f498087786..d24d4f341aea 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -28,6 +28,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.dex.ArtManager; import android.content.pm.split.SplitDependencyLoader; import android.content.res.AssetManager; import android.content.res.CompatibilityInfo; @@ -35,7 +36,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; import android.os.Bundle; -import android.os.Environment; import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; @@ -49,13 +49,15 @@ import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.Log; -import android.util.LogPrinter; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayAdjustments; + import com.android.internal.util.ArrayUtils; + import dalvik.system.VMRuntime; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -749,13 +751,6 @@ public final class LoadedApk { } } - // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp). - private static File getPrimaryProfileFile(String packageName) { - File profileDir = Environment.getDataProfilesDePackageDirectory( - UserHandle.myUserId(), packageName); - return new File(profileDir, "primary.prof"); - } - private void setupJitProfileSupport() { if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) { return; @@ -783,10 +778,12 @@ public final class LoadedApk { return; } - final File profileFile = getPrimaryProfileFile(mPackageName); - - VMRuntime.registerAppInfo(profileFile.getPath(), - codePaths.toArray(new String[codePaths.size()])); + for (int i = codePaths.size() - 1; i >= 0; i--) { + String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1]; + String profileFile = ArtManager.getCurrentProfilePath( + mPackageName, UserHandle.myUserId(), splitName); + VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)}); + } // Register the app data directory with the reporter. It will // help deciding whether or not a dex file is the primary apk or a diff --git a/core/java/android/content/pm/dex/ArtManager.java b/core/java/android/content/pm/dex/ArtManager.java index aa9c46e6a52d..f979576e5315 100644 --- a/core/java/android/content/pm/dex/ArtManager.java +++ b/core/java/android/content/pm/dex/ArtManager.java @@ -19,6 +19,7 @@ package android.content.pm.dex; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -26,6 +27,8 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Slog; +import java.io.File; + /** * Class for retrieving various kinds of information related to the runtime artifacts of * packages that are currently installed on the device. @@ -163,4 +166,29 @@ public class ArtManager { public static String getProfileName(String splitName) { return splitName == null ? "primary.prof" : splitName + ".split.prof"; } + + /** + * Return the path to the current profile corresponding to given package and split. + * + * @hide + */ + public static String getCurrentProfilePath(String packageName, int userId, String splitName) { + File profileDir = Environment.getDataProfilesDePackageDirectory(userId, packageName); + return new File(profileDir, getProfileName(splitName)).getAbsolutePath(); + } + + /** + * Return the snapshot profile file for the given package and split. + * + * KEEP in sync with installd dexopt.cpp. + * TODO(calin): inject the snapshot profile name from PM to avoid the dependency. + * + * @hide + */ + public static File getProfileSnapshotFile(String packageName, String splitName) { + File profileDir = Environment.getDataRefProfilesDePackageDirectory(packageName); + String snapshotFile = getProfileName(splitName) + ".snapshot"; + return new File(profileDir, snapshotFile); + + } } diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 62731e84a401..158041dd91e7 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -302,9 +302,8 @@ public class Environment { } /** {@hide} */ - public static File getProfileSnapshotPath(String packageName, String codePath) { - return buildPath(buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName, - "primary.prof.snapshot")); + public static File getDataRefProfilesDePackageDirectory(String packageName) { + return buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName); } /** {@hide} */ diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 56594705082a..39279b5055b1 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -583,7 +583,7 @@ public class ZygoteInit { installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, uuid, classLoaderContext, seInfo, false /* downgrade */, - targetSdkVersion); + targetSdkVersion, /*profileName*/ null); } catch (RemoteException | ServiceSpecificException e) { // Ignore (but log), we need this on the classpath for fallback mode. Log.w(TAG, "Failed compiling classpath element for system server: " diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index cdc79c7741e1..2e9ab0bf35cc 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -286,43 +286,44 @@ public class Installer extends SystemService { public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries, - @Nullable String seInfo, boolean downgrade, int targetSdkVersion) - throws InstallerException { + @Nullable String seInfo, boolean downgrade, int targetSdkVersion, + @Nullable String profileName) throws InstallerException { assertValidInstructionSet(instructionSet); if (!checkBeforeRemote()) return; try { mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade, - targetSdkVersion); + targetSdkVersion, profileName); } catch (Exception e) { throw InstallerException.from(e); } } - public boolean mergeProfiles(int uid, String packageName) throws InstallerException { + public boolean mergeProfiles(int uid, String packageName, String profileName) + throws InstallerException { if (!checkBeforeRemote()) return false; try { - return mInstalld.mergeProfiles(uid, packageName); + return mInstalld.mergeProfiles(uid, packageName, profileName); } catch (Exception e) { throw InstallerException.from(e); } } - public boolean dumpProfiles(int uid, String packageName, String codePaths) + public boolean dumpProfiles(int uid, String packageName, String profileName, String codePath) throws InstallerException { if (!checkBeforeRemote()) return false; try { - return mInstalld.dumpProfiles(uid, packageName, codePaths); + return mInstalld.dumpProfiles(uid, packageName, profileName, codePath); } catch (Exception e) { throw InstallerException.from(e); } } - public boolean copySystemProfile(String systemProfile, int uid, String packageName) - throws InstallerException { + public boolean copySystemProfile(String systemProfile, int uid, String packageName, + String profileName) throws InstallerException { if (!checkBeforeRemote()) return false; try { - return mInstalld.copySystemProfile(systemProfile, uid, packageName); + return mInstalld.copySystemProfile(systemProfile, uid, packageName, profileName); } catch (Exception e) { throw InstallerException.from(e); } @@ -366,10 +367,10 @@ public class Installer extends SystemService { } } - public void clearAppProfiles(String packageName) throws InstallerException { + public void clearAppProfiles(String packageName, String profileName) throws InstallerException { if (!checkBeforeRemote()) return; try { - mInstalld.clearAppProfiles(packageName); + mInstalld.clearAppProfiles(packageName, profileName); } catch (Exception e) { throw InstallerException.from(e); } @@ -502,21 +503,21 @@ public class Installer extends SystemService { } } - public boolean createProfileSnapshot(int appId, String packageName, String codePath) + public boolean createProfileSnapshot(int appId, String packageName, String profileName) throws InstallerException { if (!checkBeforeRemote()) return false; try { - return mInstalld.createProfileSnapshot(appId, packageName, codePath); + return mInstalld.createProfileSnapshot(appId, packageName, profileName); } catch (Exception e) { throw InstallerException.from(e); } } - public void destroyProfileSnapshot(String packageName, String codePath) + public void destroyProfileSnapshot(String packageName, String profileName) throws InstallerException { if (!checkBeforeRemote()) return; try { - mInstalld.destroyProfileSnapshot(packageName, codePath); + mInstalld.destroyProfileSnapshot(packageName, profileName); } catch (Exception e) { throw InstallerException.from(e); } diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 03950119ea13..5bf38dc21305 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -261,12 +261,12 @@ public class OtaDexoptService extends IOtaDexopt.Stub { String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade, - int targetSdkVersion) + int targetSdkVersion, @Nullable String profileName) throws InstallerException { final StringBuilder builder = new StringBuilder(); - // The version. Right now it's 4. - builder.append("4 "); + // The version. Right now it's 5. + builder.append("5 "); builder.append("dexopt"); @@ -283,6 +283,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { encodeParameter(builder, seInfo); encodeParameter(builder, downgrade); encodeParameter(builder, targetSdkVersion); + encodeParameter(builder, profileName); commands.add(builder.toString()); } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 6a08e1b5953a..8c18511eff7d 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageParser; +import android.content.pm.dex.ArtManager; import android.os.FileUtils; import android.os.PowerManager; import android.os.SystemClock; @@ -211,12 +212,14 @@ public class PackageDexOptimizer { } } + String profileName = ArtManager.getProfileName(i == 0 ? null : pkg.splitNames[i - 1]); + final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, options.getCompilerFilter(), isUsedByOtherApps); final boolean profileUpdated = options.isCheckForProfileUpdates() && - isProfileUpdated(pkg, sharedGid, compilerFilter); + isProfileUpdated(pkg, sharedGid, profileName, compilerFilter); // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct // flags. @@ -225,7 +228,7 @@ public class PackageDexOptimizer { for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter, profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid, - packageStats, options.isDowngrade()); + packageStats, options.isDowngrade(), profileName); // The end result is: // - FAILED if any path failed, // - PERFORMED if at least one path needed compilation, @@ -249,7 +252,8 @@ public class PackageDexOptimizer { @GuardedBy("mInstallLock") private int dexOptPath(PackageParser.Package pkg, String path, String isa, String compilerFilter, boolean profileUpdated, String classLoaderContext, - int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade) { + int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade, + String profileName) { int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext, profileUpdated, downgrade); if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) { @@ -275,7 +279,8 @@ public class PackageDexOptimizer { // primary dex files. mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags, compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo, - false /* downgrade*/, pkg.applicationInfo.targetSdkVersion); + false /* downgrade*/, pkg.applicationInfo.targetSdkVersion, + profileName); if (packageStats != null) { long endTime = System.currentTimeMillis(); @@ -396,7 +401,7 @@ public class PackageDexOptimizer { mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0, /*oatDir*/ null, dexoptFlags, compilerFilter, info.volumeUuid, classLoaderContext, info.seInfoUser, - options.isDowngrade(), info.targetSdkVersion); + options.isDowngrade(), info.targetSdkVersion, /*profileName*/ null); } return DEX_OPT_PERFORMED; @@ -550,14 +555,15 @@ public class PackageDexOptimizer { * current profile and the reference profile will be merged and subsequent calls * may return a different result. */ - private boolean isProfileUpdated(PackageParser.Package pkg, int uid, String compilerFilter) { + private boolean isProfileUpdated(PackageParser.Package pkg, int uid, String profileName, + String compilerFilter) { // Check if we are allowed to merge and if the compiler filter is profile guided. if (!isProfileGuidedCompilerFilter(compilerFilter)) { return false; } // Merge profiles. It returns whether or not there was an updated in the profile info. try { - return mInstaller.mergeProfiles(uid, pkg.packageName); + return mInstaller.mergeProfiles(uid, pkg.packageName, profileName); } catch (InstallerException e) { Slog.w(TAG, "Failed to merge profiles", e); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 299c59a5d093..9fdbdbe7e60e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -195,6 +195,7 @@ import android.content.pm.UserInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.content.pm.VersionedPackage; +import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.IArtManager; import android.content.res.Resources; @@ -8873,7 +8874,8 @@ Slog.e("TODD", // PackageDexOptimizer to prevent this happening on first boot. The issue // is that we don't have a good way to say "do this only once". if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(), - pkg.applicationInfo.uid, pkg.packageName)) { + pkg.applicationInfo.uid, pkg.packageName, + ArtManager.getProfileName(null))) { Log.e(TAG, "Installer failed to copy system profile!"); } else { // Disabled as this causes speed-profile compilation during first boot @@ -8908,7 +8910,8 @@ Slog.e("TODD", // issue is that we don't have a good way to say "do this only // once". if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(), - pkg.applicationInfo.uid, pkg.packageName)) { + pkg.applicationInfo.uid, pkg.packageName, + ArtManager.getProfileName(null))) { Log.e(TAG, "Failed to copy system profile for stub package!"); } else { useProfileForDexopt = true; @@ -9333,14 +9336,7 @@ Slog.e("TODD", synchronized (mInstallLock) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dump profiles"); - final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); - try { - List allCodePaths = pkg.getAllCodePathsExcludingResourceOnly(); - String codePaths = TextUtils.join(";", allCodePaths); - mInstaller.dumpProfiles(sharedGid, packageName, codePaths); - } catch (InstallerException e) { - Slog.w(TAG, "Failed to dump profiles", e); - } + mArtManagerService.dumpProfiles(pkg); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } @@ -9416,6 +9412,8 @@ Slog.e("TODD", for (int i = 0; i < childCount; i++) { clearAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); } + + clearAppProfilesLIF(pkg, UserHandle.USER_ALL); } private void clearAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) { @@ -9488,18 +9486,10 @@ Slog.e("TODD", Slog.wtf(TAG, "Package was null!", new Throwable()); return; } - clearAppProfilesLeafLIF(pkg); + mArtManagerService.clearAppProfiles(pkg); final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; for (int i = 0; i < childCount; i++) { - clearAppProfilesLeafLIF(pkg.childPackages.get(i)); - } - } - - private void clearAppProfilesLeafLIF(PackageParser.Package pkg) { - try { - mInstaller.clearAppProfiles(pkg.packageName); - } catch (InstallerException e) { - Slog.w(TAG, String.valueOf(e)); + mArtManagerService.clearAppProfiles(pkg.childPackages.get(i)); } } @@ -16108,7 +16098,6 @@ Slog.e("TODD", clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); - clearAppProfilesLIF(deletedPackage, UserHandle.USER_ALL); try { final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags, @@ -16247,7 +16236,6 @@ Slog.e("TODD", // Successfully disabled the old package. Now proceed with re-installation clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); - clearAppProfilesLIF(deletedPackage, UserHandle.USER_ALL); res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP, @@ -20283,7 +20271,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); - clearAppProfilesLIF(pkg, UserHandle.USER_ALL); mDexManager.notifyPackageUpdated(pkg.packageName, pkg.baseCodePath, pkg.splitCodePaths); } 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 81786890a436..f15dc2d5f8d3 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -25,7 +25,6 @@ import android.content.pm.PackageParser; import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; import android.os.Binder; -import android.os.Environment; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -111,11 +110,13 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { } boolean pathFound = info.applicationInfo.getBaseCodePath().equals(codePath); + String splitName = null; String[] splitCodePaths = info.applicationInfo.getSplitCodePaths(); if (!pathFound && (splitCodePaths != null)) { - for (String path : splitCodePaths) { - if (path.equals(codePath)) { + for (int i = splitCodePaths.length - 1; i >= 0; i--) { + if (splitCodePaths[i].equals(codePath)) { pathFound = true; + splitName = info.applicationInfo.splitNames[i]; break; } } @@ -126,18 +127,18 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { } // All good, create the profile snapshot. - createProfileSnapshot(packageName, codePath, callback, info); + createProfileSnapshot(packageName, splitName, callback, info); // Destroy the snapshot, we no longer need it. - destroyProfileSnapshot(packageName, codePath); + destroyProfileSnapshot(packageName, splitName); } - private void createProfileSnapshot(String packageName, String codePath, + private void createProfileSnapshot(String packageName, String splitName, ISnapshotRuntimeProfileCallback callback, PackageInfo info) { // Ask the installer to snapshot the profile. synchronized (mInstallLock) { try { if (!mInstaller.createProfileSnapshot(UserHandle.getAppId(info.applicationInfo.uid), - packageName, codePath)) { + packageName, ArtManager.getProfileName(splitName))) { postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); return; } @@ -148,28 +149,30 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { } // Open the snapshot and invoke the callback. - File snapshotProfile = Environment.getProfileSnapshotPath(packageName, codePath); + File snapshotProfile = ArtManager.getProfileSnapshotFile(packageName, splitName); ParcelFileDescriptor fd; try { fd = ParcelFileDescriptor.open(snapshotProfile, ParcelFileDescriptor.MODE_READ_ONLY); postSuccess(packageName, fd, callback); } catch (FileNotFoundException e) { - Slog.w(TAG, "Could not open snapshot profile for " + packageName + ":" + codePath, e); + Slog.w(TAG, "Could not open snapshot profile for " + packageName + ":" + + snapshotProfile, e); postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); } } - private void destroyProfileSnapshot(String packageName, String codePath) { + private void destroyProfileSnapshot(String packageName, String splitName) { if (DEBUG) { - Slog.d(TAG, "Destroying profile snapshot for" + packageName + ":" + codePath); + Slog.d(TAG, "Destroying profile snapshot for" + packageName + ":" + splitName); } synchronized (mInstallLock) { try { - mInstaller.destroyProfileSnapshot(packageName, codePath); + mInstaller.destroyProfileSnapshot(packageName, + ArtManager.getProfileName(splitName)); } catch (InstallerException e) { Slog.e(TAG, "Failed to destroy profile snapshot for " + - packageName + ":" + codePath, e); + packageName + ":" + splitName, e); } } } @@ -283,6 +286,40 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { } } + /** + * Clear the profiles for the given package. + */ + public void clearAppProfiles(PackageParser.Package pkg) { + try { + ArrayMap packageProfileNames = getPackageProfileNames(pkg); + for (int i = packageProfileNames.size() - 1; i >= 0; i--) { + String profileName = packageProfileNames.valueAt(i); + mInstaller.clearAppProfiles(pkg.packageName, profileName); + } + } catch (InstallerException e) { + Slog.w(TAG, String.valueOf(e)); + } + } + + /** + * Dumps the profiles for the given package. + */ + public void dumpProfiles(PackageParser.Package pkg) { + final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + try { + ArrayMap packageProfileNames = getPackageProfileNames(pkg); + for (int i = packageProfileNames.size() - 1; i >= 0; i--) { + String codePath = packageProfileNames.keyAt(i); + String profileName = packageProfileNames.valueAt(i); + synchronized (mInstallLock) { + mInstaller.dumpProfiles(sharedGid, pkg.packageName, profileName, codePath); + } + } + } catch (InstallerException e) { + Slog.w(TAG, "Failed to dump profiles", e); + } + } + /** * Build the profiles names for all the package code paths (excluding resource only paths). * Return the map [code path -> profile name]. -- cgit v1.2.3-59-g8ed1b