Merge "Dedup apex/Prebuilt and apex/ApexSet" into sc-dev
diff --git a/android/config.go b/android/config.go
index 6dc8efe..24fc522 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1661,6 +1661,16 @@
return paths
}
+// BuildPathsByModule returns a map from module name to build paths based on the given directory
+// prefix.
+func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
+ paths := map[string]WritablePath{}
+ for _, jar := range l.jars {
+ paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
+ }
+ return paths
+}
+
// UnmarshalJSON converts JSON configuration from raw bytes into a
// ConfiguredJarList structure.
func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error {
diff --git a/android/testing.go b/android/testing.go
index 191cb8d..b36f62c 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -713,9 +713,11 @@
func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
var searchedRules []string
- for _, p := range b.provider.BuildParamsForTests() {
- searchedRules = append(searchedRules, p.Rule.String())
- if strings.Contains(p.Rule.String(), rule) {
+ buildParams := b.provider.BuildParamsForTests()
+ for _, p := range buildParams {
+ ruleAsString := p.Rule.String()
+ searchedRules = append(searchedRules, ruleAsString)
+ if strings.Contains(ruleAsString, rule) {
return b.newTestingBuildParams(p), searchedRules
}
}
@@ -725,7 +727,7 @@
func (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams {
p, searchRules := b.maybeBuildParamsFromRule(rule)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find rule %q.\nall rules: %v", rule, searchRules))
+ panic(fmt.Errorf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n")))
}
return p
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8a71d4f..92e098c 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4546,7 +4546,7 @@
// prebuilt_apex module always depends on the prebuilt, and so it doesn't
// find the dex boot jar in it. We either need to disable the source libfoo
// or make the prebuilt libfoo preferred.
- testDexpreoptWithApexes(t, bp, "failed to find a dex jar path for module 'libfoo'", preparer)
+ testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer)
})
t.Run("prebuilt library preferred with source", func(t *testing.T) {
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index ce12f46..7297926 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -15,6 +15,8 @@
package apex
import (
+ "fmt"
+ "strings"
"testing"
"android/soong/android"
@@ -31,6 +33,139 @@
PrepareForTestWithApexBuildComponents,
)
+func TestPlatformBootclasspath_Fragments(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ prepareForTestWithMyapex,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("foo"),
+ java.FixtureConfigureBootJars("myapex:bar"),
+ android.FixtureWithRootAndroidBp(`
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {
+ apex: "myapex",
+ module:"bar-fragment",
+ },
+ ],
+ hidden_api: {
+ unsupported: [
+ "unsupported.txt",
+ ],
+ removed: [
+ "removed.txt",
+ ],
+ max_target_r_low_priority: [
+ "max-target-r-low-priority.txt",
+ ],
+ max_target_q: [
+ "max-target-q.txt",
+ ],
+ max_target_p: [
+ "max-target-p.txt",
+ ],
+ max_target_o_low_priority: [
+ "max-target-o-low-priority.txt",
+ ],
+ blocked: [
+ "blocked.txt",
+ ],
+ unsupported_packages: [
+ "unsupported-packages.txt",
+ ],
+ },
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: [
+ "bar-fragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "bar-fragment",
+ contents: ["bar"],
+ apex_available: ["myapex"],
+ api: {
+ stub_libs: ["foo"],
+ },
+ hidden_api: {
+ unsupported: [
+ "bar-unsupported.txt",
+ ],
+ removed: [
+ "bar-removed.txt",
+ ],
+ max_target_r_low_priority: [
+ "bar-max-target-r-low-priority.txt",
+ ],
+ max_target_q: [
+ "bar-max-target-q.txt",
+ ],
+ max_target_p: [
+ "bar-max-target-p.txt",
+ ],
+ max_target_o_low_priority: [
+ "bar-max-target-o-low-priority.txt",
+ ],
+ blocked: [
+ "bar-blocked.txt",
+ ],
+ unsupported_packages: [
+ "bar-unsupported-packages.txt",
+ ],
+ },
+ }
+
+ java_library {
+ name: "bar",
+ apex_available: ["myapex"],
+ srcs: ["a.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ permitted_packages: ["bar"],
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ },
+ compile_dex: true,
+ }
+ `),
+ ).RunTest(t)
+
+ pbcp := result.Module("platform-bootclasspath", "android_common")
+ info := result.ModuleProvider(pbcp, java.MonolithicHiddenAPIInfoProvider).(java.MonolithicHiddenAPIInfo)
+
+ for _, category := range java.HiddenAPIFlagFileCategories {
+ name := category.PropertyName
+ message := fmt.Sprintf("category %s", name)
+ filename := strings.ReplaceAll(name, "_", "-")
+ expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
+ android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
+ }
+
+ android.AssertPathsRelativeToTopEquals(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths)
+ android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
+ android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
+ android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/index.csv"}, info.IndexPaths)
+ android.AssertPathsRelativeToTopEquals(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/all-flags.csv"}, info.AllFlagsPaths)
+}
+
func TestPlatformBootclasspathDependencies(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 1c7ad78..10d2fe2 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -648,7 +648,8 @@
}
// Copy the dex jars of this fragment's content modules to their predefined locations.
- copyBootJarsToPredefinedLocations(ctx, contents, imageConfig.modules, imageConfig.dexPaths)
+ bootDexJarByModule := extractEncodedDexJarsFromModules(ctx, contents)
+ copyBootJarsToPredefinedLocations(ctx, bootDexJarByModule, imageConfig.dexPathsByModule)
// Build a profile for the image config and then use that to build the boot image.
profile := bootImageProfileRule(ctx, imageConfig)
@@ -763,7 +764,7 @@
// Copy manually curated flag files specified on the bootclasspath_fragment.
if b.Flag_files_by_category != nil {
- for _, category := range hiddenAPIFlagFileCategories {
+ for _, category := range HiddenAPIFlagFileCategories {
paths := b.Flag_files_by_category[category]
if len(paths) > 0 {
dests := []string{}
@@ -772,7 +773,7 @@
builder.CopyToSnapshot(p, dest)
dests = append(dests, dest)
}
- hiddenAPISet.AddProperty(category.propertyName, dests)
+ hiddenAPISet.AddProperty(category.PropertyName, dests)
}
}
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index e1a3650..dc8df5e 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -15,7 +15,6 @@
package java
import (
- "fmt"
"path/filepath"
"sort"
"strings"
@@ -254,6 +253,9 @@
dexPaths android.WritablePaths // for this image
dexPathsDeps android.WritablePaths // for the dependency images and in this image
+ // Map from module name (without prebuilt_ prefix) to the predefined build path.
+ dexPathsByModule map[string]android.WritablePath
+
// File path to a zip archive with all image files (or nil, if not needed).
zip android.WritablePath
@@ -276,13 +278,24 @@
dexLocationsDeps []string // for the dependency images and in this image
// Paths to image files.
- imagePathOnHost android.OutputPath // first image file path on host
- imagePathOnDevice string // first image file path on device
- imagesDeps android.OutputPaths // all files
+ imagePathOnHost android.OutputPath // first image file path on host
+ imagePathOnDevice string // first image file path on device
- // Only for extensions, paths to the primary boot images.
+ // All the files that constitute this image variant, i.e. .art, .oat and .vdex files.
+ imagesDeps android.OutputPaths
+
+ // The path to the primary image variant's imagePathOnHost field, where primary image variant
+ // means the image variant that this extends.
+ //
+ // This is only set for a variant of an image that extends another image.
primaryImages android.OutputPath
+ // The paths to the primary image variant's imagesDeps field, where primary image variant
+ // means the image variant that this extends.
+ //
+ // This is only set for a variant of an image that extends another image.
+ primaryImagesDeps android.Paths
+
// Rules which should be used in make to install the outputs.
installs android.RuleBuilderInstalls
vdexInstalls android.RuleBuilderInstalls
@@ -450,53 +463,27 @@
return true
}
-// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to
-// predefined paths in the global config.
-func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, bootModules []android.Module, bootjars android.ConfiguredJarList, jarPathsPredefined android.WritablePaths) {
- jarPaths := make(android.Paths, bootjars.Len())
- for i, module := range bootModules {
- if module != nil {
- bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath()
- jarPaths[i] = bootDexJar
+// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined
+// paths in the global config.
+func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) {
+ // Create the super set of module names.
+ names := []string{}
+ names = append(names, android.SortedStringKeys(srcBootDexJarsByModule)...)
+ names = append(names, android.SortedStringKeys(dstBootJarsByModule)...)
+ names = android.SortedUniqueStrings(names)
+ for _, name := range names {
+ src := srcBootDexJarsByModule[name]
+ dst := dstBootJarsByModule[name]
- name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(module))
- if bootjars.Jar(i) != name {
- ctx.ModuleErrorf("expected module %s at position %d but found %s", bootjars.Jar(i), i, name)
- }
- }
- }
-
- // The paths to bootclasspath DEX files need to be known at module GenerateAndroidBuildAction
- // time, before the boot images are built (these paths are used in dexpreopt rule generation for
- // Java libraries and apps). Generate rules that copy bootclasspath DEX jars to the predefined
- // paths.
- for i := range jarPaths {
- input := jarPaths[i]
- output := jarPathsPredefined[i]
- module := bootjars.Jar(i)
- if input == nil {
- if ctx.Config().AllowMissingDependencies() {
- apex := bootjars.Apex(i)
-
- // Create an error rule that pretends to create the output file but will actually fail if it
- // is run.
- ctx.Build(pctx, android.BuildParams{
- Rule: android.ErrorRule,
- Output: output,
- Args: map[string]string{
- "error": fmt.Sprintf("missing dependencies: dex jar for %s:%s", module, apex),
- },
- })
- } else {
- ctx.ModuleErrorf("failed to find a dex jar path for module '%s'"+
- ", note that some jars may be filtered out by module constraints", module)
- }
-
+ if src == nil {
+ ctx.ModuleErrorf("module %s does not provide a dex boot jar", name)
+ } else if dst == nil {
+ ctx.ModuleErrorf("module %s is not part of the boot configuration", name)
} else {
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
- Input: input,
- Output: output,
+ Input: src,
+ Output: dst,
})
}
}
@@ -588,7 +575,15 @@
cmd.
Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":").
- FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage)
+ // Add the path to the first file in the boot image with the arch specific directory removed,
+ // dex2oat will reconstruct the path to the actual file when it needs it. As the actual path
+ // to the file cannot be passed to the command make sure to add the actual path as an Implicit
+ // dependency to ensure that it is built before the command runs.
+ FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage).
+ // Similarly, the dex2oat tool will automatically find the paths to other files in the base
+ // boot image so make sure to add them as implicit dependencies to ensure that they are built
+ // before this command is run.
+ Implicits(image.primaryImagesDeps)
} else {
// It is a primary image, so it needs a base address.
cmd.FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress())
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 39a3e11..b13955f 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -100,6 +100,7 @@
// TODO(b/143682396): use module dependencies instead
inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input")
c.dexPaths = c.modules.BuildPaths(ctx, inputDir)
+ c.dexPathsByModule = c.modules.BuildPathsByModule(ctx, inputDir)
c.dexPathsDeps = c.dexPaths
// Create target-specific variants.
@@ -125,6 +126,7 @@
frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
for i := range targets {
frameworkCfg.variants[i].primaryImages = artCfg.variants[i].imagePathOnHost
+ frameworkCfg.variants[i].primaryImagesDeps = artCfg.variants[i].imagesDeps.Paths()
frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...)
}
@@ -152,6 +154,9 @@
// later on a singleton adds commands to copy actual jars to the predefined paths.
dexPaths android.WritablePaths
+ // Map from module name (without prebuilt_ prefix) to the predefined build path.
+ dexPathsByModule map[string]android.WritablePath
+
// A list of dex locations (a.k.a. on-device paths) to the boot jars.
dexLocations []string
}
@@ -165,10 +170,11 @@
dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "updatable_bootjars")
dexPaths := updatableBootJars.BuildPaths(ctx, dir)
+ dexPathsByModuleName := updatableBootJars.BuildPathsByModule(ctx, dir)
dexLocations := updatableBootJars.DevicePaths(ctx.Config(), android.Android)
- return updatableBootConfig{updatableBootJars, dexPaths, dexLocations}
+ return updatableBootConfig{updatableBootJars, dexPaths, dexPathsByModuleName, dexLocations}
}).(updatableBootConfig)
}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index e9693c6..f901434 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -219,7 +219,6 @@
BuiltTool("merge_csv").
Flag("--zip_input").
Flag("--key_field signature").
- FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties").
FlagWithOutput("--output=", indexCSV).
Inputs(classesJars)
rule.Build(desc, desc)
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index f2649d3..5600645 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -248,8 +248,8 @@
}
type hiddenAPIFlagFileCategory struct {
- // propertyName is the name of the property for this category.
- propertyName string
+ // PropertyName is the name of the property for this category.
+ PropertyName string
// propertyValueReader retrieves the value of the property for this category from the set of
// properties.
@@ -262,12 +262,12 @@
// The flag file category for removed members of the API.
//
-// This is extracted from hiddenAPIFlagFileCategories as it is needed to add the dex signatures
+// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
// list of removed API members that are generated automatically from the removed.txt files provided
// by API stubs.
var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Removed
- propertyName: "removed",
+ PropertyName: "removed",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Removed
},
@@ -276,10 +276,10 @@
},
}
-var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
+var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Unsupported
{
- propertyName: "unsupported",
+ PropertyName: "unsupported",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Unsupported
},
@@ -290,7 +290,7 @@
hiddenAPIRemovedFlagFileCategory,
// See HiddenAPIFlagFileProperties.Max_target_r_low_priority
{
- propertyName: "max_target_r_low_priority",
+ PropertyName: "max_target_r_low_priority",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_r_low_priority
},
@@ -300,7 +300,7 @@
},
// See HiddenAPIFlagFileProperties.Max_target_q
{
- propertyName: "max_target_q",
+ PropertyName: "max_target_q",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_q
},
@@ -310,7 +310,7 @@
},
// See HiddenAPIFlagFileProperties.Max_target_p
{
- propertyName: "max_target_p",
+ PropertyName: "max_target_p",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_p
},
@@ -320,7 +320,7 @@
},
// See HiddenAPIFlagFileProperties.Max_target_o_low_priority
{
- propertyName: "max_target_o_low_priority",
+ PropertyName: "max_target_o_low_priority",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_o_low_priority
},
@@ -330,7 +330,7 @@
},
// See HiddenAPIFlagFileProperties.Blocked
{
- propertyName: "blocked",
+ PropertyName: "blocked",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Blocked
},
@@ -340,7 +340,7 @@
},
// See HiddenAPIFlagFileProperties.Unsupported_packages
{
- propertyName: "unsupported_packages",
+ PropertyName: "unsupported_packages",
propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Unsupported_packages
},
@@ -355,7 +355,7 @@
// append appends the supplied flags files to the corresponding category in this map.
func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
- for _, category := range hiddenAPIFlagFileCategories {
+ for _, category := range HiddenAPIFlagFileCategories {
s[category] = append(s[category], other[category]...)
}
}
@@ -540,7 +540,7 @@
// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
// supplied properties and stores them in this struct.
func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
- for _, category := range hiddenAPIFlagFileCategories {
+ for _, category := range HiddenAPIFlagFileCategories {
paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
i.FlagFilesByCategory[category] = paths
}
@@ -571,6 +571,15 @@
AllFlagsPath android.Path
}
+// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
+// path.
+type bootDexJarByModule map[string]android.Path
+
+// addPath adds the path for a module to the map.
+func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
+ b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
+}
+
// pathForValidation creates a path of the same type as the supplied type but with a name of
// <path>.valid.
//
@@ -630,7 +639,7 @@
FlagWithOutput("--output ", tempPath)
// Add the options for the different categories of flag files.
- for _, category := range hiddenAPIFlagFileCategories {
+ for _, category := range HiddenAPIFlagFileCategories {
paths := flagFilesByCategory[category]
for _, path := range paths {
category.commandMutator(command, path)
@@ -759,7 +768,7 @@
bootDexJar := module.bootDexJar()
if bootDexJar == nil {
if ctx.Config().AlwaysUsePrebuiltSdks() {
- // TODO(b/179354495): Remove this work around when it is unnecessary.
+ // TODO(b/179354495): Remove this workaround when it is unnecessary.
// Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
// create a fake one that will cause a build error only if it is used.
fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name())
@@ -792,3 +801,113 @@
}
return classesJars
}
+
+// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
+// Soong but should instead only be reported in ninja if the file is actually built.
+func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
+ // TODO(b/179354495): Remove this workaround when it is unnecessary.
+ // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
+ // create a fake one that will cause a build error only if it is used.
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
+ return true
+ }
+
+ // This is called for both platform_bootclasspath and bootclasspath_fragment modules.
+ //
+ // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
+ // Ideally, a bootclasspath_fragment module should never have a platform variant created for it
+ // but unfortunately, due to b/187910671 it does.
+ //
+ // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module
+ // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e.
+ // has an APEX variant not a platform variant.
+ //
+ // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot
+ // provide a boot dex jar:
+ // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it
+ // does not have an APEX variant and only has a platform variant and neither do its content
+ // modules.
+ // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all
+ // java_sdk_library_import modules to be treated as preferred and as many of them are not part
+ // of an apex they cannot provide a boot dex jar.
+ //
+ // The first case causes problems when the affected prebuilt modules are preferred but that is an
+ // invalid configuration and it is ok for it to fail as the work to enable that is not yet
+ // complete. The second case is used for building targets that do not use boot dex jars and so
+ // deferring error reporting to ninja is fine as the affected ninja targets should never be built.
+ // That is handled above.
+ //
+ // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike
+ // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it
+ // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed
+ // that if the library can be part of an APEX then it is the APEX variant that is used.
+ //
+ // This check handles the slightly different requirements of the bootclasspath_fragment and
+ // platform_bootclasspath modules by only deferring error reporting for the platform variant of
+ // a prebuilt modules that has other variants which are part of an APEX.
+ //
+ // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
+ if android.IsModulePrebuilt(module) {
+ if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
+ apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ if apexInfo.IsForPlatform() {
+ return true
+ }
+ }
+ }
+
+ // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
+ // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
+ // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
+ // failures missing boot dex jars need to be deferred.
+ if android.IsModuleInVersionedSdk(ctx.Module()) {
+ return true
+ }
+
+ return false
+}
+
+// handleMissingDexBootFile will either log a warning or create an error rule to create the fake
+// file depending on the value returned from deferReportingMissingBootDexJar.
+func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath) {
+ if deferReportingMissingBootDexJar(ctx, module) {
+ // Create an error rule that pretends to create the output file but will actually fail if it
+ // is run.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: fake,
+ Args: map[string]string{
+ "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
+ },
+ })
+ } else {
+ ctx.ModuleErrorf("module %s does not provide a dex jar", module)
+ }
+}
+
+// retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's
+// DexJarBuildPath() method.
+//
+// The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
+// However, under certain conditions, e.g. errors, or special build configurations it will return
+// a path to a fake file.
+func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
+ bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath()
+ if bootDexJar == nil {
+ fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
+ bootDexJar = fake
+
+ handleMissingDexBootFile(ctx, module, fake)
+ }
+ return bootDexJar
+}
+
+// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
+func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
+ encodedDexJarsByModuleName := bootDexJarByModule{}
+ for _, module := range contents {
+ path := retrieveEncodedBootDexJarFromModule(ctx, module)
+ encodedDexJarsByModuleName.addPath(module, path)
+ }
+ return encodedDexJarsByModuleName
+}
diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go
index a6bf8c7..edf4235 100644
--- a/java/hiddenapi_monolithic.go
+++ b/java/hiddenapi_monolithic.go
@@ -99,4 +99,4 @@
i.AllFlagsPaths = android.FirstUniquePaths(i.AllFlagsPaths)
}
-var monolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{})
+var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{})
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 87c695c..a4beb89 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -280,7 +280,6 @@
}
monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments)
-
// Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile
input := newHiddenAPIFlagInput()
@@ -342,7 +341,7 @@
monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, fragments)
// Store the information for testing.
- ctx.SetProvider(monolithicHiddenAPIInfoProvider, monolithicInfo)
+ ctx.SetProvider(MonolithicHiddenAPIInfoProvider, monolithicInfo)
return monolithicInfo
}
@@ -390,11 +389,13 @@
generateUpdatableBcpPackagesRule(ctx, imageConfig, updatableModules)
// Copy non-updatable module dex jars to their predefined locations.
- copyBootJarsToPredefinedLocations(ctx, nonUpdatableModules, imageConfig.modules, imageConfig.dexPaths)
+ nonUpdatableBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, nonUpdatableModules)
+ copyBootJarsToPredefinedLocations(ctx, nonUpdatableBootDexJarsByModule, imageConfig.dexPathsByModule)
// Copy updatable module dex jars to their predefined locations.
config := GetUpdatableBootConfig(ctx)
- copyBootJarsToPredefinedLocations(ctx, updatableModules, config.modules, config.dexPaths)
+ updatableBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, updatableModules)
+ copyBootJarsToPredefinedLocations(ctx, updatableBootDexJarsByModule, config.dexPathsByModule)
// Build a profile for the image config and then use that to build the boot image.
profile := bootImageProfileRule(ctx, imageConfig)
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index ed5549d..0318a07 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -15,8 +15,6 @@
package java
import (
- "fmt"
- "strings"
"testing"
"android/soong/android"
@@ -152,116 +150,6 @@
})
}
-func TestPlatformBootclasspath_Fragments(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForTestWithPlatformBootclasspath,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- android.FixtureWithRootAndroidBp(`
- platform_bootclasspath {
- name: "platform-bootclasspath",
- fragments: [
- {module:"bar-fragment"},
- ],
- hidden_api: {
- unsupported: [
- "unsupported.txt",
- ],
- removed: [
- "removed.txt",
- ],
- max_target_r_low_priority: [
- "max-target-r-low-priority.txt",
- ],
- max_target_q: [
- "max-target-q.txt",
- ],
- max_target_p: [
- "max-target-p.txt",
- ],
- max_target_o_low_priority: [
- "max-target-o-low-priority.txt",
- ],
- blocked: [
- "blocked.txt",
- ],
- unsupported_packages: [
- "unsupported-packages.txt",
- ],
- },
- }
-
- bootclasspath_fragment {
- name: "bar-fragment",
- contents: ["bar"],
- api: {
- stub_libs: ["foo"],
- },
- hidden_api: {
- unsupported: [
- "bar-unsupported.txt",
- ],
- removed: [
- "bar-removed.txt",
- ],
- max_target_r_low_priority: [
- "bar-max-target-r-low-priority.txt",
- ],
- max_target_q: [
- "bar-max-target-q.txt",
- ],
- max_target_p: [
- "bar-max-target-p.txt",
- ],
- max_target_o_low_priority: [
- "bar-max-target-o-low-priority.txt",
- ],
- blocked: [
- "bar-blocked.txt",
- ],
- unsupported_packages: [
- "bar-unsupported-packages.txt",
- ],
- },
- }
-
- java_library {
- name: "bar",
- srcs: ["a.java"],
- system_modules: "none",
- sdk_version: "none",
- compile_dex: true,
- }
-
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- public: {
- enabled: true,
- },
- compile_dex: true,
- }
- `),
- ).RunTest(t)
-
- pbcp := result.Module("platform-bootclasspath", "android_common")
- info := result.ModuleProvider(pbcp, monolithicHiddenAPIInfoProvider).(MonolithicHiddenAPIInfo)
-
- for _, category := range hiddenAPIFlagFileCategories {
- name := category.propertyName
- message := fmt.Sprintf("category %s", name)
- filename := strings.ReplaceAll(name, "_", "-")
- expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
- android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
- }
-
- android.AssertPathsRelativeToTopEquals(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths)
- android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
- android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
- android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/index.csv"}, info.IndexPaths)
- android.AssertPathsRelativeToTopEquals(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/all-flags.csv"}, info.AllFlagsPaths)
-}
-
func TestPlatformBootclasspathVariant(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
diff --git a/scripts/hiddenapi/merge_csv.py b/scripts/hiddenapi/merge_csv.py
index b047aab..a65326c 100755
--- a/scripts/hiddenapi/merge_csv.py
+++ b/scripts/hiddenapi/merge_csv.py
@@ -55,14 +55,15 @@
if entry.endswith('.uau'):
csv_readers.append(dict_reader(io.TextIOWrapper(zip.open(entry, 'r'))))
-headers = set()
if args.header:
fieldnames = args.header.split(',')
else:
+ headers = {}
# Build union of all columns from source files:
for reader in csv_readers:
- headers = headers.union(reader.fieldnames)
- fieldnames = sorted(headers)
+ for fieldname in reader.fieldnames:
+ headers[fieldname] = ""
+ fieldnames = list(headers.keys())
# By default chain the csv readers together so that the resulting output is
# the concatenation of the rows from each of them:
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index d9fe281..f2ab6a1 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -15,12 +15,53 @@
package sdk
import (
+ "fmt"
+ "path/filepath"
"testing"
"android/soong/android"
"android/soong/java"
)
+// fixtureAddPlatformBootclasspathForBootclasspathFragment adds a platform_bootclasspath module that
+// references the bootclasspath fragment.
+func fixtureAddPlatformBootclasspathForBootclasspathFragment(apex, fragment string) android.FixturePreparer {
+ return android.GroupFixturePreparers(
+ // Add a platform_bootclasspath module.
+ android.FixtureAddTextFile("frameworks/base/boot/Android.bp", fmt.Sprintf(`
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {
+ apex: "%s",
+ module: "%s",
+ },
+ ],
+ }
+ `, apex, fragment)),
+ android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil),
+ )
+}
+
+// fixtureAddPrebuiltApexForBootclasspathFragment adds a prebuilt_apex that exports the fragment.
+func fixtureAddPrebuiltApexForBootclasspathFragment(apex, fragment string) android.FixturePreparer {
+ apexFile := fmt.Sprintf("%s.apex", apex)
+ dir := "prebuilts/apex"
+ return android.GroupFixturePreparers(
+ // A preparer to add a prebuilt apex to the test fixture.
+ android.FixtureAddTextFile(filepath.Join(dir, "Android.bp"), fmt.Sprintf(`
+ prebuilt_apex {
+ name: "%s",
+ src: "%s",
+ exported_bootclasspath_fragments: [
+ "%s",
+ ],
+ }
+ `, apex, apexFile, fragment)),
+ android.FixtureAddFile(filepath.Join(dir, apexFile), nil),
+ )
+}
+
func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
@@ -34,20 +75,8 @@
"system/sepolicy/apex/com.android.art-file_contexts": nil,
}),
- // platform_bootclasspath that depends on the fragment.
- android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
- platform_bootclasspath {
- name: "platform-bootclasspath",
- fragments: [
- {
- apex: "com.android.art",
- module: "mybootclasspathfragment",
- },
- ],
- }
- `),
- // Needed for platform_bootclasspath
- android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil),
+ // Add a platform_bootclasspath that depends on the fragment.
+ fixtureAddPlatformBootclasspathForBootclasspathFragment("com.android.art", "mybootclasspathfragment"),
java.FixtureConfigureBootJars("com.android.art:mybootlib"),
android.FixtureWithRootAndroidBp(`
@@ -89,19 +118,8 @@
`),
).RunTest(t)
- // A preparer to add a prebuilt apex to the test fixture.
- prepareWithPrebuiltApex := android.GroupFixturePreparers(
- android.FixtureAddTextFile("prebuilts/apex/Android.bp", `
- prebuilt_apex {
- name: "com.android.art",
- src: "art.apex",
- exported_bootclasspath_fragments: [
- "mybootclasspathfragment",
- ],
- }
- `),
- android.FixtureAddFile("prebuilts/apex/art.apex", nil),
- )
+ // A preparer to update the test fixture used when processing an unpackage snapshot.
+ preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "mybootclasspathfragment")
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
@@ -154,9 +172,9 @@
checkAllCopyRules(`
.intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
`),
- snapshotTestPreparer(checkSnapshotWithoutSource, prepareWithPrebuiltApex),
- snapshotTestPreparer(checkSnapshotWithSourcePreferred, prepareWithPrebuiltApex),
- snapshotTestPreparer(checkSnapshotPreferredWithSource, prepareWithPrebuiltApex),
+ snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
)
}
@@ -166,6 +184,12 @@
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
+ java.FixtureConfigureUpdatableBootJars("myapex:mybootlib", "myapex:myothersdklibrary"),
+ prepareForSdkTestWithApex,
+
+ // Add a platform_bootclasspath that depends on the fragment.
+ fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
+
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
@@ -179,8 +203,16 @@
],
}
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "2",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ }
+
bootclasspath_fragment {
name: "mybootclasspathfragment",
+ apex_available: ["myapex"],
contents: [
// This should be automatically added to the sdk_snapshot as a java_boot_libs module.
"mybootlib",
@@ -198,35 +230,48 @@
java_library {
name: "mybootlib",
+ apex_available: ["myapex"],
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
+ min_sdk_version: "2",
compile_dex: true,
+ permitted_packages: ["mybootlib"],
}
java_sdk_library {
name: "mysdklibrary",
+ apex_available: ["myapex"],
srcs: ["Test.java"],
shared_library: false,
public: {enabled: true},
+ min_sdk_version: "2",
}
java_sdk_library {
name: "myothersdklibrary",
+ apex_available: ["myapex"],
srcs: ["Test.java"],
shared_library: false,
public: {enabled: true},
+ min_sdk_version: "2",
+ permitted_packages: ["myothersdklibrary"],
}
java_sdk_library {
name: "mycoreplatform",
+ apex_available: ["myapex"],
srcs: ["Test.java"],
shared_library: false,
public: {enabled: true},
+ min_sdk_version: "2",
}
`),
).RunTest(t)
+ // A preparer to update the test fixture used when processing an unpackage snapshot.
+ preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("myapex", "mybootclasspathfragment")
+
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -235,7 +280,7 @@
name: "mybootclasspathfragment",
prefer: false,
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
contents: [
"mybootlib",
"myothersdklibrary",
@@ -259,7 +304,7 @@
name: "mybootlib",
prefer: false,
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
jars: ["java/mybootlib.jar"],
}
@@ -267,7 +312,7 @@
name: "myothersdklibrary",
prefer: false,
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
@@ -282,7 +327,7 @@
name: "mysdklibrary",
prefer: false,
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
@@ -297,7 +342,7 @@
name: "mycoreplatform",
prefer: false,
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
@@ -315,7 +360,7 @@
name: "mysdk_mybootclasspathfragment@current",
sdk_member_name: "mybootclasspathfragment",
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
contents: [
"mysdk_mybootlib@current",
"mysdk_myothersdklibrary@current",
@@ -339,7 +384,7 @@
name: "mysdk_mybootlib@current",
sdk_member_name: "mybootlib",
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
jars: ["java/mybootlib.jar"],
}
@@ -347,7 +392,7 @@
name: "mysdk_myothersdklibrary@current",
sdk_member_name: "myothersdklibrary",
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
@@ -362,7 +407,7 @@
name: "mysdk_mysdklibrary@current",
sdk_member_name: "mysdklibrary",
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
@@ -377,7 +422,7 @@
name: "mysdk_mycoreplatform@current",
sdk_member_name: "mycoreplatform",
visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
+ apex_available: ["myapex"],
shared_library: false,
public: {
jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
@@ -416,7 +461,11 @@
.intermediates/mycoreplatform.stubs/android_common/javac/mycoreplatform.stubs.jar -> sdk_library/public/mycoreplatform-stubs.jar
.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
-`))
+`),
+ snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
+ )
}
// Test that bootclasspath_fragment works with sdk.
@@ -482,7 +531,12 @@
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("mysdklibrary"),
+ java.FixtureConfigureUpdatableBootJars("myapex:mybootlib"),
prepareForSdkTestWithApex,
+
+ // Add a platform_bootclasspath that depends on the fragment.
+ fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
+
android.MockFS{
"my-blocked.txt": nil,
"my-max-target-o-low-priority.txt": nil,
@@ -549,6 +603,7 @@
sdk_version: "none",
min_sdk_version: "1",
compile_dex: true,
+ permitted_packages: ["mybootlib"],
}
java_sdk_library {
@@ -560,6 +615,9 @@
`),
).RunTest(t)
+ // A preparer to update the test fixture used when processing an unpackage snapshot.
+ preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("myapex", "mybootclasspathfragment")
+
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -633,5 +691,8 @@
.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
`),
+ snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
)
}