Merge "cc/linker.go: check min_sdk_version."
diff --git a/android/arch.go b/android/arch.go
index c1b2c33..bb1b613 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1025,7 +1025,7 @@
}
// Merges the property struct in srcValue into dst.
-func mergePropertyStruct(ctx BaseMutatorContext, dst interface{}, srcValue reflect.Value) {
+func mergePropertyStruct(ctx ArchVariantContext, dst interface{}, srcValue reflect.Value) {
src := maybeBlueprintEmbed(srcValue).Interface()
// order checks the `android:"variant_prepend"` tag to handle properties where the
@@ -1054,7 +1054,7 @@
// Returns the immediate child of the input property struct that corresponds to
// the sub-property "field".
-func getChildPropertyStruct(ctx BaseMutatorContext,
+func getChildPropertyStruct(ctx ArchVariantContext,
src reflect.Value, field, userFriendlyField string) reflect.Value {
// Step into non-nil pointers to structs in the src value.
@@ -1186,7 +1186,7 @@
// },
// This struct will also contain sub-structs containing to the architecture/CPU
// variants and features that themselves contain properties specific to those.
-func getArchTypeStruct(ctx BaseMutatorContext, archProperties interface{}, archType ArchType) reflect.Value {
+func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) reflect.Value {
archPropValues := reflect.ValueOf(archProperties).Elem()
archProp := archPropValues.FieldByName("Arch").Elem()
prefix := "arch." + archType.Name
@@ -1201,7 +1201,7 @@
// key: value,
// },
// },
-func getMultilibStruct(ctx BaseMutatorContext, archProperties interface{}, archType ArchType) reflect.Value {
+func getMultilibStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) reflect.Value {
archPropValues := reflect.ValueOf(archProperties).Elem()
multilibProp := archPropValues.FieldByName("Multilib").Elem()
multilibProperties := getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib)
@@ -1851,6 +1851,12 @@
return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
}
+// ArchVariantContext defines the limited context necessary to retrieve arch_variant properties.
+type ArchVariantContext interface {
+ ModuleErrorf(fmt string, args ...interface{})
+ PropertyErrorf(property, fmt string, args ...interface{})
+}
+
// GetArchProperties returns a map of architectures to the values of the
// properties of the 'propertySet' struct that are specific to that architecture.
//
@@ -1863,7 +1869,7 @@
// For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }`
// will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given
// propertyset contains `Foo []string`.
-func (m *ModuleBase) GetArchProperties(ctx BaseMutatorContext, propertySet interface{}) map[ArchType]interface{} {
+func (m *ModuleBase) GetArchProperties(ctx ArchVariantContext, propertySet interface{}) map[ArchType]interface{} {
// Return value of the arch types to the prop values for that arch.
archToProp := map[ArchType]interface{}{}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 922e40a..68182a7 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4542,7 +4542,12 @@
}
func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
- preparer := java.FixtureConfigureBootJars("myapex:libfoo", "myapex:libbar")
+ preparer := android.GroupFixturePreparers(
+ java.FixtureConfigureBootJars("myapex:libfoo", "myapex:libbar"),
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+ )
checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
t.Helper()
@@ -4564,7 +4569,7 @@
checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedInputs string) {
t.Helper()
platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
- indexRule := platformBootclasspath.Rule("platform-bootclasspath-monolithic-hiddenapi-index")
+ indexRule := platformBootclasspath.Rule("monolithic_hidden_API_index")
java.CheckHiddenAPIRuleInputs(t, expectedInputs, indexRule)
}
@@ -4602,10 +4607,10 @@
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
- // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+ // Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
`)
})
@@ -4636,10 +4641,10 @@
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
- // Make sure that the dex file from the apex_set contributes to the hiddenapi index file.
+ // Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
`)
})
@@ -4743,10 +4748,10 @@
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
- // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+ // Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/prebuilt_libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/prebuilt_libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
`)
})
@@ -4810,10 +4815,10 @@
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
- // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+ // Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/libfoo/android_common_apex10000/hiddenapi/index.csv
+.intermediates/libbar/android_common_myapex/javac/libbar.jar
+.intermediates/libfoo/android_common_apex10000/javac/libfoo.jar
`)
})
@@ -4879,10 +4884,10 @@
checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
- // Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+ // Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/prebuilt_libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/prebuilt_libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
`)
})
}
diff --git a/cc/builder.go b/cc/builder.go
index 29cde9d..51c8a0b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -804,6 +804,7 @@
ImplicitOutputs: implicitOutputs,
Inputs: objFiles,
Implicits: deps,
+ OrderOnly: sharedLibs,
Args: args,
})
}
diff --git a/cc/cc.go b/cc/cc.go
index c5552d6..a0ad0d6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3230,6 +3230,9 @@
return false
}
}
+ if cc.IsLlndk() {
+ return false
+ }
if isLibDepTag && c.static() && libDepTag.shared() {
// shared_lib dependency from a static lib is considered as crossing
// the APEX boundary because the dependency doesn't actually is
diff --git a/cc/library.go b/cc/library.go
index c5ff9b1..1ba3597 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1426,11 +1426,10 @@
}
}
-func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path {
+func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) (timestamp android.Path, installPaths android.WritablePaths) {
srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
- var installPaths []android.WritablePath
for _, header := range srcFiles {
headerDir := filepath.Dir(header.String())
relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir)
@@ -1443,7 +1442,7 @@
installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base()))
}
- return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths)
+ return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths), installPaths
}
// link registers actions to link this library, and sets various fields
@@ -1459,7 +1458,9 @@
var timestampFiles android.Paths
for _, dir := range library.Properties.Llndk.Export_preprocessed_headers {
- timestampFiles = append(timestampFiles, processLLNDKHeaders(ctx, dir, genHeaderOutDir))
+ timestampFile, installPaths := processLLNDKHeaders(ctx, dir, genHeaderOutDir)
+ timestampFiles = append(timestampFiles, timestampFile)
+ library.addExportedGeneratedHeaders(installPaths.Paths()...)
}
if Bool(library.Properties.Llndk.Export_headers_as_system) {
diff --git a/cc/test.go b/cc/test.go
index d4c23d7..047a69e 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -48,12 +48,19 @@
Unit_test *bool
// Add ShippingApiLevelModuleController to auto generated test config. If the device properties
- // for the shipping api level is less than the test_min_api_level, skip this module.
- Test_min_api_level *int64
+ // for the shipping api level is less than the min_shipping_api_level, skip this module.
+ Min_shipping_api_level *int64
+
+ // Add ShippingApiLevelModuleController to auto generated test config. If any of the device
+ // shipping api level and vendor api level properties are less than the
+ // vsr_min_shipping_api_level, skip this module.
+ // As this includes the shipping api level check, it is not allowed to define
+ // min_shipping_api_level at the same time with this property.
+ Vsr_min_shipping_api_level *int64
// Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an
- // integer value and the value is less than the test_min_vndk_version, skip this module.
- Test_min_vndk_version *int64
+ // integer value and the value is less than the min_vndk_version, skip this module.
+ Min_vndk_version *int64
}
type TestBinaryProperties struct {
@@ -97,7 +104,7 @@
// Add ShippingApiLevelModuleController to auto generated test config. If the device properties
// for the shipping api level is less than the test_min_api_level, skip this module.
- // Deprecated (b/187258404). Use test_options.test_min_api_level instead.
+ // Deprecated (b/187258404). Use test_options.min_shipping_api_level instead.
Test_min_api_level *int64
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
@@ -404,19 +411,30 @@
for _, tag := range test.Properties.Test_options.Test_suite_tag {
configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
}
- if test.Properties.Test_options.Test_min_api_level != nil {
+ if test.Properties.Test_options.Min_shipping_api_level != nil {
+ if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
+ ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
+ }
var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Test_min_api_level), 10)})
+ options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
} else if test.Properties.Test_min_api_level != nil {
// TODO: (b/187258404) Remove test.Properties.Test_min_api_level
+ if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
+ ctx.PropertyErrorf("test_min_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
+ }
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
}
- if test.Properties.Test_options.Test_min_vndk_version != nil {
+ if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Test_min_vndk_version), 10)})
+ options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Vsr_min_shipping_api_level), 10)})
+ configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
+ }
+ if test.Properties.Test_options.Min_vndk_version != nil {
+ var options []tradefed.Option
+ options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_vndk_version), 10)})
options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 1844bce..7e73bf7 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -130,9 +130,11 @@
ProvidesUsesLibrary string // library name (usually the same as module name)
ClassLoaderContexts ClassLoaderContextMap
- Archs []android.ArchType
- DexPreoptImagesDeps []android.OutputPaths
- DexPreoptImageLocationsOnHost []string // boot image location on host (file path without the arch subdirectory)
+ Archs []android.ArchType
+ DexPreoptImagesDeps []android.OutputPaths
+
+ DexPreoptImageLocationsOnHost []string // boot image location on host (file path without the arch subdirectory)
+ DexPreoptImageLocationsOnDevice []string // boot image location on device (file path without the arch subdirectory)
PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files
PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 9d9234f..da015a3 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -499,11 +499,16 @@
// PathToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art
func PathToLocation(path android.Path, arch android.ArchType) string {
- pathArch := filepath.Base(filepath.Dir(path.String()))
+ return PathStringToLocation(path.String(), arch)
+}
+
+// PathStringToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art
+func PathStringToLocation(path string, arch android.ArchType) string {
+ pathArch := filepath.Base(filepath.Dir(path))
if pathArch != arch.String() {
panic(fmt.Errorf("last directory in %q must be %q", path, arch.String()))
}
- return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
+ return filepath.Join(filepath.Dir(filepath.Dir(path)), filepath.Base(path))
}
func makefileMatch(pattern, s string) bool {
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index 32c4f84..7dbe74c 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -37,6 +37,12 @@
globalConfigPath = flag.String("global", "", "path to global configuration file")
moduleConfigPath = flag.String("module", "", "path to module configuration file")
outDir = flag.String("out_dir", "", "path to output directory")
+ // If uses_target_files is true, dexpreopt_gen will be running on extracted target_files.zip files.
+ // In this case, the tool replace output file path with $(basePath)/$(on-device file path).
+ // The flag is useful when running dex2oat on system image and vendor image which are built separately.
+ usesTargetFiles = flag.Bool("uses_target_files", false, "whether or not dexpreopt is running on target_files")
+ // basePath indicates the path where target_files.zip is extracted.
+ basePath = flag.String("base_path", ".", "base path where images and tools are extracted")
)
type builderContext struct {
@@ -134,32 +140,28 @@
}
}
}()
-
+ if *usesTargetFiles {
+ moduleConfig.ManifestPath = android.OptionalPath{}
+ prefix := "dex2oat_result"
+ moduleConfig.BuildPath = android.PathForOutput(ctx, filepath.Join(prefix, moduleConfig.DexLocation))
+ for i, location := range moduleConfig.PreoptBootClassPathDexLocations {
+ moduleConfig.PreoptBootClassPathDexFiles[i] = android.PathForSource(ctx, *basePath+location)
+ }
+ for i := range moduleConfig.ClassLoaderContexts {
+ for _, v := range moduleConfig.ClassLoaderContexts[i] {
+ v.Host = android.PathForSource(ctx, *basePath+v.Device)
+ }
+ }
+ moduleConfig.EnforceUsesLibraries = false
+ for i, location := range moduleConfig.DexPreoptImageLocationsOnDevice {
+ moduleConfig.DexPreoptImageLocationsOnHost[i] = *basePath + location
+ }
+ }
writeScripts(ctx, globalSoongConfig, globalConfig, moduleConfig, *dexpreoptScriptPath)
}
func writeScripts(ctx android.BuilderContext, globalSoong *dexpreopt.GlobalSoongConfig,
global *dexpreopt.GlobalConfig, module *dexpreopt.ModuleConfig, dexpreoptScriptPath string) {
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module)
- if err != nil {
- panic(err)
- }
-
- installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install")
-
- dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String())
- dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String())
-
- for _, install := range dexpreoptRule.Installs() {
- installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/"))
- dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
- dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
- }
- dexpreoptRule.Command().Tool(globalSoong.SoongZip).
- FlagWithArg("-o ", "$2").
- FlagWithArg("-C ", installDir.String()).
- FlagWithArg("-D ", installDir.String())
-
write := func(rule *android.RuleBuilder, file string) {
script := &bytes.Buffer{}
script.WriteString(scriptHeader)
@@ -195,6 +197,30 @@
panic(err)
}
}
+ dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module)
+ if err != nil {
+ panic(err)
+ }
+ // When usesTargetFiles is true, only odex/vdex files are necessary.
+ // So skip redunant processes(such as copying the result to the artifact path, and zipping, and so on.)
+ if *usesTargetFiles {
+ write(dexpreoptRule, dexpreoptScriptPath)
+ return
+ }
+ installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install")
+
+ dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String())
+ dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String())
+
+ for _, install := range dexpreoptRule.Installs() {
+ installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/"))
+ dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
+ dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
+ }
+ dexpreoptRule.Command().Tool(globalSoong.SoongZip).
+ FlagWithArg("-o ", "$2").
+ FlagWithArg("-C ", installDir.String()).
+ FlagWithArg("-D ", installDir.String())
// The written scripts will assume the input is $1 and the output is $2
if module.DexPath.String() != "$1" {
diff --git a/java/base.go b/java/base.go
index 19c85cd..03652be 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1177,8 +1177,14 @@
j.properties.Instrument = true
}
+ // enforce syntax check to jacoco filters for any build (http://b/183622051)
+ specs := j.jacocoModuleToZipCommand(ctx)
+ if ctx.Failed() {
+ return
+ }
+
if j.shouldInstrument(ctx) {
- outputFile = j.instrument(ctx, flags, outputFile, jarName)
+ outputFile = j.instrument(ctx, flags, outputFile, jarName, specs)
}
// merge implementation jar with resources if necessary
@@ -1217,9 +1223,11 @@
return
}
- // Hidden API CSV generation and dex encoding
- dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
- proptools.Bool(j.dexProperties.Uncompress_dex))
+ // Update hidden API paths.
+ j.hiddenAPIUpdatePaths(ctx, dexOutputFile, j.implementationJarFile)
+
+ // Encode hidden API flags in dex file.
+ dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
// merge dex jar with resources if necessary
if j.resourceJar != nil {
@@ -1390,9 +1398,7 @@
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string) android.OutputPath {
-
- specs := j.jacocoModuleToZipCommand(ctx)
+ classesJar android.Path, jarName string, specs string) android.OutputPath {
jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName).OutputPath
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 20421de..16aa5e2 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -61,8 +61,14 @@
}
// SdkMemberType causes dependencies added with this tag to be automatically added to the sdk as if
-// they were specified using java_boot_libs.
-func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
+// they were specified using java_boot_libs or java_sdk_libs.
+func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+ // If the module is a java_sdk_library then treat it as if it was specified in the java_sdk_libs
+ // property, otherwise treat if it was specified in the java_boot_libs property.
+ if javaSdkLibrarySdkMemberType.IsInstance(child) {
+ return javaSdkLibrarySdkMemberType
+ }
+
return javaBootLibsSdkMemberType
}
@@ -85,6 +91,9 @@
type BootclasspathFragmentCoverageAffectedProperties struct {
// The contents of this bootclasspath_fragment, could be either java_library, or java_sdk_library.
//
+ // A java_sdk_library specified here will also be treated as if it was specified on the stub_libs
+ // property.
+ //
// The order of this list matters as it is the order that is used in the bootclasspath.
Contents []string
@@ -114,6 +123,15 @@
properties bootclasspathFragmentProperties
}
+// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
+// bootclasspath fragment modules.
+type commonBootclasspathFragment interface {
+ // produceHiddenAPIAllFlagsFile produces the all-flags.csv and intermediate files.
+ //
+ // Updates the supplied flagFileInfo with the paths to the generated files set.
+ produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo)
+}
+
func bootclasspathFragmentFactory() android.Module {
m := &BootclasspathFragmentModule{}
m.AddProperties(&m.properties)
@@ -371,7 +389,7 @@
})
// Perform hidden API processing.
- b.generateHiddenAPIBuildActions(ctx)
+ b.generateHiddenAPIBuildActions(ctx, contents)
// Construct the boot image info from the config.
info := BootclasspathFragmentApexContentInfo{
@@ -431,19 +449,43 @@
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) {
- // Resolve the properties to paths.
- flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
-
- // Store the information for use by platform_bootclasspath.
- ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
+func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module) {
// Convert the kind specific lists of modules into kind specific lists of jars.
- stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx)
+ stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx, contents)
// Store the information for use by other modules.
bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind}
ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo)
+
+ // Resolve the properties to paths.
+ flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
+
+ hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, contents)
+
+ // Delegate the production of the hidden API all flags file to a module type specific method.
+ common := ctx.Module().(commonBootclasspathFragment)
+ common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, stubJarsByKind, &flagFileInfo)
+
+ // Store the information for use by platform_bootclasspath.
+ ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
+}
+
+// produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files)
+// for the fragment.
+func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
+ // If no stubs have been provided then don't perform hidden API processing. This is a temporary
+ // workaround to avoid existing bootclasspath_fragments that do not provide stubs breaking the
+ // build.
+ // TODO(b/179354495): Remove this workaround.
+ if len(stubJarsByKind) == 0 {
+ // Nothing to do.
+ return
+ }
+
+ // Generate the rules to create the hidden API flags and update the supplied flagFileInfo with the
+ // paths to the created files.
+ hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, stubJarsByKind, flagFileInfo)
}
// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
@@ -524,6 +566,32 @@
// Flag files by *hiddenAPIFlagFileCategory
Flag_files_by_category map[*hiddenAPIFlagFileCategory]android.Paths
+
+ // The path to the generated stub-flags.csv file.
+ Stub_flags_path android.OptionalPath
+
+ // The path to the generated annotation-flags.csv file.
+ Annotation_flags_path android.OptionalPath
+
+ // The path to the generated metadata.csv file.
+ Metadata_path android.OptionalPath
+
+ // The path to the generated index.csv file.
+ Index_path android.OptionalPath
+
+ // The path to the generated all-flags.csv file.
+ All_flags_path android.OptionalPath
+}
+
+func pathsToOptionalPath(paths android.Paths) android.OptionalPath {
+ switch len(paths) {
+ case 0:
+ return android.OptionalPath{}
+ case 1:
+ return android.OptionalPathForPath(paths[0])
+ default:
+ panic(fmt.Errorf("expected 0 or 1 paths, found %q", paths))
+ }
}
func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -537,6 +605,13 @@
flagFileInfo := mctx.OtherModuleProvider(module, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo)
b.Flag_files_by_category = flagFileInfo.categoryToPaths
+ // Copy all the generated file paths.
+ b.Stub_flags_path = pathsToOptionalPath(flagFileInfo.StubFlagsPaths)
+ b.Annotation_flags_path = pathsToOptionalPath(flagFileInfo.AnnotationFlagsPaths)
+ b.Metadata_path = pathsToOptionalPath(flagFileInfo.MetadataPaths)
+ b.Index_path = pathsToOptionalPath(flagFileInfo.IndexPaths)
+ b.All_flags_path = pathsToOptionalPath(flagFileInfo.AllFlagsPaths)
+
// Copy stub_libs properties.
b.Stub_libs = module.properties.Api.Stub_libs
b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs
@@ -563,14 +638,17 @@
corePlatformApiPropertySet.AddPropertyWithTag("stub_libs", b.Core_platform_stub_libs, requiredMemberDependency)
}
+ hiddenAPISet := propertySet.AddPropertySet("hidden_api")
+ hiddenAPIDir := "hiddenapi"
+
+ // Copy manually curated flag files specified on the bootclasspath_fragment.
if b.Flag_files_by_category != nil {
- hiddenAPISet := propertySet.AddPropertySet("hidden_api")
for _, category := range hiddenAPIFlagFileCategories {
paths := b.Flag_files_by_category[category]
if len(paths) > 0 {
dests := []string{}
for _, p := range paths {
- dest := filepath.Join("hiddenapi", p.Base())
+ dest := filepath.Join(hiddenAPIDir, p.Base())
builder.CopyToSnapshot(p, dest)
dests = append(dests, dest)
}
@@ -578,10 +656,47 @@
}
}
}
+
+ copyOptionalPath := func(path android.OptionalPath, property string) {
+ if path.Valid() {
+ p := path.Path()
+ dest := filepath.Join(hiddenAPIDir, p.Base())
+ builder.CopyToSnapshot(p, dest)
+ hiddenAPISet.AddProperty(property, dest)
+ }
+ }
+
+ // Copy all the generated files, if available.
+ copyOptionalPath(b.Stub_flags_path, "stub_flags")
+ copyOptionalPath(b.Annotation_flags_path, "annotation_flags")
+ copyOptionalPath(b.Metadata_path, "metadata")
+ copyOptionalPath(b.Index_path, "index")
+ copyOptionalPath(b.All_flags_path, "all_flags")
}
var _ android.SdkMemberType = (*bootclasspathFragmentMemberType)(nil)
+// prebuiltBootclasspathFragmentProperties contains additional prebuilt_bootclasspath_fragment
+// specific properties.
+type prebuiltBootclasspathFragmentProperties struct {
+ Hidden_api struct {
+ // The path to the stub-flags.csv file created by the bootclasspath_fragment.
+ Stub_flags *string `android:"path"`
+
+ // The path to the annotation-flags.csv file created by the bootclasspath_fragment.
+ Annotation_flags *string `android:"path"`
+
+ // The path to the metadata.csv file created by the bootclasspath_fragment.
+ Metadata *string `android:"path"`
+
+ // The path to the index.csv file created by the bootclasspath_fragment.
+ Index *string `android:"path"`
+
+ // The path to the all-flags.csv file created by the bootclasspath_fragment.
+ All_flags *string `android:"path"`
+ }
+}
+
// A prebuilt version of the bootclasspath_fragment module.
//
// At the moment this is basically just a bootclasspath_fragment module that can be used as a
@@ -590,6 +705,9 @@
type prebuiltBootclasspathFragmentModule struct {
BootclasspathFragmentModule
prebuilt android.Prebuilt
+
+ // Additional prebuilt specific properties.
+ prebuiltProperties prebuiltBootclasspathFragmentProperties
}
func (module *prebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt {
@@ -600,9 +718,29 @@
return module.prebuilt.Name(module.ModuleBase.Name())
}
+// produceHiddenAPIAllFlagsFile returns a path to the prebuilt all-flags.csv or nil if none is
+// specified.
+func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
+ pathsForOptionalSrc := func(src *string) android.Paths {
+ if src == nil {
+ // TODO(b/179354495): Fail if this is not provided once prebuilts have been updated.
+ return nil
+ }
+ return android.Paths{android.PathForModuleSrc(ctx, *src)}
+ }
+
+ flagFileInfo.StubFlagsPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags)
+ flagFileInfo.AnnotationFlagsPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Annotation_flags)
+ flagFileInfo.MetadataPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Metadata)
+ flagFileInfo.IndexPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Index)
+ flagFileInfo.AllFlagsPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags)
+}
+
+var _ commonBootclasspathFragment = (*prebuiltBootclasspathFragmentModule)(nil)
+
func prebuiltBootclasspathFragmentFactory() android.Module {
m := &prebuiltBootclasspathFragmentModule{}
- m.AddProperties(&m.properties)
+ m.AddProperties(&m.properties, &m.prebuiltProperties)
// This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
// array.
android.InitPrebuiltModule(m, &[]string{"placeholder"})
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 32ed7ea..db284c9 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -204,7 +204,7 @@
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("mysdklibrary", "mycoreplatform"),
+ FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
).RunTestWithBp(t, `
bootclasspath_fragment {
name: "myfragment",
@@ -212,7 +212,7 @@
api: {
stub_libs: [
"mystublib",
- "mysdklibrary",
+ "myothersdklibrary",
],
},
core_platform_api: {
@@ -231,15 +231,22 @@
java_sdk_library {
name: "mysdklibrary",
srcs: ["a.java"],
- compile_dex: true,
+ shared_library: false,
public: {enabled: true},
system: {enabled: true},
}
java_sdk_library {
+ name: "myothersdklibrary",
+ srcs: ["a.java"],
+ shared_library: false,
+ public: {enabled: true},
+ }
+
+ java_sdk_library {
name: "mycoreplatform",
srcs: ["a.java"],
- compile_dex: true,
+ shared_library: false,
public: {enabled: true},
}
`)
@@ -249,16 +256,23 @@
stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
- // Check that SdkPublic uses public stubs.
+ // Stubs jars for mysdklibrary
publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
- android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{stubsJar, publicStubsJar}, info.stubJarsByKind[android.SdkPublic])
-
- // Check that SdkSystem uses system stubs.
systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
- android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkSystem])
- // Check that SdkTest also uses system stubs as the mysdklibrary does not provide test stubs.
- android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkTest])
+ // Stubs jars for myothersdklibrary
+ otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
+
+ // Check that SdkPublic uses public stubs for all sdk libraries.
+ android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.stubJarsByKind[android.SdkPublic])
+
+ // Check that SdkSystem uses system stubs for mysdklibrary and public stubs for myothersdklibrary
+ // as it does not provide system stubs.
+ android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.stubJarsByKind[android.SdkSystem])
+
+ // Check that SdkTest also uses system stubs for mysdklibrary as it does not provide test stubs
+ // and public stubs for myothersdklibrary as it does not provide test stubs either.
+ android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.stubJarsByKind[android.SdkTest])
// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 8d23ad6..2e46d74 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -184,7 +184,7 @@
imagesDeps = append(imagesDeps, variant.imagesDeps)
}
// The image locations for all Android variants are identical.
- hostImageLocations := bootImage.getAnyAndroidVariant().imageLocations()
+ hostImageLocations, deviceImageLocations := bootImage.getAnyAndroidVariant().imageLocations()
var profileClassListing android.OptionalPath
var profileBootListing android.OptionalPath
@@ -224,9 +224,10 @@
ProvidesUsesLibrary: providesUsesLib,
ClassLoaderContexts: d.classLoaderContexts,
- Archs: archs,
- DexPreoptImagesDeps: imagesDeps,
- DexPreoptImageLocationsOnHost: hostImageLocations,
+ Archs: archs,
+ DexPreoptImagesDeps: imagesDeps,
+ DexPreoptImageLocationsOnHost: hostImageLocations,
+ DexPreoptImageLocationsOnDevice: deviceImageLocations,
PreoptBootClassPathDexFiles: dexFiles.Paths(),
PreoptBootClassPathDexLocations: dexLocations,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 07715ab..be202c0 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -244,6 +244,9 @@
// Subdirectory where the image files are installed.
installDirOnHost string
+ // Subdirectory where the image files on device are installed.
+ installDirOnDevice string
+
// A list of (location, jar) pairs for the Java modules in this image.
modules android.ConfiguredJarList
@@ -273,8 +276,9 @@
dexLocationsDeps []string // for the dependency images and in this image
// Paths to image files.
- imagePathOnHost android.OutputPath // first image file
- imagesDeps android.OutputPaths // all files
+ imagePathOnHost android.OutputPath // first image file path on host
+ imagePathOnDevice string // first image file path on device
+ imagesDeps android.OutputPaths // all files
// Only for extensions, paths to the primary boot images.
primaryImages android.OutputPath
@@ -361,11 +365,12 @@
// The location is passed as an argument to the ART tools like dex2oat instead of the real path.
// ART tools will then reconstruct the architecture-specific real path.
//
-func (image *bootImageVariant) imageLocations() (imageLocations []string) {
+func (image *bootImageVariant) imageLocations() (imageLocationsOnHost []string, imageLocationsOnDevice []string) {
if image.extends != nil {
- imageLocations = image.extends.getVariant(image.target).imageLocations()
+ imageLocationsOnHost, imageLocationsOnDevice = image.extends.getVariant(image.target).imageLocations()
}
- return append(imageLocations, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType))
+ return append(imageLocationsOnHost, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType)),
+ append(imageLocationsOnDevice, dexpreopt.PathStringToLocation(image.imagePathOnDevice, image.target.Arch.ArchType))
}
func dexpreoptBootJarsFactory() android.SingletonModule {
@@ -796,12 +801,13 @@
// Create a rule to call oatdump.
output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
rule := android.NewRuleBuilder(pctx, ctx)
+ imageLocationsOnHost, _ := image.imageLocations()
rule.Command().
// TODO: for now, use the debug version for better error reporting
BuiltTool("oatdumpd").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
- FlagWithArg("--image=", strings.Join(image.imageLocations(), ":")).Implicits(image.imagesDeps.Paths()).
+ FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
rule.Build("dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
@@ -871,8 +877,8 @@
ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String())
ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String())
}
- imageLocations := current.getAnyAndroidVariant().imageLocations()
- ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocations, ":"))
+ imageLocationsOnHost, _ := current.getAnyAndroidVariant().imageLocations()
+ ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocationsOnHost, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 7fb0444..3724860 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -84,25 +84,28 @@
frameworkModules := global.BootJars.RemoveList(artModules)
artDirOnHost := "apex/art_boot_images/javalib"
+ artDirOnDevice := "apex/com.android.art/javalib"
frameworkSubdir := "system/framework"
// ART config for the primary boot image in the ART apex.
// It includes the Core Libraries.
artCfg := bootImageConfig{
- name: artBootImageName,
- stem: "boot",
- installDirOnHost: artDirOnHost,
- modules: artModules,
+ name: artBootImageName,
+ stem: "boot",
+ installDirOnHost: artDirOnHost,
+ installDirOnDevice: artDirOnDevice,
+ modules: artModules,
}
// Framework config for the boot image extension.
// It includes framework libraries and depends on the ART config.
frameworkCfg := bootImageConfig{
- extends: &artCfg,
- name: frameworkBootImageName,
- stem: "boot",
- installDirOnHost: frameworkSubdir,
- modules: frameworkModules,
+ extends: &artCfg,
+ name: frameworkBootImageName,
+ stem: "boot",
+ installDirOnHost: frameworkSubdir,
+ installDirOnDevice: frameworkSubdir,
+ modules: frameworkModules,
}
configs := map[string]*bootImageConfig{
@@ -131,11 +134,12 @@
arch := target.Arch.ArchType
imageDir := c.dir.Join(ctx, target.Os.String(), c.installDirOnHost, arch.String())
variant := &bootImageVariant{
- bootImageConfig: c,
- target: target,
- imagePathOnHost: imageDir.Join(ctx, imageName),
- imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
- dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os),
+ bootImageConfig: c,
+ target: target,
+ imagePathOnHost: imageDir.Join(ctx, imageName),
+ imagePathOnDevice: filepath.Join("/", c.installDirOnDevice, arch.String(), imageName),
+ imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
+ dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os),
}
variant.dexLocationsDeps = variant.dexLocations
c.variants = append(c.variants, variant)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index a34044f..829c473 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -56,66 +56,28 @@
// this file so using the encoded dex jar here would result in a cycle in the ninja rules.
bootDexJarPath android.Path
- // The path to the CSV file that contains mappings from Java signature to various flags derived
- // from annotations in the source, e.g. whether it is public or the sdk version above which it
- // can no longer be used.
- //
- // It is created by the Class2NonSdkList tool which processes the .class files in the class
- // implementation jar looking for UnsupportedAppUsage and CovariantReturnType annotations. The
- // tool also consumes the hiddenAPISingletonPathsStruct.stubFlags file in order to perform
- // consistency checks on the information in the annotations and to filter out bridge methods
- // that are already part of the public API.
- flagsCSVPath android.Path
-
- // The path to the CSV file that contains mappings from Java signature to the value of properties
- // specified on UnsupportedAppUsage annotations in the source.
- //
- // Like the flagsCSVPath file this is also created by the Class2NonSdkList in the same way.
- // Although the two files could potentially be created in a single invocation of the
- // Class2NonSdkList at the moment they are created using their own invocation, with the behavior
- // being determined by the property that is used.
- metadataCSVPath android.Path
-
- // The path to the CSV file that contains mappings from Java signature to source location
- // information.
- //
- // It is created by the merge_csv tool which processes the class implementation jar, extracting
- // all the files ending in .uau (which are CSV files) and merges them together. The .uau files are
- // created by the unsupported app usage annotation processor during compilation of the class
- // implementation jar.
- indexCSVPath android.Path
-
// The paths to the classes jars that contain classes and class members annotated with
// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
// processing.
classesJarPaths android.Paths
}
-func (h *hiddenAPI) flagsCSV() android.Path {
- return h.flagsCSVPath
-}
-
-func (h *hiddenAPI) metadataCSV() android.Path {
- return h.metadataCSVPath
-}
-
func (h *hiddenAPI) bootDexJar() android.Path {
return h.bootDexJarPath
}
-func (h *hiddenAPI) indexCSV() android.Path {
- return h.indexCSVPath
-}
-
func (h *hiddenAPI) classesJars() android.Paths {
return h.classesJarPaths
}
+// hiddenAPIModule is the interface a module that embeds the hiddenAPI structure must implement.
+type hiddenAPIModule interface {
+ android.Module
+ hiddenAPIIntf
+}
+
type hiddenAPIIntf interface {
bootDexJar() android.Path
- flagsCSV() android.Path
- indexCSV() android.Path
- metadataCSV() android.Path
classesJars() android.Paths
}
@@ -130,6 +92,12 @@
h.configurationName = configurationName
+ // If the frameworks/base directories does not exist and no prebuilt hidden API flag files have
+ // been configured then it is not possible to do hidden API encoding.
+ if !ctx.Config().FrameworksBaseDirExists(ctx) && ctx.Config().PrebuiltHiddenApiDir(ctx) == "" {
+ return
+ }
+
// It is important that hiddenapi information is only gathered for/from modules that are actually
// on the boot jars list because the runtime only enforces access to the hidden API for the
// bootclassloader. If information is gathered for modules not on the list then that will cause
@@ -191,29 +159,19 @@
return active
}
-// hiddenAPIExtractAndEncode is called by any module that could contribute to the hiddenapi
-// processing.
+// hiddenAPIEncodeDex is called by any module that needs to encode dex files.
//
// It ignores any module that has not had initHiddenApi() called on it and which is not in the boot
-// jar list.
+// jar list. In that case it simply returns the supplied dex jar path.
//
-// Otherwise, it generates ninja rules to do the following:
-// 1. Extract information needed for hiddenapi processing from the module and output it into CSV
-// files.
-// 2. Conditionally adds the supplied dex file to the list of files used to generate the
-// hiddenAPISingletonPathsStruct.stubsFlag file.
-// 3. Conditionally creates a copy of the supplied dex file into which it has encoded the hiddenapi
-// flags and returns this instead of the supplied dex jar, otherwise simply returns the supplied
-// dex jar.
-func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, dexJar android.OutputPath,
- implementationJar android.Path, uncompressDex bool) android.OutputPath {
+// Otherwise, it creates a copy of the supplied dex file into which it has encoded the hiddenapi
+// flags and returns this instead of the supplied dex jar.
+func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.OutputPath, uncompressDex bool) android.OutputPath {
if !h.active {
return dexJar
}
- h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar)
-
hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
// Create a copy of the dex jar which has been encoded with hiddenapi flags.
@@ -225,23 +183,15 @@
return dexJar
}
-// hiddenAPIExtractInformation generates ninja rules to extract the information from the classes
+// hiddenAPIUpdatePaths generates ninja rules to extract the information from the classes
// jar, and outputs it to the appropriate module specific CSV file.
//
// It also makes the dex jar available for use when generating the
// hiddenAPISingletonPathsStruct.stubFlags.
-func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJar, classesJar android.Path) {
- if !h.active {
- return
- }
+func (h *hiddenAPI) hiddenAPIUpdatePaths(ctx android.ModuleContext, dexJar, classesJar android.Path) {
- // More than one library with the same classes may need to be encoded but only one should be
- // used as a source of information for hidden API processing otherwise it will result in
- // duplicate entries in the files.
- if !h.primary {
- return
- }
-
+ // Save the classes jars even if this is not active as they may be used by modular hidden API
+ // processing.
classesJars := android.Paths{classesJar}
ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
@@ -249,26 +199,51 @@
})
h.classesJarPaths = classesJars
- stubFlagsCSV := hiddenAPISingletonPaths(ctx).stubFlags
+ // Save the unencoded dex jar so it can be used when generating the
+ // hiddenAPISingletonPathsStruct.stubFlags file.
+ h.bootDexJarPath = dexJar
+}
- flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv")
+// buildRuleToGenerateAnnotationFlags builds a ninja rule to generate the annotation-flags.csv file
+// from the classes jars and stub-flags.csv files.
+//
+// The annotation-flags.csv file contains mappings from Java signature to various flags derived from
+// annotations in the source, e.g. whether it is public or the sdk version above which it can no
+// longer be used.
+//
+// It is created by the Class2NonSdkList tool which processes the .class files in the class
+// implementation jar looking for UnsupportedAppUsage and CovariantReturnType annotations. The
+// tool also consumes the hiddenAPISingletonPathsStruct.stubFlags file in order to perform
+// consistency checks on the information in the annotations and to filter out bridge methods
+// that are already part of the public API.
+func buildRuleToGenerateAnnotationFlags(ctx android.ModuleContext, desc string, classesJars android.Paths, stubFlagsCSV android.Path, outputPath android.WritablePath) {
ctx.Build(pctx, android.BuildParams{
Rule: hiddenAPIGenerateCSVRule,
- Description: "hiddenapi flags",
+ Description: desc,
Inputs: classesJars,
- Output: flagsCSV,
+ Output: outputPath,
Implicit: stubFlagsCSV,
Args: map[string]string{
"outFlag": "--write-flags-csv",
"stubAPIFlags": stubFlagsCSV.String(),
},
})
- h.flagsCSVPath = flagsCSV
+}
- metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv")
+// buildRuleToGenerateMetadata builds a ninja rule to generate the metadata.csv file from
+// the classes jars and stub-flags.csv files.
+//
+// The metadata.csv file contains mappings from Java signature to the value of properties specified
+// on UnsupportedAppUsage annotations in the source.
+//
+// Like the annotation-flags.csv file this is also created by the Class2NonSdkList in the same way.
+// Although the two files could potentially be created in a single invocation of the
+// Class2NonSdkList at the moment they are created using their own invocation, with the behavior
+// being determined by the property that is used.
+func buildRuleToGenerateMetadata(ctx android.ModuleContext, desc string, classesJars android.Paths, stubFlagsCSV android.Path, metadataCSV android.WritablePath) {
ctx.Build(pctx, android.BuildParams{
Rule: hiddenAPIGenerateCSVRule,
- Description: "hiddenapi metadata",
+ Description: desc,
Inputs: classesJars,
Output: metadataCSV,
Implicit: stubFlagsCSV,
@@ -277,22 +252,27 @@
"stubAPIFlags": stubFlagsCSV.String(),
},
})
- h.metadataCSVPath = metadataCSV
+}
- indexCSV := android.PathForModuleOut(ctx, "hiddenapi", "index.csv")
+// buildRuleToGenerateIndex builds a ninja rule to generate the index.csv file from the classes
+// jars.
+//
+// The index.csv file contains mappings from Java signature to source location information.
+//
+// It is created by the merge_csv tool which processes the class implementation jar, extracting
+// all the files ending in .uau (which are CSV files) and merges them together. The .uau files are
+// created by the unsupported app usage annotation processor during compilation of the class
+// implementation jar.
+func buildRuleToGenerateIndex(ctx android.ModuleContext, desc string, classesJars android.Paths, indexCSV android.WritablePath) {
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
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("merged-hiddenapi-index", "Merged Hidden API index")
- h.indexCSVPath = indexCSV
-
- // Save the unencoded dex jar so it can be used when generating the
- // hiddenAPISingletonPathsStruct.stubFlags file.
- h.bootDexJarPath = dexJar
+ rule.Build(desc, desc)
}
var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{
@@ -329,11 +309,7 @@
}
enforceHiddenApiFlagsToAllMembers := true
- // If frameworks/base doesn't exist we must be building with the 'master-art' manifest.
- // Disable assertion that all methods/fields have hidden API flags assigned.
- if !ctx.Config().FrameworksBaseDirExists(ctx) {
- enforceHiddenApiFlagsToAllMembers = false
- }
+
// b/149353192: when a module is instrumented, jacoco adds synthetic members
// $jacocoData and $jacocoInit. Since they don't exist when building the hidden API flags,
// don't complain when we don't find hidden API flags for the synthetic members.
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 335f5b8..2dceb65 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -15,6 +15,8 @@
package java
import (
+ "strings"
+
"android/soong/android"
"github.com/google/blueprint"
)
@@ -97,7 +99,12 @@
systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
if config.IsEnvTrue("EMMA_INSTRUMENT") {
+ // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
+ // allows everyone access but it is needed to ensure consistent flags between the
+ // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
publicStubModules = append(publicStubModules, "jacoco-stubs")
+ systemStubModules = append(systemStubModules, "jacoco-stubs")
+ testStubModules = append(testStubModules, "jacoco-stubs")
}
m := map[android.SdkKind][]string{}
@@ -121,8 +128,21 @@
// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
// in hiddenAPIAddStubLibDependencies.
-func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext) map[android.SdkKind]android.Paths {
+func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext, contents []android.Module) map[android.SdkKind]android.Paths {
m := map[android.SdkKind]android.Paths{}
+
+ // If the contents includes any java_sdk_library modules then add them to the stubs.
+ for _, module := range contents {
+ if _, ok := module.(SdkLibraryDependency); ok {
+ for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
+ dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
+ if dexJar != nil {
+ m[kind] = append(m[kind], dexJar)
+ }
+ }
+ }
+ }
+
ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
@@ -133,6 +153,12 @@
}
}
})
+
+ // Normalize the paths, i.e. remove duplicates and sort.
+ for k, v := range m {
+ m[k] = android.SortedUniquePaths(v)
+ }
+
return m
}
@@ -166,7 +192,7 @@
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
// name.
-func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.OutputPath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
+func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
// Singleton rule which applies hiddenapi on all boot class path dex files.
rule := android.NewRuleBuilder(pctx, ctx)
@@ -338,57 +364,105 @@
},
}
-// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties
+// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties and also generated
+// by hidden API processing.
+//
+// This is used both for an individual bootclasspath_fragment to provide it to other modules and
+// for a module to collate the files from the fragments it depends upon. That is why the fields are
+// all Paths even though they are initialized with a single path.
type hiddenAPIFlagFileInfo struct {
// categoryToPaths maps from the flag file category to the paths containing information for that
// category.
categoryToPaths map[*hiddenAPIFlagFileCategory]android.Paths
+
+ // The paths to the generated stub-flags.csv files.
+ StubFlagsPaths android.Paths
+
+ // The paths to the generated annotation-flags.csv files.
+ AnnotationFlagsPaths android.Paths
+
+ // The paths to the generated metadata.csv files.
+ MetadataPaths android.Paths
+
+ // The paths to the generated index.csv files.
+ IndexPaths android.Paths
+
+ // The paths to the generated all-flags.csv files.
+ AllFlagsPaths android.Paths
}
func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) {
for _, category := range hiddenAPIFlagFileCategories {
i.categoryToPaths[category] = append(i.categoryToPaths[category], other.categoryToPaths[category]...)
}
+ i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPaths...)
+ i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPaths...)
+ i.MetadataPaths = append(i.MetadataPaths, other.MetadataPaths...)
+ i.IndexPaths = append(i.IndexPaths, other.IndexPaths...)
+ i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPaths...)
}
var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
-// ruleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from the
-// flags from all the modules, the stub flags, augmented with some additional configuration files.
+// pathForValidation creates a path of the same type as the supplied type but with a name of
+// <path>.valid.
+//
+// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
+// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
+func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
+ extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
+ return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
+}
+
+// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
+// the flags from all the modules, the stub flags, augmented with some additional configuration
+// files.
//
// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
// an entry for every single member in the dex implementation jars of the individual modules. Every
// signature in any of the other files MUST be included in this file.
//
-// moduleSpecificFlagsPaths are the paths to the flags files generated by each module using
-// information from the baseFlagsPath as well as from annotations within the source.
+// annotationFlags is the path to the annotation flags file generated from annotation information
+// in each module.
//
-// augmentationInfo is a struct containing paths to files that augment the information provided by
-// the moduleSpecificFlagsPaths.
-// ruleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from the
-// flags from all the modules, the stub flags, augmented with some additional configuration files.
-//
-// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
-// an entry for every single member in the dex implementation jars of the individual modules. Every
-// signature in any of the other files MUST be included in this file.
-//
-// moduleSpecificFlagsPaths are the paths to the flags files generated by each module using
-// information from the baseFlagsPath as well as from annotations within the source.
-//
-// augmentationInfo is a struct containing paths to files that augment the information provided by
-// the moduleSpecificFlagsPaths.
-func ruleToGenerateHiddenApiFlags(ctx android.BuilderContext, outputPath android.WritablePath, baseFlagsPath android.Path, moduleSpecificFlagsPaths android.Paths, augmentationInfo hiddenAPIFlagFileInfo) {
+// flagFileInfo is a struct containing paths to files that augment the information provided by
+// the annotationFlags.
+func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlags android.Path, flagFileInfo *hiddenAPIFlagFileInfo) {
+
+ // The file which is used to record that the flags file is valid.
+ var validFile android.WritablePath
+
+ // If there are flag files that have been generated by fragments on which this depends then use
+ // them to validate the flag file generated by the rules created by this method.
+ if allFlagsPaths := flagFileInfo.AllFlagsPaths; len(allFlagsPaths) > 0 {
+ // The flags file generated by the rule created by this method needs to be validated to ensure
+ // that it is consistent with the flag files generated by the individual fragments.
+
+ validFile = pathForValidation(ctx, outputPath)
+
+ // Create a rule to validate the output from the following rule.
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("verify_overlaps").
+ Input(outputPath).
+ Inputs(allFlagsPaths).
+ // If validation passes then update the file that records that.
+ Text("&& touch").Output(validFile)
+ rule.Build(name+"Validation", desc+" validation")
+ }
+
+ // Create the rule that will generate the flag files.
tempPath := tempPathForRestat(ctx, outputPath)
rule := android.NewRuleBuilder(pctx, ctx)
command := rule.Command().
BuiltTool("generate_hiddenapi_lists").
FlagWithInput("--csv ", baseFlagsPath).
- Inputs(moduleSpecificFlagsPaths).
+ Input(annotationFlags).
FlagWithOutput("--output ", tempPath)
// Add the options for the different categories of flag files.
for _, category := range hiddenAPIFlagFileCategories {
- paths := augmentationInfo.categoryToPaths[category]
+ paths := flagFileInfo.categoryToPaths[category]
for _, path := range paths {
category.commandMutator(command, path)
}
@@ -396,5 +470,109 @@
commitChangeForRestat(rule, tempPath, outputPath)
- rule.Build("hiddenAPIFlagsFile", "hiddenapi flags")
+ if validFile != nil {
+ // Add the file that indicates that the file generated by this is valid.
+ //
+ // This will cause the validation rule above to be run any time that the output of this rule
+ // changes but the validation will run in parallel with other rules that depend on this file.
+ command.Validation(validFile)
+ }
+
+ rule.Build(name, desc)
+}
+
+// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
+// of the bootclasspath.
+//
+// It takes:
+// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
+// * The list of modules that are the contents of the fragment.
+// * The additional manually curated flag files to use.
+//
+// It generates:
+// * stub-flags.csv
+// * annotation-flags.csv
+// * metadata.csv
+// * index.csv
+// * all-flags.csv
+func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
+ hiddenApiSubDir := "modular-hiddenapi"
+
+ // Generate the stub-flags.csv.
+ bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)
+ stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
+ rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, stubJarsByKind)
+ rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
+
+ // Extract the classes jars from the contents.
+ classesJars := extractClassJarsFromHiddenAPIModules(ctx, contents)
+
+ // Generate the set of flags from the annotations in the source code.
+ annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
+ buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
+
+ // Generate the metadata from the annotations in the source code.
+ metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
+ buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
+
+ // Generate the index file from the CSV files in the classes jars.
+ indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
+ buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
+
+ // Removed APIs need to be marked and in order to do that the flagFileInfo needs to specify files
+ // containing dex signatures of all the removed APIs. In the monolithic files that is done by
+ // manually combining all the removed.txt files for each API and then converting them to dex
+ // signatures, see the combined-removed-dex module. That will all be done automatically in future.
+ // For now removed APIs are ignored.
+ // TODO(b/179354495): handle removed apis automatically.
+
+ // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
+ // files.
+ outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
+ buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, flagFileInfo)
+
+ // Store the paths in the info for use by other modules and sdk snapshot generation.
+ flagFileInfo.StubFlagsPaths = android.Paths{stubFlagsCSV}
+ flagFileInfo.AnnotationFlagsPaths = android.Paths{annotationFlagsCSV}
+ flagFileInfo.MetadataPaths = android.Paths{metadataCSV}
+ flagFileInfo.IndexPaths = android.Paths{indexCSV}
+ flagFileInfo.AllFlagsPaths = android.Paths{outputPath}
+}
+
+// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
+func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule {
+ hiddenAPIModules := []hiddenAPIModule{}
+ for _, module := range contents {
+ if hiddenAPI, ok := module.(hiddenAPIModule); ok {
+ hiddenAPIModules = append(hiddenAPIModules, hiddenAPI)
+ } else if _, ok := module.(*DexImport); ok {
+ // Ignore this for the purposes of hidden API processing
+ } else {
+ ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
+ }
+ }
+ return hiddenAPIModules
+}
+
+// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules.
+func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
+ bootDexJars := android.Paths{}
+ for _, module := range contents {
+ bootDexJar := module.bootDexJar()
+ if bootDexJar == nil {
+ ctx.ModuleErrorf("module %s does not provide a dex jar", module)
+ } else {
+ bootDexJars = append(bootDexJars, bootDexJar)
+ }
+ }
+ return bootDexJars
+}
+
+// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules.
+func extractClassJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
+ classesJars := android.Paths{}
+ for _, module := range contents {
+ classesJars = append(classesJars, module.classesJars()...)
+ }
+ return classesJars
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 676a0e7..848aa59 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -117,7 +117,6 @@
}
type hiddenAPISingleton struct {
- flags android.Path
}
// hiddenAPI singleton rules
@@ -136,17 +135,10 @@
// consistency.
if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" {
- h.flags = prebuiltFlagsRule(ctx)
+ prebuiltFlagsRule(ctx)
prebuiltIndexRule(ctx)
return
}
-
- // These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
- if ctx.Config().FrameworksBaseDirExists(ctx) {
- h.flags = flagsRule(ctx)
- } else {
- h.flags = emptyFlagsRule(ctx)
- }
}
// Checks to see whether the supplied module variant is in the list of boot jars.
@@ -187,7 +179,7 @@
return true
}
-func prebuiltFlagsRule(ctx android.SingletonContext) android.Path {
+func prebuiltFlagsRule(ctx android.SingletonContext) {
outputPath := hiddenAPISingletonPaths(ctx).flags
inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv")
@@ -196,8 +188,6 @@
Output: outputPath,
Input: inputPath,
})
-
- return outputPath
}
func prebuiltIndexRule(ctx android.SingletonContext) {
@@ -211,28 +201,6 @@
})
}
-// flagsRule is a placeholder that simply returns the location of the file, the generation of the
-// ninja rules is done in generateHiddenAPIBuildActions.
-func flagsRule(ctx android.SingletonContext) android.Path {
- outputPath := hiddenAPISingletonPaths(ctx).flags
- return outputPath
-}
-
-// emptyFlagsRule creates a rule to build an empty hiddenapi-flags.csv, which is needed by master-art-host builds that
-// have a partial manifest without frameworks/base but still need to build a boot image.
-func emptyFlagsRule(ctx android.SingletonContext) android.Path {
- rule := android.NewRuleBuilder(pctx, ctx)
-
- outputPath := hiddenAPISingletonPaths(ctx).flags
-
- rule.Command().Text("rm").Flag("-f").Output(outputPath)
- rule.Command().Text("touch").Output(outputPath)
-
- rule.Build("emptyHiddenAPIFlagsFile", "empty hiddenapi flags")
-
- return outputPath
-}
-
// tempPathForRestat creates a path of the same type as the supplied type but with a name of
// <path>.tmp.
//
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 3ab2277..e6b45ac 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -60,10 +60,7 @@
}
func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) {
- expectedErrorMessage :=
- "hiddenapi has determined that the source module \"foo\" should be ignored as it has been" +
- " replaced by the prebuilt module \"prebuilt_foo\" but unfortunately it does not provide a" +
- " suitable boot dex jar"
+ expectedErrorMessage := "module prebuilt_foo{os:android,arch:common} does not provide a dex jar"
android.GroupFixturePreparers(
hiddenApiFixtureFactory,
diff --git a/java/java.go b/java/java.go
index 9a5fbfc..f85de3d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1315,7 +1315,7 @@
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
if dexOutputPath := di.PrebuiltExportPath(j.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
j.dexJarFile = dexOutputPath
- j.hiddenAPIExtractInformation(ctx, dexOutputPath, outputFile)
+ j.hiddenAPIUpdatePaths(ctx, dexOutputPath, outputFile)
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
@@ -1346,9 +1346,11 @@
return
}
- // Hidden API CSV generation and dex encoding
- dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, outputFile,
- proptools.Bool(j.dexProperties.Uncompress_dex))
+ // Update hidden API paths.
+ j.hiddenAPIUpdatePaths(ctx, dexOutputFile, outputFile)
+
+ // Encode hidden API flags in dex file.
+ dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
j.dexJarFile = dexOutputFile
}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 1feed3d..c8fafed 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -257,17 +257,6 @@
return defaultBootImageConfig(ctx)
}
-// hiddenAPISupportingModule encapsulates the information provided by any module that contributes to
-// the hidden API processing.
-type hiddenAPISupportingModule struct {
- module android.Module
-
- bootDexJar android.Path
- flagsCSV android.Path
- indexCSV android.Path
- metadataCSV android.Path
-}
-
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) {
@@ -290,67 +279,6 @@
return
}
- // nilPathHandler will check the supplied path and if it is nil then it will either immediately
- // report an error, or it will defer the error reporting until it is actually used, depending
- // whether missing dependencies are allowed.
- var nilPathHandler func(path android.Path, name string, module android.Module) android.Path
- if ctx.Config().AllowMissingDependencies() {
- nilPathHandler = func(path android.Path, name string, module android.Module) android.Path {
- if path == nil {
- outputPath := android.PathForModuleOut(ctx, "missing", module.Name(), name)
- path = outputPath
-
- // 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: outputPath,
- Args: map[string]string{
- "error": fmt.Sprintf("missing hidden API file: %s for %s", name, module),
- },
- })
- }
- return path
- }
- } else {
- nilPathHandler = func(path android.Path, name string, module android.Module) android.Path {
- if path == nil {
- ctx.ModuleErrorf("module %s does not provide a %s file", module, name)
- }
- return path
- }
- }
-
- hiddenAPISupportingModules := []hiddenAPISupportingModule{}
- for _, module := range modules {
- if h, ok := module.(hiddenAPIIntf); ok {
- hiddenAPISupportingModule := hiddenAPISupportingModule{
- module: module,
- bootDexJar: nilPathHandler(h.bootDexJar(), "bootDexJar", module),
- flagsCSV: nilPathHandler(h.flagsCSV(), "flagsCSV", module),
- indexCSV: nilPathHandler(h.indexCSV(), "indexCSV", module),
- metadataCSV: nilPathHandler(h.metadataCSV(), "metadataCSV", module),
- }
-
- // If any errors were reported when trying to populate the hiddenAPISupportingModule struct
- // then don't add it to the list.
- if ctx.Failed() {
- continue
- }
-
- hiddenAPISupportingModules = append(hiddenAPISupportingModules, hiddenAPISupportingModule)
- } else if _, ok := module.(*DexImport); ok {
- // Ignore this for the purposes of hidden API processing
- } else {
- ctx.ModuleErrorf("module %s of type %s does not support hidden API processing", module, ctx.OtherModuleType(module))
- }
- }
-
- moduleSpecificFlagsPaths := android.Paths{}
- for _, module := range hiddenAPISupportingModules {
- moduleSpecificFlagsPaths = append(moduleSpecificFlagsPaths, module.flagsCSV)
- }
-
flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
for _, fragment := range fragments {
if ctx.OtherModuleHasProvider(fragment, hiddenAPIFlagFileInfoProvider) {
@@ -362,61 +290,53 @@
// Store the information for testing.
ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
- outputPath := hiddenAPISingletonPaths(ctx).flags
- baseFlagsPath := hiddenAPISingletonPaths(ctx).stubFlags
- ruleToGenerateHiddenApiFlags(ctx, outputPath, baseFlagsPath, moduleSpecificFlagsPaths, flagFileInfo)
+ hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules)
- b.generateHiddenAPIStubFlagsRules(ctx, hiddenAPISupportingModules)
- b.generateHiddenAPIIndexRules(ctx, hiddenAPISupportingModules)
- b.generatedHiddenAPIMetadataRules(ctx, hiddenAPISupportingModules)
-}
+ sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx, nil)
-func (b *platformBootclasspathModule) generateHiddenAPIStubFlagsRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
- bootDexJars := android.Paths{}
- for _, module := range modules {
- bootDexJars = append(bootDexJars, module.bootDexJar)
- }
-
- sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx)
-
- outputPath := hiddenAPISingletonPaths(ctx).stubFlags
- rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, outputPath, bootDexJars, sdkKindToStubPaths)
+ // Generate the monolithic stub-flags.csv file.
+ bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
+ stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
+ rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, sdkKindToStubPaths)
rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
+
+ // Extract the classes jars from the contents.
+ classesJars := extractClassJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
+
+ // Generate the annotation-flags.csv file from all the module annotations.
+ annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags.csv")
+ buildRuleToGenerateAnnotationFlags(ctx, "monolithic hiddenapi flags", classesJars, stubFlags, annotationFlags)
+
+ // Generate the monotlithic hiddenapi-flags.csv file.
+ allFlags := hiddenAPISingletonPaths(ctx).flags
+ buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "hiddenapi flags", allFlags, stubFlags, annotationFlags, &flagFileInfo)
+
+ // Generate an intermediate monolithic hiddenapi-metadata.csv file directly from the annotations
+ // in the source code.
+ intermediateMetadataCSV := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "intermediate-metadata.csv")
+ buildRuleToGenerateMetadata(ctx, "monolithic hidden API metadata", classesJars, stubFlags, intermediateMetadataCSV)
+
+ // Reformat the intermediate file to add | quotes just in case that is important for the tools
+ // that consume the metadata file.
+ // TODO(b/179354495): Investigate whether it is possible to remove this reformatting step.
+ metadataCSV := hiddenAPISingletonPaths(ctx).metadata
+ b.buildRuleMergeCSV(ctx, "reformat monolithic hidden API metadata", android.Paths{intermediateMetadataCSV}, metadataCSV)
+
+ // Generate the monolithic hiddenapi-index.csv file directly from the CSV files in the classes
+ // jars.
+ indexCSV := hiddenAPISingletonPaths(ctx).index
+ buildRuleToGenerateIndex(ctx, "monolithic hidden API index", classesJars, indexCSV)
}
-func (b *platformBootclasspathModule) generateHiddenAPIIndexRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
- indexes := android.Paths{}
- for _, module := range modules {
- indexes = append(indexes, module.indexCSV)
- }
-
+func (b *platformBootclasspathModule) buildRuleMergeCSV(ctx android.ModuleContext, desc string, inputPaths android.Paths, outputPath android.WritablePath) {
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("merge_csv").
Flag("--key_field signature").
- FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties").
- FlagWithOutput("--output=", hiddenAPISingletonPaths(ctx).index).
- Inputs(indexes)
- rule.Build("platform-bootclasspath-monolithic-hiddenapi-index", "monolithic hidden API index")
-}
-
-func (b *platformBootclasspathModule) generatedHiddenAPIMetadataRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
- metadataCSVFiles := android.Paths{}
- for _, module := range modules {
- metadataCSVFiles = append(metadataCSVFiles, module.metadataCSV)
- }
-
- rule := android.NewRuleBuilder(pctx, ctx)
-
- outputPath := hiddenAPISingletonPaths(ctx).metadata
-
- rule.Command().
- BuiltTool("merge_csv").
- Flag("--key_field signature").
FlagWithOutput("--output=", outputPath).
- Inputs(metadataCSVFiles)
+ Inputs(inputPaths)
- rule.Build("platform-bootclasspath-monolithic-hiddenapi-metadata", "monolithic hidden API metadata")
+ rule.Build(desc, desc)
}
// generateHiddenApiMakeVars generates make variables needed by hidden API related make rules, e.g.
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 98d4614..efcbc80 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -155,6 +155,8 @@
func TestPlatformBootclasspath_Fragments(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
android.FixtureWithRootAndroidBp(`
platform_bootclasspath {
name: "platform-bootclasspath",
@@ -192,6 +194,9 @@
bootclasspath_fragment {
name: "bar-fragment",
contents: ["bar"],
+ api: {
+ stub_libs: ["foo"],
+ },
hidden_api: {
unsupported: [
"bar-unsupported.txt",
@@ -227,6 +232,15 @@
sdk_version: "none",
compile_dex: true,
}
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ },
+ compile_dex: true,
+ }
`),
).RunTest(t)
@@ -240,6 +254,12 @@
expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
android.AssertPathsRelativeToTopEquals(t, message, expected, info.categoryToPaths[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) {
@@ -407,20 +427,14 @@
}
`)
- platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common")
- indexRule := platformBootclasspath.Rule("platform-bootclasspath-monolithic-hiddenapi-index")
- CheckHiddenAPIRuleInputs(t, `
-.intermediates/bar/android_common/hiddenapi/index.csv
-.intermediates/foo/android_common/hiddenapi/index.csv
-`,
- indexRule)
-
// Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that
// creates the index.csv file.
- foo := result.ModuleForTests("foo", "android_common")
- indexParams := foo.Output("hiddenapi/index.csv")
+ platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common")
+ indexRule := platformBootclasspath.Rule("monolithic_hidden_API_index")
CheckHiddenAPIRuleInputs(t, `
+.intermediates/bar/android_common/javac/bar.jar
.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar
.intermediates/foo/android_common/javac/foo.jar
-`, indexParams)
+`,
+ indexRule)
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 7804512..f04f837 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -900,11 +900,17 @@
return componentProps
}
-// Check if this can be used as a shared library.
func (c *commonToSdkLibraryAndImport) sharedLibrary() bool {
return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true)
}
+// Check if the stub libraries should be compiled for dex
+func (c *commonToSdkLibraryAndImport) stubLibrariesCompiledForDex() bool {
+ // Always compile the dex file files for the stub libraries if they will be used on the
+ // bootclasspath.
+ return !c.sharedLibrary()
+}
+
// Properties related to the use of a module as an component of a java_sdk_library.
type SdkLibraryComponentProperties struct {
@@ -978,6 +984,9 @@
// SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
// tool which processes dex files.
SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path
+
+ // sharedLibrary returns true if this can be used as a shared library.
+ sharedLibrary() bool
}
type SdkLibrary struct {
@@ -1309,9 +1318,13 @@
// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
// interop with older developer tools that don't support 1.9.
props.Java_version = proptools.StringPtr("1.8")
- if module.dexProperties.Compile_dex != nil {
- props.Compile_dex = module.dexProperties.Compile_dex
+
+ // The imports need to be compiled to dex if the java_sdk_library requests it.
+ compileDex := module.dexProperties.Compile_dex
+ if module.stubLibrariesCompiledForDex() {
+ compileDex = proptools.BoolPtr(true)
}
+ props.Compile_dex = compileDex
// Dist the class jar artifact for sdk builds.
if !Bool(module.sdkLibraryProperties.No_dist) {
@@ -1969,7 +1982,11 @@
props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
// The imports need to be compiled to dex if the java_sdk_library_import requests it.
- props.Compile_dex = module.properties.Compile_dex
+ compileDex := module.properties.Compile_dex
+ if module.stubLibrariesCompiledForDex() {
+ compileDex = proptools.BoolPtr(true)
+ }
+ props.Compile_dex = compileDex
mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
@@ -2111,7 +2128,7 @@
if dexOutputPath := di.PrebuiltExportPath(module.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
module.dexJarFile = dexOutputPath
module.initHiddenAPI(ctx, module.configurationName)
- module.hiddenAPIExtractInformation(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0])
+ module.hiddenAPIUpdatePaths(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0])
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
diff --git a/scripts/build-rustdocs.sh b/scripts/build-rustdocs.sh
new file mode 100755
index 0000000..ad8ba16
--- /dev/null
+++ b/scripts/build-rustdocs.sh
@@ -0,0 +1,31 @@
+#!/bin/bash -ex
+
+# Copyright 2021 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Builds the platform rustdocs and copies them to the dist directory to provide
+# online docs for each build.
+
+if [ -z "${OUT_DIR}" ]; then
+ echo Must set OUT_DIR
+ exit 1
+fi
+
+source build/envsetup.sh
+m rustdoc
+
+if [ -n "${DIST_DIR}" ]; then
+ mkdir -p ${DIST_DIR}
+ cp -r ${OUT_DIR}/soong/rustdoc $DIST_DIR/rustdoc
+fi
diff --git a/scripts/hiddenapi/Android.bp b/scripts/hiddenapi/Android.bp
index af7e7fe..7472f52 100644
--- a/scripts/hiddenapi/Android.bp
+++ b/scripts/hiddenapi/Android.bp
@@ -47,3 +47,18 @@
},
},
}
+
+python_binary_host {
+ name: "verify_overlaps",
+ main: "verify_overlaps.py",
+ srcs: ["verify_overlaps.py"],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/scripts/hiddenapi/verify_overlaps.py b/scripts/hiddenapi/verify_overlaps.py
new file mode 100755
index 0000000..c8e3879
--- /dev/null
+++ b/scripts/hiddenapi/verify_overlaps.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+Verify that one set of hidden API flags is a subset of another.
+"""
+
+import argparse
+import csv
+
+args_parser = argparse.ArgumentParser(description='Verify that one set of hidden API flags is a subset of another.')
+args_parser.add_argument('all', help='All the flags')
+args_parser.add_argument('subsets', nargs=argparse.REMAINDER, help='Subsets of the flags')
+args = args_parser.parse_args()
+
+
+def dict_reader(input):
+ return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
+
+# Read in all the flags into a dict indexed by signature
+allFlagsBySignature = {}
+with open(args.all, 'r') as allFlagsFile:
+ allFlagsReader = dict_reader(allFlagsFile)
+ for row in allFlagsReader:
+ signature = row['signature']
+ allFlagsBySignature[signature]=row
+
+failed = False
+for subsetPath in args.subsets:
+ mismatchingSignatures = []
+ with open(subsetPath, 'r') as subsetFlagsFile:
+ subsetReader = dict_reader(subsetFlagsFile)
+ for row in subsetReader:
+ signature = row['signature']
+ if signature in allFlagsBySignature:
+ allFlags = allFlagsBySignature.get(signature)
+ if allFlags != row:
+ mismatchingSignatures.append((signature, row[None], allFlags[None]))
+ else:
+ mismatchingSignatures.append((signature, row[None], []))
+
+
+ if mismatchingSignatures:
+ failed = True
+ print("ERROR: Hidden API flags are inconsistent:")
+ print("< " + subsetPath)
+ print("> " + args.all)
+ for mismatch in mismatchingSignatures:
+ print()
+ print("< " + mismatch[0] + "," + ",".join(mismatch[1]))
+ if mismatch[2] != None:
+ print("> " + mismatch[0] + "," + ",".join(mismatch[2]))
+ else:
+ print("> " + mismatch[0] + " - missing")
+
+if failed:
+ sys.exit(1)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index f18e697..bd69f06 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -165,21 +165,33 @@
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
- java.FixtureWithLastReleaseApis("mysdklibrary", "mycoreplatform"),
+ java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
bootclasspath_fragments: ["mybootclasspathfragment"],
- java_sdk_libs: ["mysdklibrary", "mycoreplatform"],
+ java_sdk_libs: [
+ // This is not strictly needed as it should be automatically added to the sdk_snapshot as
+ // a java_sdk_libs module because it is used in the mybootclasspathfragment's
+ // api.stub_libs property. However, it is specified here to ensure that duplicates are
+ // correctly deduped.
+ "mysdklibrary",
+ ],
}
bootclasspath_fragment {
name: "mybootclasspathfragment",
- contents: ["mybootlib"],
+ contents: [
+ // This should be automatically added to the sdk_snapshot as a java_boot_libs module.
+ "mybootlib",
+ // This should be automatically added to the sdk_snapshot as a java_sdk_libs module.
+ "myothersdklibrary",
+ ],
api: {
stub_libs: ["mysdklibrary"],
},
core_platform_api: {
+ // This should be automatically added to the sdk_snapshot as a java_sdk_libs module.
stub_libs: ["mycoreplatform"],
},
}
@@ -195,14 +207,21 @@
java_sdk_library {
name: "mysdklibrary",
srcs: ["Test.java"],
- compile_dex: true,
+ shared_library: false,
+ public: {enabled: true},
+ }
+
+ java_sdk_library {
+ name: "myothersdklibrary",
+ srcs: ["Test.java"],
+ shared_library: false,
public: {enabled: true},
}
java_sdk_library {
name: "mycoreplatform",
srcs: ["Test.java"],
- compile_dex: true,
+ shared_library: false,
public: {enabled: true},
}
`),
@@ -217,13 +236,23 @@
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- contents: ["mybootlib"],
+ contents: [
+ "mybootlib",
+ "myothersdklibrary",
+ ],
api: {
stub_libs: ["mysdklibrary"],
},
core_platform_api: {
stub_libs: ["mycoreplatform"],
},
+ hidden_api: {
+ stub_flags: "hiddenapi/stub-flags.csv",
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ all_flags: "hiddenapi/all-flags.csv",
+ },
}
java_import {
@@ -235,12 +264,26 @@
}
java_sdk_library_import {
+ name: "myothersdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myothersdklibrary_stub_sources"],
+ current_api: "sdk_library/public/myothersdklibrary.txt",
+ removed_api: "sdk_library/public/myothersdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+
+java_sdk_library_import {
name: "mysdklibrary",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- shared_library: true,
- compile_dex: true,
+ shared_library: false,
public: {
jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
@@ -255,8 +298,7 @@
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- shared_library: true,
- compile_dex: true,
+ shared_library: false,
public: {
jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
@@ -265,7 +307,7 @@
sdk_version: "current",
},
}
-`),
+ `),
checkVersionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -274,13 +316,23 @@
sdk_member_name: "mybootclasspathfragment",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- contents: ["mysdk_mybootlib@current"],
+ contents: [
+ "mysdk_mybootlib@current",
+ "mysdk_myothersdklibrary@current",
+ ],
api: {
stub_libs: ["mysdk_mysdklibrary@current"],
},
core_platform_api: {
stub_libs: ["mysdk_mycoreplatform@current"],
},
+ hidden_api: {
+ stub_flags: "hiddenapi/stub-flags.csv",
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ all_flags: "hiddenapi/all-flags.csv",
+ },
}
java_import {
@@ -292,12 +344,26 @@
}
java_sdk_library_import {
+ name: "mysdk_myothersdklibrary@current",
+ sdk_member_name: "myothersdklibrary",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myothersdklibrary_stub_sources"],
+ current_api: "sdk_library/public/myothersdklibrary.txt",
+ removed_api: "sdk_library/public/myothersdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+
+java_sdk_library_import {
name: "mysdk_mysdklibrary@current",
sdk_member_name: "mysdklibrary",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- shared_library: true,
- compile_dex: true,
+ shared_library: false,
public: {
jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
@@ -312,8 +378,7 @@
sdk_member_name: "mycoreplatform",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- shared_library: true,
- compile_dex: true,
+ shared_library: false,
public: {
jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
@@ -329,13 +394,22 @@
bootclasspath_fragments: ["mysdk_mybootclasspathfragment@current"],
java_boot_libs: ["mysdk_mybootlib@current"],
java_sdk_libs: [
+ "mysdk_myothersdklibrary@current",
"mysdk_mysdklibrary@current",
"mysdk_mycoreplatform@current",
],
}
-`),
+ `),
checkAllCopyRules(`
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/all-flags.csv -> hiddenapi/all-flags.csv
.intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
+.intermediates/myothersdklibrary.stubs/android_common/javac/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
.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
@@ -487,6 +561,11 @@
max_target_o_low_priority: ["hiddenapi/my-max-target-o-low-priority.txt"],
blocked: ["hiddenapi/my-blocked.txt"],
unsupported_packages: ["hiddenapi/my-unsupported-packages.txt"],
+ stub_flags: "hiddenapi/stub-flags.csv",
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ all_flags: "hiddenapi/all-flags.csv",
},
}
@@ -523,6 +602,11 @@
my-max-target-o-low-priority.txt -> hiddenapi/my-max-target-o-low-priority.txt
my-blocked.txt -> hiddenapi/my-blocked.txt
my-unsupported-packages.txt -> hiddenapi/my-unsupported-packages.txt
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/all-flags.csv -> hiddenapi/all-flags.csv
.intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt