Loading services/core/java/com/android/server/pm/Installer.java +14 −0 Original line number Diff line number Diff line Loading @@ -692,6 +692,20 @@ public class Installer extends SystemService { } } /** * Deletes the reference profile with the given name of the given package. * @throws InstallerException if the deletion fails. */ public void deleteReferenceProfile(String packageName, String profileName) throws InstallerException { if (!checkBeforeRemote()) return; try { mInstalld.deleteReferenceProfile(packageName, profileName); } catch (Exception e) { throw InstallerException.from(e); } } public void createUserData(String uuid, int userId, int userSerial, int flags) throws InstallerException { if (!checkBeforeRemote()) return; Loading services/core/java/com/android/server/pm/PackageDexOptimizer.java +92 −67 Original line number Diff line number Diff line Loading @@ -324,12 +324,12 @@ public class PackageDexOptimizer { String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter()); // If the app is used by other apps, we must not use the existing profile because it // may contain user data, unless the profile is newly created on install. final boolean resetProfile = isProfileGuidedCompilerFilter(compilerFilter) final boolean useCloudProfile = isProfileGuidedCompilerFilter(compilerFilter) && isUsedByOtherApps && options.getCompilationReason() != PackageManagerService.REASON_INSTALL; String dexMetadataPath = null; if (options.isDexoptInstallWithDexMetadata() || resetProfile) { if (options.isDexoptInstallWithDexMetadata() || useCloudProfile) { File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(new File(path)); dexMetadataPath = dexMetadataFile == null ? null : dexMetadataFile.getAbsolutePath(); Loading @@ -339,22 +339,35 @@ public class PackageDexOptimizer { // PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to // profiles. int profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; if (resetProfile) { if (!resetProfile(pkg, profileName, path, dexMetadataPath)) { if (options.isCheckForProfileUpdates()) { profileAnalysisResult = analyseProfiles(pkg, sharedGid, profileName, compilerFilter); } String cloudProfileName = null; try { if (useCloudProfile) { cloudProfileName = "cloud-" + profileName; if (prepareCloudProfile(pkg, cloudProfileName, path, dexMetadataPath)) { profileName = cloudProfileName; } else { // Fall back to use the shared filter. compilerFilter = PackageManagerServiceCompilerMapping.getCompilerFilterForReason( PackageManagerService.REASON_SHARED); profileName = null; } } else if (options.isCheckForProfileUpdates()) { profileAnalysisResult = analyseProfiles(pkg, sharedGid, profileName, compilerFilter); // We still run `analyseProfiles` even if `useCloudProfile` is true because it // merges profiles into the reference profile, which a system API // `ArtManager.snapshotRuntimeProfile` takes snapshots from. However, we don't // want the result to affect the decision of whether dexopt is needed. profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; } // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct // flags. final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, resetProfile, options); final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, useCloudProfile, options); for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter, Loading Loading @@ -400,27 +413,39 @@ public class PackageDexOptimizer { result = newResult; } } } finally { if (cloudProfileName != null) { try { mInstaller.deleteReferenceProfile(pkg.getPackageName(), cloudProfileName); } catch (InstallerException e) { Slog.w(TAG, "Failed to cleanup cloud profile", e); } } } } return result; } /** * Resets the profiles of the dex file at {@code path} belonging to the package {@code pkg} to * the initial state as if the package is newly installed. Returns true on success, or false * otherwise. * Creates a profile with the name {@code profileName} from the dex metadata file at {@code * dexMetadataPath} for the dex file at {@code path} belonging to the package {@code pkg}. * * @return true on success, or false otherwise. */ @GuardedBy("mInstallLock") private boolean resetProfile(AndroidPackage pkg, String profileName, String path, private boolean prepareCloudProfile(AndroidPackage pkg, String profileName, String path, @Nullable String dexMetadataPath) { if (dexMetadataPath != null) { try { mInstaller.clearAppProfiles(pkg.getPackageName(), profileName); // Make sure we don't keep any existing contents. mInstaller.deleteReferenceProfile(pkg.getPackageName(), profileName); final int appId = UserHandle.getAppId(pkg.getUid()); mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId, profileName, path, dexMetadataPath); mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId, profileName, path, dexMetadataPath); return true; } catch (InstallerException e) { Slog.w(TAG, "Failed to reset profile", e); Slog.w(TAG, "Failed to prepare cloud profile", e); return false; } } else { Loading Loading @@ -835,16 +860,16 @@ public class PackageDexOptimizer { private int getDexFlags(ApplicationInfo info, String compilerFilter, DexoptOptions options) { return getDexFlags((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0, info.getHiddenApiEnforcementPolicy(), info.splitDependencies, info.requestsIsolatedSplitLoading(), compilerFilter, false /* resetProfile */, info.requestsIsolatedSplitLoading(), compilerFilter, false /* useCloudProfile */, options); } private int getDexFlags(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting, String compilerFilter, boolean resetProfile, DexoptOptions options) { String compilerFilter, boolean useCloudProfile, DexoptOptions options) { return getDexFlags(pkg.isDebuggable(), AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting), pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter, resetProfile, options); useCloudProfile, options); } /** Loading @@ -853,15 +878,15 @@ public class PackageDexOptimizer { */ private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy, SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading, String compilerFilter, boolean resetProfile, DexoptOptions options) { String compilerFilter, boolean useCloudProfile, DexoptOptions options) { // Profile guide compiled oat files should not be public unles they are based // on profiles from dex metadata archives. // The flag isDexoptInstallWithDexMetadata applies only on installs when we know that // the user does not have an existing profile. // The flag resetProfile applies only when the existing profile is already reset. // The flag useCloudProfile applies only when the cloud profile should be used. boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter); boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata() || resetProfile; || useCloudProfile; int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0; // Some apps are executed with restrictions on hidden API usage. If this app is one // of them, pass a flag to dexopt to enable the same restrictions during compilation. Loading Loading
services/core/java/com/android/server/pm/Installer.java +14 −0 Original line number Diff line number Diff line Loading @@ -692,6 +692,20 @@ public class Installer extends SystemService { } } /** * Deletes the reference profile with the given name of the given package. * @throws InstallerException if the deletion fails. */ public void deleteReferenceProfile(String packageName, String profileName) throws InstallerException { if (!checkBeforeRemote()) return; try { mInstalld.deleteReferenceProfile(packageName, profileName); } catch (Exception e) { throw InstallerException.from(e); } } public void createUserData(String uuid, int userId, int userSerial, int flags) throws InstallerException { if (!checkBeforeRemote()) return; Loading
services/core/java/com/android/server/pm/PackageDexOptimizer.java +92 −67 Original line number Diff line number Diff line Loading @@ -324,12 +324,12 @@ public class PackageDexOptimizer { String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter()); // If the app is used by other apps, we must not use the existing profile because it // may contain user data, unless the profile is newly created on install. final boolean resetProfile = isProfileGuidedCompilerFilter(compilerFilter) final boolean useCloudProfile = isProfileGuidedCompilerFilter(compilerFilter) && isUsedByOtherApps && options.getCompilationReason() != PackageManagerService.REASON_INSTALL; String dexMetadataPath = null; if (options.isDexoptInstallWithDexMetadata() || resetProfile) { if (options.isDexoptInstallWithDexMetadata() || useCloudProfile) { File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(new File(path)); dexMetadataPath = dexMetadataFile == null ? null : dexMetadataFile.getAbsolutePath(); Loading @@ -339,22 +339,35 @@ public class PackageDexOptimizer { // PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to // profiles. int profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; if (resetProfile) { if (!resetProfile(pkg, profileName, path, dexMetadataPath)) { if (options.isCheckForProfileUpdates()) { profileAnalysisResult = analyseProfiles(pkg, sharedGid, profileName, compilerFilter); } String cloudProfileName = null; try { if (useCloudProfile) { cloudProfileName = "cloud-" + profileName; if (prepareCloudProfile(pkg, cloudProfileName, path, dexMetadataPath)) { profileName = cloudProfileName; } else { // Fall back to use the shared filter. compilerFilter = PackageManagerServiceCompilerMapping.getCompilerFilterForReason( PackageManagerService.REASON_SHARED); profileName = null; } } else if (options.isCheckForProfileUpdates()) { profileAnalysisResult = analyseProfiles(pkg, sharedGid, profileName, compilerFilter); // We still run `analyseProfiles` even if `useCloudProfile` is true because it // merges profiles into the reference profile, which a system API // `ArtManager.snapshotRuntimeProfile` takes snapshots from. However, we don't // want the result to affect the decision of whether dexopt is needed. profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; } // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct // flags. final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, resetProfile, options); final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, useCloudProfile, options); for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter, Loading Loading @@ -400,27 +413,39 @@ public class PackageDexOptimizer { result = newResult; } } } finally { if (cloudProfileName != null) { try { mInstaller.deleteReferenceProfile(pkg.getPackageName(), cloudProfileName); } catch (InstallerException e) { Slog.w(TAG, "Failed to cleanup cloud profile", e); } } } } return result; } /** * Resets the profiles of the dex file at {@code path} belonging to the package {@code pkg} to * the initial state as if the package is newly installed. Returns true on success, or false * otherwise. * Creates a profile with the name {@code profileName} from the dex metadata file at {@code * dexMetadataPath} for the dex file at {@code path} belonging to the package {@code pkg}. * * @return true on success, or false otherwise. */ @GuardedBy("mInstallLock") private boolean resetProfile(AndroidPackage pkg, String profileName, String path, private boolean prepareCloudProfile(AndroidPackage pkg, String profileName, String path, @Nullable String dexMetadataPath) { if (dexMetadataPath != null) { try { mInstaller.clearAppProfiles(pkg.getPackageName(), profileName); // Make sure we don't keep any existing contents. mInstaller.deleteReferenceProfile(pkg.getPackageName(), profileName); final int appId = UserHandle.getAppId(pkg.getUid()); mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId, profileName, path, dexMetadataPath); mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId, profileName, path, dexMetadataPath); return true; } catch (InstallerException e) { Slog.w(TAG, "Failed to reset profile", e); Slog.w(TAG, "Failed to prepare cloud profile", e); return false; } } else { Loading Loading @@ -835,16 +860,16 @@ public class PackageDexOptimizer { private int getDexFlags(ApplicationInfo info, String compilerFilter, DexoptOptions options) { return getDexFlags((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0, info.getHiddenApiEnforcementPolicy(), info.splitDependencies, info.requestsIsolatedSplitLoading(), compilerFilter, false /* resetProfile */, info.requestsIsolatedSplitLoading(), compilerFilter, false /* useCloudProfile */, options); } private int getDexFlags(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting, String compilerFilter, boolean resetProfile, DexoptOptions options) { String compilerFilter, boolean useCloudProfile, DexoptOptions options) { return getDexFlags(pkg.isDebuggable(), AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting), pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter, resetProfile, options); useCloudProfile, options); } /** Loading @@ -853,15 +878,15 @@ public class PackageDexOptimizer { */ private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy, SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading, String compilerFilter, boolean resetProfile, DexoptOptions options) { String compilerFilter, boolean useCloudProfile, DexoptOptions options) { // Profile guide compiled oat files should not be public unles they are based // on profiles from dex metadata archives. // The flag isDexoptInstallWithDexMetadata applies only on installs when we know that // the user does not have an existing profile. // The flag resetProfile applies only when the existing profile is already reset. // The flag useCloudProfile applies only when the cloud profile should be used. boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter); boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata() || resetProfile; || useCloudProfile; int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0; // Some apps are executed with restrictions on hidden API usage. If this app is one // of them, pass a flag to dexopt to enable the same restrictions during compilation. Loading