diff options
Diffstat (limited to 'java/dexpreopt.go')
| -rw-r--r-- | java/dexpreopt.go | 303 |
1 files changed, 260 insertions, 43 deletions
diff --git a/java/dexpreopt.go b/java/dexpreopt.go index a96b31281..794924401 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -16,8 +16,11 @@ package java import ( "path/filepath" + "sort" "strings" + "github.com/google/blueprint/proptools" + "android/soong/android" "android/soong/dexpreopt" ) @@ -28,7 +31,7 @@ type DexpreopterInterface interface { IsInstallable() bool // True if dexpreopt is disabled for the java module. - dexpreoptDisabled(ctx android.BaseModuleContext) bool + dexpreoptDisabled(ctx android.BaseModuleContext, libraryName string) bool // If the java module is to be installed into an APEX, this list contains information about the // dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed @@ -78,22 +81,38 @@ func (install *dexpreopterInstall) SubModuleName() string { func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries { return android.AndroidMkEntries{ Class: "ETC", - SubName: install.SubModuleName(), OutputFile: android.OptionalPathForPath(install.outputPathOnHost), ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + entries.SetString("LOCAL_MODULE", install.FullModuleName()) entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String()) entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice) entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false") + // Unset LOCAL_SOONG_INSTALLED_MODULE so that this does not default to the primary .apex file + // Without this, installation of the dexpreopt artifacts get skipped + entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", "") }, }, } } +func (install dexpreopterInstall) PackageFile(ctx android.ModuleContext) android.PackagingSpec { + return ctx.PackageFile(install.installDirOnDevice, install.installFileOnDevice, install.outputPathOnHost) +} + +type Dexpreopter struct { + dexpreopter +} + type dexpreopter struct { dexpreoptProperties DexpreoptProperties importDexpreoptProperties ImportDexpreoptProperties + // If true, the dexpreopt rules will not be generated + // Unlike Dex_preopt.Enabled which is user-facing, + // shouldDisableDexpreopt is a mutated propery. + shouldDisableDexpreopt bool + installPath android.InstallPath uncompressedDex bool isSDKLibrary bool @@ -126,6 +145,10 @@ type dexpreopter struct { // The path to the profile that dexpreopter accepts. It must be in the binary format. If this is // set, it overrides the profile settings in `dexpreoptProperties`. inputProfilePathOnHost android.Path + + // The path to the profile that matches the dex optimized by r8/d8. It is in text format. If this is + // set, it will be converted to a binary profile which will be subsequently used for dexpreopt. + rewrittenProfile android.Path } type DexpreoptProperties struct { @@ -145,6 +168,11 @@ type DexpreoptProperties struct { // defaults to searching for a file that matches the name of this module in the default // profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found. Profile *string `android:"path"` + + // If set to true, r8/d8 will use `profile` as input to generate a new profile that matches + // the optimized dex. + // The new profile will be subsequently used as the profile to dexpreopt the dex file. + Enable_profile_rewriting *bool } Dex_preopt_result struct { @@ -165,24 +193,47 @@ func init() { } func isApexVariant(ctx android.BaseModuleContext) bool { - apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) return !apexInfo.IsForPlatform() } func forPrebuiltApex(ctx android.BaseModuleContext) bool { - apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) return apexInfo.ForPrebuiltApex } -func moduleName(ctx android.BaseModuleContext) string { - // Remove the "prebuilt_" prefix if the module is from a prebuilt because the prefix is not - // expected by dexpreopter. - return android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()) +// For apex variant of modules, this returns true on the source variant if the prebuilt apex +// has been selected using apex_contributions. +// The prebuilt apex will be responsible for generating the dexpreopt rules of the deapexed java lib. +func disableSourceApexVariant(ctx android.BaseModuleContext) bool { + if !isApexVariant(ctx) { + return false // platform variant + } + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + psi := android.PrebuiltSelectionInfoMap{} + ctx.VisitDirectDeps(func(am android.Module) { + if prebuiltSelectionInfo, ok := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); ok { + psi = prebuiltSelectionInfo + } + }) + // Find the apex variant for this module + _, apexVariantsWithoutTestApexes, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes) + disableSource := false + // find the selected apexes + for _, apexVariant := range apexVariantsWithoutTestApexes { + for _, selected := range psi.GetSelectedModulesForApiDomain(apexVariant) { + // If the apex_contribution for this api domain contains a prebuilt apex, disable the source variant + if strings.HasPrefix(selected, "prebuilt_com.google.android") { + disableSource = true + } + } + } + return disableSource } // Returns whether dexpreopt is applicable to the module. // When it returns true, neither profile nor dexpreopt artifacts will be generated. -func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { +func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName string) bool { if !ctx.Device() { return true } @@ -195,6 +246,10 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { return true } + if d.shouldDisableDexpreopt { + return true + } + // If the module is from a prebuilt APEX, it shouldn't be installable, but it can still be // dexpreopted. if !ctx.Module().(DexpreopterInterface).IsInstallable() && !forPrebuiltApex(ctx) { @@ -205,14 +260,37 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { return true } + if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex { + // dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes + return false + } + global := dexpreopt.GetGlobalConfig(ctx) - isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) - if isApexVariant(ctx) { - // Don't preopt APEX variant module unless the module is an APEX system server jar. + // Use the libName argument to determine if the library being dexpreopt'd is a system server jar + // ctx.ModuleName() is not safe. In case of prebuilt apexes, the dexpreopt rules of system server jars + // are created in the ctx object of the top-level prebuilt apex. + isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(libName) + + if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex || isApexVariant(ctx) { + // dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes if !isApexSystemServerJar { return true } + ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + allApexInfos := []android.ApexInfo{} + if allApexInfosProvider, ok := android.ModuleProvider(ctx, android.AllApexInfoProvider); ok { + allApexInfos = allApexInfosProvider.ApexInfos + } + if len(allApexInfos) > 0 && !ai.MinSdkVersion.EqualTo(allApexInfos[0].MinSdkVersion) { + // Apex system server jars are dexpreopted and installed on to the system image. + // Since we can have BigAndroid and Go variants of system server jar providing apexes, + // and these two variants can have different min_sdk_versions, hide one of the apex variants + // from make to prevent collisions. + // + // Unlike cc, min_sdk_version does not have an effect on the build actions of java libraries. + ctx.Module().MakeUninstallable() + } } else { // Don't preopt the platform variant of an APEX system server jar to avoid conflicts. if isApexSystemServerJar { @@ -226,16 +304,18 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool { } func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) { - if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) || !dexpreopt.IsDex2oatNeeded(ctx) { + if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex && dexpreopt.IsDex2oatNeeded(ctx) { + // prebuilt apexes can genererate rules to dexpreopt deapexed jars + // Add a dex2oat dep aggressively on _every_ apex module + dexpreopt.RegisterToolDeps(ctx) + return + } + if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())) || !dexpreopt.IsDex2oatNeeded(ctx) { return } dexpreopt.RegisterToolDeps(ctx) } -func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool { - return dexpreopt.OdexOnSystemOtherByName(moduleName(ctx), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx)) -} - // Returns the install path of the dex jar of a module. // // Do not rely on `ApexInfo.ApexVariationName` because it can be something like "apex1000", rather @@ -244,20 +324,42 @@ func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath a // This function is on a best-effort basis. It cannot handle the case where an APEX jar is not a // system server jar, which is fine because we currently only preopt system server jars for APEXes. func (d *dexpreopter) getInstallPath( - ctx android.ModuleContext, defaultInstallPath android.InstallPath) android.InstallPath { + ctx android.ModuleContext, libName string, defaultInstallPath android.InstallPath) android.InstallPath { global := dexpreopt.GetGlobalConfig(ctx) - if global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) { - dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, moduleName(ctx)) + if global.AllApexSystemServerJars(ctx).ContainsJar(libName) { + dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, libName) return android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexLocation, "/")) } - if !d.dexpreoptDisabled(ctx) && isApexVariant(ctx) && + if !d.dexpreoptDisabled(ctx, libName) && isApexVariant(ctx) && filepath.Base(defaultInstallPath.PartitionDir()) != "apex" { ctx.ModuleErrorf("unable to get the install path of the dex jar for dexpreopt") } return defaultInstallPath } -func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) { +// DexpreoptPrebuiltApexSystemServerJars generates the dexpreopt artifacts from a jar file that has been deapexed from a prebuilt apex +func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleContext, libraryName string, di *android.DeapexerInfo) { + // A single prebuilt apex can have multiple apex system jars + // initialize the output path for this dex jar + dc := dexpreopt.GetGlobalConfig(ctx) + d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/")) + // generate the rules for creating the .odex and .vdex files for this system server jar + dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName)) + + d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless + if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) { + // Set the profile path to guide optimization + prof := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName) + ".prof") + if prof == nil { + ctx.ModuleErrorf("Could not find a .prof file in this prebuilt apex") + } + d.inputProfilePathOnHost = prof + } + + d.dexpreopt(ctx, libraryName, dexJarFile) +} + +func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJarFile android.WritablePath) { global := dexpreopt.GetGlobalConfig(ctx) // TODO(b/148690468): The check on d.installPath is to bail out in cases where @@ -270,7 +372,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath) - providesUsesLib := moduleName(ctx) + providesUsesLib := libName if ulib, ok := ctx.Module().(ProvidesUsesLib); ok { name := ulib.ProvidesUsesLib() if name != nil { @@ -280,11 +382,11 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr // If it is test, make config files regardless of its dexpreopt setting. // The config files are required for apps defined in make which depend on the lib. - if d.isTest && d.dexpreoptDisabled(ctx) { + if d.isTest && d.dexpreoptDisabled(ctx, libName) { return } - isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(moduleName(ctx)) + isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(libName) bootImage := defaultBootImageConfig(ctx) // When `global.PreoptWithUpdatableBcp` is true, `bcpForDexpreopt` below includes the mainline @@ -303,7 +405,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr targets = append(targets, target) } } - if isSystemServerJar && moduleName(ctx) != "com.android.location.provider" { + if isSystemServerJar && libName != "com.android.location.provider" { // If the module is a system server jar, only preopt for the primary arch because the jar can // only be loaded by system server. "com.android.location.provider" is a special case because // it's also used by apps as a shared library. @@ -326,30 +428,39 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr var profileClassListing android.OptionalPath var profileBootListing android.OptionalPath profileIsTextListing := false + if d.inputProfilePathOnHost != nil { profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost) } else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) { - // If dex_preopt.profile_guided is not set, default it based on the existence of the - // dexprepot.profile option or the profile class listing. - if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" { + // If enable_profile_rewriting is set, use the rewritten profile instead of the checked-in profile + if d.EnableProfileRewriting() { + profileClassListing = android.OptionalPathForPath(d.GetRewrittenProfile()) + profileIsTextListing = true + } else if profile := d.GetProfile(); profile != "" { + // If dex_preopt.profile_guided is not set, default it based on the existence of the + // dexprepot.profile option or the profile class listing. profileClassListing = android.OptionalPathForPath( - android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile))) + android.PathForModuleSrc(ctx, profile)) profileBootListing = android.ExistentPathForSource(ctx, - ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot") + ctx.ModuleDir(), profile+"-boot") profileIsTextListing = true } else if global.ProfileDir != "" { profileClassListing = android.ExistentPathForSource(ctx, - global.ProfileDir, moduleName(ctx)+".prof") + global.ProfileDir, libName+".prof") } } d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid() + // A single apex can have multiple system server jars + // Use the dexJar to create a unique scope for each + dexJarStem := strings.TrimSuffix(dexJarFile.Base(), dexJarFile.Ext()) + // Full dexpreopt config, used to create dexpreopt build rules. dexpreoptConfig := &dexpreopt.ModuleConfig{ - Name: moduleName(ctx), + Name: libName, DexLocation: dexLocation, - BuildPath: android.PathForModuleOut(ctx, "dexpreopt", moduleName(ctx)+".jar").OutputPath, + BuildPath: android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, libName+".jar").OutputPath, DexPath: dexJarFile, ManifestPath: android.OptionalPathForPath(d.manifestFile), UncompressedDex: d.uncompressedDex, @@ -373,39 +484,90 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr PreoptBootClassPathDexFiles: dexFiles.Paths(), PreoptBootClassPathDexLocations: dexLocations, - PreoptExtractedApk: false, - NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true), ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false), PresignedPrebuilt: d.isPresignedPrebuilt, } - d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config") + d.configPath = android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "dexpreopt.config") dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath) - if d.dexpreoptDisabled(ctx) { + if d.dexpreoptDisabled(ctx, libName) { return } globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) - dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig) + // The root "product_packages.txt" is generated by `build/make/core/Makefile`. It contains a list + // of all packages that are installed on the device. We use `grep` to filter the list by the app's + // dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime + // from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns. + productPackages := android.PathForModuleInPartitionInstall(ctx, "", "product_packages.txt") + appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "product_packages.txt") + appProductPackagesStaging := appProductPackages.ReplaceExtension(ctx, "txt.tmp") + clcNames, _ := dexpreopt.ComputeClassLoaderContextDependencies(dexpreoptConfig.ClassLoaderContexts) + sort.Strings(clcNames) // The order needs to be deterministic. + productPackagesRule := android.NewRuleBuilder(pctx, ctx) + if len(clcNames) > 0 { + productPackagesRule.Command(). + Text("grep -F -x"). + FlagForEachArg("-e ", clcNames). + Input(productPackages). + FlagWithOutput("> ", appProductPackagesStaging). + Text("|| true") + } else { + productPackagesRule.Command(). + Text("rm -f").Output(appProductPackagesStaging). + Text("&&"). + Text("touch").Output(appProductPackagesStaging) + } + productPackagesRule.Command(). + Text("rsync --checksum"). + Input(appProductPackagesStaging). + Output(appProductPackages) + productPackagesRule.Restat().Build("product_packages."+dexJarStem, "dexpreopt product_packages") + + // Prebuilts are active, do not copy the dexpreopt'd source javalib to out/soong/system_server_dexjars + // The javalib from the deapexed prebuilt will be copied to this location. + // TODO (b/331665856): Implement a principled solution for this. + copyApexSystemServerJarDex := !disableSourceApexVariant(ctx) && !ctx.Module().IsHideFromMake() + dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule( + ctx, globalSoong, global, dexpreoptConfig, appProductPackages, copyApexSystemServerJarDex) if err != nil { ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error()) return } - dexpreoptRule.Build("dexpreopt", "dexpreopt") + dexpreoptRule.Build("dexpreopt"+"."+dexJarStem, "dexpreopt") - isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) + // The current ctx might be of a deapexer module created by a prebuilt apex + // Use the path of the dex file to determine the library name + isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(dexJarStem) + dexpreoptPartition := d.installPath.Partition() + // dexpreoptPartition is set to empty for dexpreopts of system APEX and system_other. + // In case of system APEX, however, we can set it to "system" manually. + // TODO(b/346662300): Let dexpreopter generate the installPath for dexpreopt files instead of + // using the dex location to generate the installPath. + if isApexSystemServerJar { + dexpreoptPartition = "system" + } for _, install := range dexpreoptRule.Installs() { // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT. installDir := strings.TrimPrefix(filepath.Dir(install.To), "/") + partition := dexpreoptPartition + if strings.HasPrefix(installDir, partition+"/") { + installDir = strings.TrimPrefix(installDir, partition+"/") + } else { + // If the partition for the installDir is different from the install partition, set the + // partition empty to install the dexpreopt files to the desired partition. + // TODO(b/346439786): Define and use the dexpreopt module type to avoid this mismatch. + partition = "" + } installBase := filepath.Base(install.To) arch := filepath.Base(installDir) - installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir) + installPath := android.PathForModuleInPartitionInstall(ctx, partition, installDir) isProfile := strings.HasSuffix(installBase, ".prof") if isProfile { @@ -423,7 +585,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr // The installs will be handled by Make as sub-modules of the java library. d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{ name: arch + "-" + installBase, - moduleName: moduleName(ctx), + moduleName: libName, outputPathOnHost: install.From, installDirOnDevice: installPath, installFileOnDevice: installBase, @@ -439,6 +601,37 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr } } +func getModuleInstallPathInfo(ctx android.ModuleContext, fullInstallPath string) (android.InstallPath, string, string) { + installPath := android.PathForModuleInstall(ctx) + installDir, installBase := filepath.Split(strings.TrimPrefix(fullInstallPath, "/")) + + if !strings.HasPrefix(installDir, installPath.Partition()+"/") { + // Return empty filename if the install partition is not for the target image. + return installPath, "", "" + } + relDir, err := filepath.Rel(installPath.Partition(), installDir) + if err != nil { + panic(err) + } + return installPath, relDir, installBase +} + +// RuleBuilder.Install() adds output-to-install copy pairs to a list for Make. To share this +// information with PackagingSpec in soong, call PackageFile for them. +// The install path and the target install partition of the module must be the same. +func packageFile(ctx android.ModuleContext, install android.RuleBuilderInstall) { + installPath, relDir, name := getModuleInstallPathInfo(ctx, install.To) + // Empty name means the install partition is not for the target image. + // For the system image, files for "apex" and "system_other" are skipped here. + // The skipped "apex" files are for testing only, for example, + // "/apex/art_boot_images/javalib/x86/boot.vdex". + // TODO(b/320196894): Files for "system_other" are skipped because soong creates the system + // image only for now. + if name != "" { + ctx.PackageFile(installPath.Join(ctx, relDir), name, install.From) + } +} + func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall { return d.builtInstalledForApex } @@ -454,3 +647,27 @@ func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries { func (d *dexpreopter) OutputProfilePathOnHost() android.Path { return d.outputProfilePathOnHost } + +func (d *dexpreopter) disableDexpreopt() { + d.shouldDisableDexpreopt = true +} + +func (d *dexpreopter) EnableProfileRewriting() bool { + return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting) +} + +func (d *dexpreopter) GetProfile() string { + return proptools.String(d.dexpreoptProperties.Dex_preopt.Profile) +} + +func (d *dexpreopter) GetProfileGuided() bool { + return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Profile_guided) +} + +func (d *dexpreopter) GetRewrittenProfile() android.Path { + return d.rewrittenProfile +} + +func (d *dexpreopter) SetRewrittenProfile(p android.Path) { + d.rewrittenProfile = p +} |