Loading services/core/java/com/android/server/pm/Installer.java +44 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,14 @@ public class Installer extends SystemService { */ public static final int PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES = 3; /** * The results of {@code getOdexVisibility}. See * {@link #getOdexVisibility(String, String, String)} for details. */ public static final int ODEX_NOT_FOUND = 0; public static final int ODEX_IS_PUBLIC = 1; public static final int ODEX_IS_PRIVATE = 2; public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE; public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE; Loading Loading @@ -866,6 +874,15 @@ public class Installer extends SystemService { } } /** * Prepares the app profile for the package at the given path: * <ul> * <li>Creates the current profile for the given user ID, unless the user ID is * {@code UserHandle.USER_NULL}.</li> * <li>Merges the profile from the dex metadata file (if present) into the reference * profile.</li> * </ul> */ public boolean prepareAppProfile(String pkg, @UserIdInt int userId, @AppIdInt int appId, String profileName, String codePath, String dexMetadataPath) throws InstallerException { if (!checkBeforeRemote()) return false; Loading Loading @@ -1016,6 +1033,33 @@ public class Installer extends SystemService { } } /** * Returns the visibility of the optimized artifacts. * * @param packageName name of the package. * @param apkPath path to the APK. * @param instructionSet instruction set of the optimized artifacts. * @param outputPath path to the directory that contains the optimized artifacts (i.e., the * directory that {@link #dexopt} outputs to). * * @return {@link #ODEX_NOT_FOUND} if the optimized artifacts are not found, or * {@link #ODEX_IS_PUBLIC} if the optimized artifacts are accessible by all apps, or * {@link #ODEX_IS_PRIVATE} if the optimized artifacts are only accessible by this app. * * @throws InstallerException if failed to get the visibility of the optimized artifacts. */ public int getOdexVisibility(String packageName, String apkPath, String instructionSet, String outputPath) throws InstallerException { if (!checkBeforeRemote()) return -1; BlockGuard.getVmPolicy().onPathAccess(apkPath); BlockGuard.getVmPolicy().onPathAccess(outputPath); try { return mInstalld.getOdexVisibility(packageName, apkPath, instructionSet, outputPath); } catch (Exception e) { throw InstallerException.from(e); } } public static class InstallerException extends Exception { public InstallerException(String detailMessage) { super(detailMessage); Loading services/core/java/com/android/server/pm/PackageDexOptimizer.java +97 −34 Original line number Diff line number Diff line Loading @@ -319,28 +319,42 @@ public class PackageDexOptimizer { String profileName = ArtManager.getProfileName( i == 0 ? null : pkg.getSplitNames()[i - 1]); final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); 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) && isUsedByOtherApps && options.getCompilationReason() != PackageManagerService.REASON_INSTALL; String dexMetadataPath = null; if (options.isDexoptInstallWithDexMetadata()) { if (options.isDexoptInstallWithDexMetadata() || resetProfile) { File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(new File(path)); dexMetadataPath = dexMetadataFile == null ? null : dexMetadataFile.getAbsolutePath(); } final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); final String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter(), isUsedByOtherApps); // If we don't have to check for profiles updates assume // PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to // profiles. final int profileAnalysisResult = options.isCheckForProfileUpdates() ? analyseProfiles(pkg, sharedGid, profileName, compilerFilter) : PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; int profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; if (resetProfile) { if (!resetProfile(pkg, profileName, path, dexMetadataPath)) { // Fall back to use the shared filter. compilerFilter = PackageManagerServiceCompilerMapping.getCompilerFilterForReason( PackageManagerService.REASON_SHARED); } } else if (options.isCheckForProfileUpdates()) { profileAnalysisResult = analyseProfiles(pkg, sharedGid, profileName, compilerFilter); } // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct // flags. final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, options); final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, resetProfile, options); for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter, Loading Loading @@ -390,6 +404,30 @@ public class PackageDexOptimizer { 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. */ @GuardedBy("mInstallLock") private boolean resetProfile(AndroidPackage pkg, String profileName, String path, @Nullable String dexMetadataPath) { if (dexMetadataPath != null) { try { mInstaller.clearAppProfiles(pkg.getPackageName(), profileName); final int appId = UserHandle.getAppId(pkg.getUid()); mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId, profileName, path, dexMetadataPath); return true; } catch (InstallerException e) { Slog.w(TAG, "Failed to reset profile", e); return false; } } else { return false; } } /** * Performs dexopt on the {@code path} belonging to the package {@code pkg}. * Loading @@ -405,15 +443,15 @@ public class PackageDexOptimizer { String classLoaderContext, int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade, String profileName, String dexMetadataPath, int compilationReason) { int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext, profileAnalysisResult, downgrade); String oatDir = getPackageOatDirIfSupported(pkg, pkgSetting.getTransientState().isUpdatedSystemApp()); int dexoptNeeded = getDexoptNeeded(pkg.getPackageName(), path, isa, compilerFilter, classLoaderContext, profileAnalysisResult, downgrade, dexoptFlags, oatDir); if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) { return DEX_OPT_SKIPPED; } String oatDir = getPackageOatDirIfSupported(pkg, pkgSetting.getTransientState().isUpdatedSystemApp()); Log.i(TAG, "Running dexopt (dexoptNeeded=" + dexoptNeeded + ") on: " + path + " pkg=" + pkg.getPackageName() + " isa=" + isa + " dexoptFlags=" + printDexoptFlags(dexoptFlags) Loading Loading @@ -456,6 +494,7 @@ public class PackageDexOptimizer { /** * Perform dexopt (if needed) on a system server code path). */ @GuardedBy("mInstallLock") @DexOptResult public int dexoptSystemServerPath( String dexPath, PackageDexUsage.DexUseInfo dexUseInfo, DexoptOptions options) { Loading @@ -466,12 +505,15 @@ public class PackageDexOptimizer { int result = DEX_OPT_SKIPPED; for (String isa : dexUseInfo.getLoaderIsas()) { int dexoptNeeded = getDexoptNeeded( PackageManagerService.PLATFORM_PACKAGE_NAME, dexPath, isa, options.getCompilerFilter(), dexUseInfo.getClassLoaderContext(), PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES, /* downgrade= */ false); /* downgrade= */ false, dexoptFlags, /* oatDir= */ null); if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) { continue; Loading Loading @@ -714,7 +756,7 @@ public class PackageDexOptimizer { } /** * Returns the compiler filter that should be used to optimize the package code. * Returns the compiler filter that should be used to optimize the secondary dex. * The target filter will be updated if the package code is used by other apps * or if it has the safe mode flag set. */ Loading Loading @@ -754,12 +796,12 @@ public class PackageDexOptimizer { } /** * Returns the compiler filter that should be used to optimize the package code. * The target filter will be updated if the package code is used by other apps * or if it has the safe mode flag set. * Returns the compiler filter that should be used to optimize the primary dex. * The target filter will be updated if the package has the safe mode flag set. Note that this * method does NOT take other app use into account. The caller should be responsible for * handling the case where the package code is used by other apps. */ private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter, boolean isUsedByOtherApps) { private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter) { // When an app or priv app is configured to run out of box, only verify it. if (pkg.isUseEmbeddedDex() || (pkg.isPrivileged() Loading @@ -783,12 +825,6 @@ public class PackageDexOptimizer { return getSafeModeCompilerFilter(targetCompilerFilter); } if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) { // If the dex files is used by other apps, apply the shared filter. return PackageManagerServiceCompilerMapping.getCompilerFilterForReason( PackageManagerService.REASON_SHARED); } return targetCompilerFilter; } Loading @@ -799,14 +835,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, options); info.requestsIsolatedSplitLoading(), compilerFilter, false /* resetProfile */, options); } private int getDexFlags(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting, String compilerFilter, DexoptOptions options) { String compilerFilter, boolean resetProfile, DexoptOptions options) { return getDexFlags(pkg.isDebuggable(), AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting), pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter, options); resetProfile, options); } /** Loading @@ -815,13 +853,15 @@ public class PackageDexOptimizer { */ private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy, SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading, String compilerFilter, DexoptOptions options) { String compilerFilter, boolean resetProfile, 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. boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter); boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata(); boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata() || resetProfile; 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 @@ -866,8 +906,19 @@ public class PackageDexOptimizer { * Assesses if there's a need to perform dexopt on {@code path} for the given * configuration (isa, compiler filter, profile). */ private int getDexoptNeeded(String path, String isa, String compilerFilter, String classLoaderContext, int profileAnalysisResult, boolean downgrade) { @GuardedBy("mInstallLock") private int getDexoptNeeded(String packageName, String path, String isa, String compilerFilter, String classLoaderContext, int profileAnalysisResult, boolean downgrade, int dexoptFlags, String oatDir) { final boolean shouldBePublic = (dexoptFlags & DEXOPT_PUBLIC) != 0; // If the artifacts should be public while the current artifacts are not, we should // re-compile anyway. if (shouldBePublic && isOdexPrivate(packageName, path, isa, oatDir)) { // Ensure compilation by pretending a compiler filter change on the apk/odex location // (the reason for the '-'. A positive value means the 'oat' location). return adjustDexoptNeeded(-DexFile.DEX2OAT_FOR_FILTER); } int dexoptNeeded; try { // A profile guided optimizations with an empty profile is essentially 'verify' and Loading Loading @@ -901,6 +952,18 @@ public class PackageDexOptimizer { return compilerFilter.endsWith("-profile"); } /** Returns true if the current artifacts of the app are private to the app itself. */ @GuardedBy("mInstallLock") private boolean isOdexPrivate(String packageName, String path, String isa, String oatDir) { try { return mInstaller.getOdexVisibility(packageName, path, isa, oatDir) == Installer.ODEX_IS_PRIVATE; } catch (Exception e) { Slog.w(TAG, "Failed to get odex visibility for " + path, e); return false; } } /** * Checks if there is an update on the profile information of the {@code pkg}. * If the compiler filter is not profile guided the method returns a safe default: Loading Loading
services/core/java/com/android/server/pm/Installer.java +44 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,14 @@ public class Installer extends SystemService { */ public static final int PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES = 3; /** * The results of {@code getOdexVisibility}. See * {@link #getOdexVisibility(String, String, String)} for details. */ public static final int ODEX_NOT_FOUND = 0; public static final int ODEX_IS_PUBLIC = 1; public static final int ODEX_IS_PRIVATE = 2; public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE; public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE; Loading Loading @@ -866,6 +874,15 @@ public class Installer extends SystemService { } } /** * Prepares the app profile for the package at the given path: * <ul> * <li>Creates the current profile for the given user ID, unless the user ID is * {@code UserHandle.USER_NULL}.</li> * <li>Merges the profile from the dex metadata file (if present) into the reference * profile.</li> * </ul> */ public boolean prepareAppProfile(String pkg, @UserIdInt int userId, @AppIdInt int appId, String profileName, String codePath, String dexMetadataPath) throws InstallerException { if (!checkBeforeRemote()) return false; Loading Loading @@ -1016,6 +1033,33 @@ public class Installer extends SystemService { } } /** * Returns the visibility of the optimized artifacts. * * @param packageName name of the package. * @param apkPath path to the APK. * @param instructionSet instruction set of the optimized artifacts. * @param outputPath path to the directory that contains the optimized artifacts (i.e., the * directory that {@link #dexopt} outputs to). * * @return {@link #ODEX_NOT_FOUND} if the optimized artifacts are not found, or * {@link #ODEX_IS_PUBLIC} if the optimized artifacts are accessible by all apps, or * {@link #ODEX_IS_PRIVATE} if the optimized artifacts are only accessible by this app. * * @throws InstallerException if failed to get the visibility of the optimized artifacts. */ public int getOdexVisibility(String packageName, String apkPath, String instructionSet, String outputPath) throws InstallerException { if (!checkBeforeRemote()) return -1; BlockGuard.getVmPolicy().onPathAccess(apkPath); BlockGuard.getVmPolicy().onPathAccess(outputPath); try { return mInstalld.getOdexVisibility(packageName, apkPath, instructionSet, outputPath); } catch (Exception e) { throw InstallerException.from(e); } } public static class InstallerException extends Exception { public InstallerException(String detailMessage) { super(detailMessage); Loading
services/core/java/com/android/server/pm/PackageDexOptimizer.java +97 −34 Original line number Diff line number Diff line Loading @@ -319,28 +319,42 @@ public class PackageDexOptimizer { String profileName = ArtManager.getProfileName( i == 0 ? null : pkg.getSplitNames()[i - 1]); final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); 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) && isUsedByOtherApps && options.getCompilationReason() != PackageManagerService.REASON_INSTALL; String dexMetadataPath = null; if (options.isDexoptInstallWithDexMetadata()) { if (options.isDexoptInstallWithDexMetadata() || resetProfile) { File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(new File(path)); dexMetadataPath = dexMetadataFile == null ? null : dexMetadataFile.getAbsolutePath(); } final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); final String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter(), isUsedByOtherApps); // If we don't have to check for profiles updates assume // PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to // profiles. final int profileAnalysisResult = options.isCheckForProfileUpdates() ? analyseProfiles(pkg, sharedGid, profileName, compilerFilter) : PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; int profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; if (resetProfile) { if (!resetProfile(pkg, profileName, path, dexMetadataPath)) { // Fall back to use the shared filter. compilerFilter = PackageManagerServiceCompilerMapping.getCompilerFilterForReason( PackageManagerService.REASON_SHARED); } } else if (options.isCheckForProfileUpdates()) { profileAnalysisResult = analyseProfiles(pkg, sharedGid, profileName, compilerFilter); } // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct // flags. final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, options); final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, resetProfile, options); for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter, Loading Loading @@ -390,6 +404,30 @@ public class PackageDexOptimizer { 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. */ @GuardedBy("mInstallLock") private boolean resetProfile(AndroidPackage pkg, String profileName, String path, @Nullable String dexMetadataPath) { if (dexMetadataPath != null) { try { mInstaller.clearAppProfiles(pkg.getPackageName(), profileName); final int appId = UserHandle.getAppId(pkg.getUid()); mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId, profileName, path, dexMetadataPath); return true; } catch (InstallerException e) { Slog.w(TAG, "Failed to reset profile", e); return false; } } else { return false; } } /** * Performs dexopt on the {@code path} belonging to the package {@code pkg}. * Loading @@ -405,15 +443,15 @@ public class PackageDexOptimizer { String classLoaderContext, int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade, String profileName, String dexMetadataPath, int compilationReason) { int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext, profileAnalysisResult, downgrade); String oatDir = getPackageOatDirIfSupported(pkg, pkgSetting.getTransientState().isUpdatedSystemApp()); int dexoptNeeded = getDexoptNeeded(pkg.getPackageName(), path, isa, compilerFilter, classLoaderContext, profileAnalysisResult, downgrade, dexoptFlags, oatDir); if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) { return DEX_OPT_SKIPPED; } String oatDir = getPackageOatDirIfSupported(pkg, pkgSetting.getTransientState().isUpdatedSystemApp()); Log.i(TAG, "Running dexopt (dexoptNeeded=" + dexoptNeeded + ") on: " + path + " pkg=" + pkg.getPackageName() + " isa=" + isa + " dexoptFlags=" + printDexoptFlags(dexoptFlags) Loading Loading @@ -456,6 +494,7 @@ public class PackageDexOptimizer { /** * Perform dexopt (if needed) on a system server code path). */ @GuardedBy("mInstallLock") @DexOptResult public int dexoptSystemServerPath( String dexPath, PackageDexUsage.DexUseInfo dexUseInfo, DexoptOptions options) { Loading @@ -466,12 +505,15 @@ public class PackageDexOptimizer { int result = DEX_OPT_SKIPPED; for (String isa : dexUseInfo.getLoaderIsas()) { int dexoptNeeded = getDexoptNeeded( PackageManagerService.PLATFORM_PACKAGE_NAME, dexPath, isa, options.getCompilerFilter(), dexUseInfo.getClassLoaderContext(), PROFILE_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES, /* downgrade= */ false); /* downgrade= */ false, dexoptFlags, /* oatDir= */ null); if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) { continue; Loading Loading @@ -714,7 +756,7 @@ public class PackageDexOptimizer { } /** * Returns the compiler filter that should be used to optimize the package code. * Returns the compiler filter that should be used to optimize the secondary dex. * The target filter will be updated if the package code is used by other apps * or if it has the safe mode flag set. */ Loading Loading @@ -754,12 +796,12 @@ public class PackageDexOptimizer { } /** * Returns the compiler filter that should be used to optimize the package code. * The target filter will be updated if the package code is used by other apps * or if it has the safe mode flag set. * Returns the compiler filter that should be used to optimize the primary dex. * The target filter will be updated if the package has the safe mode flag set. Note that this * method does NOT take other app use into account. The caller should be responsible for * handling the case where the package code is used by other apps. */ private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter, boolean isUsedByOtherApps) { private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter) { // When an app or priv app is configured to run out of box, only verify it. if (pkg.isUseEmbeddedDex() || (pkg.isPrivileged() Loading @@ -783,12 +825,6 @@ public class PackageDexOptimizer { return getSafeModeCompilerFilter(targetCompilerFilter); } if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) { // If the dex files is used by other apps, apply the shared filter. return PackageManagerServiceCompilerMapping.getCompilerFilterForReason( PackageManagerService.REASON_SHARED); } return targetCompilerFilter; } Loading @@ -799,14 +835,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, options); info.requestsIsolatedSplitLoading(), compilerFilter, false /* resetProfile */, options); } private int getDexFlags(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting, String compilerFilter, DexoptOptions options) { String compilerFilter, boolean resetProfile, DexoptOptions options) { return getDexFlags(pkg.isDebuggable(), AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting), pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter, options); resetProfile, options); } /** Loading @@ -815,13 +853,15 @@ public class PackageDexOptimizer { */ private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy, SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading, String compilerFilter, DexoptOptions options) { String compilerFilter, boolean resetProfile, 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. boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter); boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata(); boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata() || resetProfile; 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 @@ -866,8 +906,19 @@ public class PackageDexOptimizer { * Assesses if there's a need to perform dexopt on {@code path} for the given * configuration (isa, compiler filter, profile). */ private int getDexoptNeeded(String path, String isa, String compilerFilter, String classLoaderContext, int profileAnalysisResult, boolean downgrade) { @GuardedBy("mInstallLock") private int getDexoptNeeded(String packageName, String path, String isa, String compilerFilter, String classLoaderContext, int profileAnalysisResult, boolean downgrade, int dexoptFlags, String oatDir) { final boolean shouldBePublic = (dexoptFlags & DEXOPT_PUBLIC) != 0; // If the artifacts should be public while the current artifacts are not, we should // re-compile anyway. if (shouldBePublic && isOdexPrivate(packageName, path, isa, oatDir)) { // Ensure compilation by pretending a compiler filter change on the apk/odex location // (the reason for the '-'. A positive value means the 'oat' location). return adjustDexoptNeeded(-DexFile.DEX2OAT_FOR_FILTER); } int dexoptNeeded; try { // A profile guided optimizations with an empty profile is essentially 'verify' and Loading Loading @@ -901,6 +952,18 @@ public class PackageDexOptimizer { return compilerFilter.endsWith("-profile"); } /** Returns true if the current artifacts of the app are private to the app itself. */ @GuardedBy("mInstallLock") private boolean isOdexPrivate(String packageName, String path, String isa, String oatDir) { try { return mInstaller.getOdexVisibility(packageName, path, isa, oatDir) == Installer.ODEX_IS_PRIVATE; } catch (Exception e) { Slog.w(TAG, "Failed to get odex visibility for " + path, e); return false; } } /** * Checks if there is an update on the profile information of the {@code pkg}. * If the compiler filter is not profile guided the method returns a safe default: Loading