Merge changes from topic "revert-15071196-init_first_stage_soong-GBJXQRPEKC" into sc-dev
* changes:
Revert "Add install_in_root to cc_binary"
Revert "Add ramdisk_available to sysprop_library"
Revert "Fix ndk and aml arch order"
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 43b7cbe..f3493bd 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -166,6 +166,7 @@
func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) {
p := module.Prebuilt()
module.AddProperties(&p.properties)
+ module.base().customizableProperties = module.GetProperties()
if srcsSupplier == nil {
panic(fmt.Errorf("srcsSupplier must not be nil"))
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index ced37fe..23524a5 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -259,6 +259,38 @@
}`,
prebuilt: []OsType{Android, BuildOs},
},
+ {
+ name: "prebuilt properties customizable",
+ replaceBp: true,
+ modules: `
+ source {
+ name: "foo",
+ deps: [":bar"],
+ }
+
+ soong_config_module_type {
+ name: "prebuilt_with_config",
+ module_type: "prebuilt",
+ config_namespace: "any_namespace",
+ bool_variables: ["bool_var"],
+ properties: ["prefer"],
+ }
+
+ prebuilt_with_config {
+ name: "bar",
+ prefer: true,
+ srcs: ["prebuilt_file"],
+ soong_config_variables: {
+ bool_var: {
+ prefer: false,
+ conditions_default: {
+ prefer: true,
+ },
+ },
+ },
+ }`,
+ prebuilt: []OsType{Android, BuildOs},
+ },
}
func TestPrebuilts(t *testing.T) {
@@ -394,6 +426,9 @@
ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
ctx.RegisterModuleType("source", newSourceModule)
ctx.RegisterModuleType("override_source", newOverrideSourceModule)
+ ctx.RegisterModuleType("soong_config_module_type", soongConfigModuleTypeFactory)
+ ctx.RegisterModuleType("soong_config_string_variable", soongConfigStringVariableDummyFactory)
+ ctx.RegisterModuleType("soong_config_bool_variable", soongConfigBoolVariableDummyFactory)
}
type prebuiltModule struct {
diff --git a/android/sdk.go b/android/sdk.go
index 36c576d..42c8ffa 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -38,6 +38,36 @@
type sdkAwareWithoutModule interface {
RequiredSdks
+ // SdkMemberComponentName will return the name to use for a component of this module based on the
+ // base name of this module.
+ //
+ // The baseName is the name returned by ModuleBase.BaseModuleName(), i.e. the name specified in
+ // the name property in the .bp file so will not include the prebuilt_ prefix.
+ //
+ // The componentNameCreator is a func for creating the name of a component from the base name of
+ // the module, e.g. it could just append ".component" to the name passed in.
+ //
+ // This is intended to be called by prebuilt modules that create component models. It is because
+ // prebuilt module base names come in a variety of different forms:
+ // * unversioned - this is the same as the source module.
+ // * internal to an sdk - this is the unversioned name prefixed by the base name of the sdk
+ // module.
+ // * versioned - this is the same as the internal with the addition of an "@<version>" suffix.
+ //
+ // While this can be called from a source module in that case it will behave the same way as the
+ // unversioned name and return the result of calling the componentNameCreator func on the supplied
+ // base name.
+ //
+ // e.g. Assuming the componentNameCreator func simply appends ".component" to the name passed in
+ // then this will work as follows:
+ // * An unversioned name of "foo" will return "foo.component".
+ // * An internal to the sdk name of "sdk_foo" will return "sdk_foo.component".
+ // * A versioned name of "sdk_foo@current" will return "sdk_foo.component@current".
+ //
+ // Note that in the latter case the ".component" suffix is added before the version. Adding it
+ // after would change the version.
+ SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string
+
sdkBase() *SdkBase
MakeMemberOf(sdk SdkRef)
IsInAnySdk() bool
@@ -135,6 +165,18 @@
return s
}
+func (s *SdkBase) SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string {
+ if s.MemberName() == "" {
+ return componentNameCreator(baseName)
+ } else {
+ index := strings.LastIndex(baseName, "@")
+ unversionedName := baseName[:index]
+ unversionedComponentName := componentNameCreator(unversionedName)
+ versionSuffix := baseName[index:]
+ return unversionedComponentName + versionSuffix
+ }
+}
+
// MakeMemberOf sets this module to be a member of a specific SDK
func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
s.properties.ContainingSdk = &sdk
@@ -317,6 +359,8 @@
// SdkMemberType returns the SdkMemberType that will be used to automatically add the child module
// to the sdk.
+ //
+ // Returning nil will prevent the module being added to the sdk.
SdkMemberType(child Module) SdkMemberType
// ExportMember determines whether a module added to the sdk through this tag will be exported
@@ -643,3 +687,30 @@
// into which to copy the prebuilt files.
Name() string
}
+
+// ExportedComponentsInfo contains information about the components that this module exports to an
+// sdk snapshot.
+//
+// A component of a module is a child module that the module creates and which forms an integral
+// part of the functionality that the creating module provides. A component module is essentially
+// owned by its creator and is tightly coupled to the creator and other components.
+//
+// e.g. the child modules created by prebuilt_apis are not components because they are not tightly
+// coupled to the prebuilt_apis module. Once they are created the prebuilt_apis ignores them. The
+// child impl and stub library created by java_sdk_library (and corresponding import) are components
+// because the creating module depends upon them in order to provide some of its own functionality.
+//
+// A component is exported if it is part of an sdk snapshot. e.g. The xml and impl child modules are
+// components but they are not exported as they are not part of an sdk snapshot.
+//
+// This information is used by the sdk snapshot generation code to ensure that it does not create
+// an sdk snapshot that contains a declaration of the component module and the module that creates
+// it as that would result in duplicate modules when attempting to use the snapshot. e.g. a snapshot
+// that included the java_sdk_library_import "foo" and also a java_import "foo.stubs" would fail
+// as there would be two modules called "foo.stubs".
+type ExportedComponentsInfo struct {
+ // The names of the exported components.
+ Components []string
+}
+
+var ExportedComponentsInfoProvider = blueprint.NewProvider(ExportedComponentsInfo{})
diff --git a/apex/apex.go b/apex/apex.go
index e731702..bea54bc 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -177,6 +177,12 @@
// used in tests.
Test_only_force_compression *bool
+ // Canonical name of this APEX bundle. Used to determine the path to the
+ // activated APEX on device (i.e. /apex/<apexVariationName>), and used for the
+ // apex mutator variations. For override_apex modules, this is the name of the
+ // overridden base module.
+ ApexVariationName string `blueprint:"mutated"`
+
IsCoverageVariant bool `blueprint:"mutated"`
// List of sanitizer names that this APEX is enabled for
@@ -808,6 +814,10 @@
var _ ApexInfoMutator = (*apexBundle)(nil)
+func (a *apexBundle) ApexVariationName() string {
+ return a.properties.ApexVariationName
+}
+
// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
// indirect) dependencies are collected. But a few types of modules that shouldn't be included in
@@ -896,15 +906,15 @@
// This is the main part of this mutator. Mark the collected dependencies that they need to
// be built for this apexBundle.
- // Note that there are many different names.
- // ApexVariationName: this is the name of the apex variation
+ apexVariationName := proptools.StringDefault(a.properties.Apex_name, mctx.ModuleName()) // could be com.android.foo
+ a.properties.ApexVariationName = apexVariationName
apexInfo := android.ApexInfo{
- ApexVariationName: mctx.ModuleName(), // could be com.android.foo
+ ApexVariationName: apexVariationName,
MinSdkVersion: minSdkVersion,
RequiredSdks: a.RequiredSdks(),
Updatable: a.Updatable(),
- InApexVariants: []string{mctx.ModuleName()}, // could be com.android.foo
- InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo
+ InApexVariants: []string{apexVariationName},
+ InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo
ApexContents: []*android.ApexContents{apexContents},
}
mctx.WalkDeps(func(child, parent android.Module) bool {
@@ -917,6 +927,10 @@
}
type ApexInfoMutator interface {
+ // ApexVariationName returns the name of the APEX variation to use in the apex
+ // mutator etc. It is the same name as ApexInfo.ApexVariationName.
+ ApexVariationName() string
+
// ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
// depended upon by an apex and which require an apex specific variant.
ApexInfoMutator(android.TopDownMutatorContext)
@@ -1042,10 +1056,8 @@
}
// apexBundle itself is mutated so that it and its dependencies have the same apex variant.
- // TODO(jiyong): document the reason why the VNDK APEX is an exception here.
- unprefixedModuleName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName())
- if apexModuleTypeRequiresVariant(mctx.Module()) {
- apexBundleName := unprefixedModuleName
+ if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
+ apexBundleName := ai.ApexVariationName()
mctx.CreateVariations(apexBundleName)
if strings.HasPrefix(apexBundleName, "com.android.art") {
// Create an alias from the platform variant. This is done to make
@@ -1068,6 +1080,7 @@
// apex variant name. This name matches the name used to create the variations of modules for
// which apexModuleTypeRequiresVariant return true.
// TODO(b/191269918): Remove this workaround.
+ unprefixedModuleName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName())
mctx.SetDefaultDependencyVariation(&unprefixedModuleName)
mctx.CreateVariations(apexBundleName)
if strings.HasPrefix(apexBundleName, "com.android.art") {
@@ -1079,18 +1092,13 @@
// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific
// variant.
-func apexModuleTypeRequiresVariant(module android.Module) bool {
+func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool {
if a, ok := module.(*apexBundle); ok {
+ // TODO(jiyong): document the reason why the VNDK APEX is an exception here.
return !a.vndkApex
}
- // Match apex_set and prebuilt_apex. Would also match apexBundle but that is handled specially
- // above.
- if _, ok := module.(ApexInfoMutator); ok {
- return true
- }
-
- return false
+ return true
}
// See android.UpdateDirectlyInAnyApex
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1bc2514..4829029 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3670,13 +3670,13 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ module := ctx.ModuleForTests("myapex", "android_common_com.android.myapex_image")
apexManifestRule := module.Rule("apexManifestRule")
ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
apexRule := module.Rule("apexRule")
ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
- apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+ apexBundle := module.Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, apexBundle)
name := apexBundle.BaseModuleName()
prefix := "TARGET_"
@@ -4219,6 +4219,59 @@
}
}
+func TestPrebuiltApexName(t *testing.T) {
+ testApex(t, `
+ prebuilt_apex {
+ name: "com.company.android.myapex",
+ apex_name: "com.android.myapex",
+ src: "company-myapex-arm.apex",
+ }
+ `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+
+ testApex(t, `
+ apex_set {
+ name: "com.company.android.myapex",
+ apex_name: "com.android.myapex",
+ set: "company-myapex.apks",
+ }
+ `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+}
+
+func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
+ _ = android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithApexBuildComponents,
+ android.FixtureWithRootAndroidBp(`
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ }
+
+ prebuilt_apex {
+ name: "com.company.android.art",
+ apex_name: "com.android.art",
+ src: "com.company.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ contents: ["core-oj"],
+ }
+
+ java_import {
+ name: "core-oj",
+ jars: ["prebuilt.jar"],
+ }
+ `),
+ ).RunTest(t)
+}
+
// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
// propagation of paths to dex implementation jars from the former to the latter.
func TestPrebuiltExportDexImplementationJars(t *testing.T) {
@@ -4416,11 +4469,18 @@
}
}
- checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedInputs string) {
+ checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
t.Helper()
platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
- indexRule := platformBootclasspath.Rule("monolithic_hidden_API_index")
- java.CheckHiddenAPIRuleInputs(t, expectedInputs, indexRule)
+ var rule android.TestingBuildParams
+
+ rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv")
+ java.CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule)
+ }
+
+ fragment := java.ApexVariantReference{
+ Apex: proptools.StringPtr("myapex"),
+ Module: proptools.StringPtr("my-bootclasspath-fragment"),
}
t.Run("prebuilt only", func(t *testing.T) {
@@ -4435,7 +4495,13 @@
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo", "libbar"],
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
}
java_import {
@@ -4450,18 +4516,19 @@
jars: ["libbar.jar"],
},
apex_available: ["myapex"],
+ shared_library: false,
}
`
- ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
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")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
-.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
-`)
+ out/soong/.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
+ out/soong/.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
+ `)
})
t.Run("apex_set only", func(t *testing.T) {
@@ -4469,7 +4536,13 @@
apex_set {
name: "myapex",
set: "myapex.apks",
- exported_java_libs: ["libfoo", "libbar"],
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
}
java_import {
@@ -4484,18 +4557,19 @@
jars: ["libbar.jar"],
},
apex_available: ["myapex"],
+ shared_library: false,
}
`
- ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
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")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
-.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
-`)
+ out/soong/.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
+ out/soong/.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
+ `)
})
t.Run("prebuilt with source library preferred", func(t *testing.T) {
@@ -4510,7 +4584,13 @@
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo", "libbar"],
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
}
java_import {
@@ -4531,6 +4611,7 @@
jars: ["libbar.jar"],
},
apex_available: ["myapex"],
+ shared_library: false,
}
java_sdk_library {
@@ -4546,7 +4627,7 @@
// prebuilt_apex module always depends on the prebuilt, and so it doesn't
// find the dex boot jar in it. We either need to disable the source libfoo
// or make the prebuilt libfoo preferred.
- testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer)
+ testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer, fragment)
})
t.Run("prebuilt library preferred with source", func(t *testing.T) {
@@ -4561,7 +4642,13 @@
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo", "libbar"],
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
}
java_import {
@@ -4584,6 +4671,7 @@
jars: ["libbar.jar"],
},
apex_available: ["myapex"],
+ shared_library: false,
}
java_sdk_library {
@@ -4594,15 +4682,15 @@
}
`
- ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
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")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
-.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
-`)
+ out/soong/.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
+ out/soong/.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
+ `)
})
t.Run("prebuilt with source apex preferred", func(t *testing.T) {
@@ -4630,7 +4718,13 @@
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo", "libbar"],
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
}
java_import {
@@ -4651,6 +4745,7 @@
jars: ["libbar.jar"],
},
apex_available: ["myapex"],
+ shared_library: false,
}
java_sdk_library {
@@ -4661,15 +4756,15 @@
}
`
- ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
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")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar/android_common_myapex/javac/libbar.jar
-.intermediates/libfoo/android_common_apex10000/javac/libfoo.jar
-`)
+ out/soong/.intermediates/libbar/android_common_myapex/javac/libbar.jar
+ out/soong/.intermediates/libfoo/android_common_apex10000/javac/libfoo.jar
+ `)
})
t.Run("prebuilt preferred with source apex disabled", func(t *testing.T) {
@@ -4697,7 +4792,13 @@
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo", "libbar"],
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
}
java_import {
@@ -4720,6 +4821,7 @@
jars: ["libbar.jar"],
},
apex_available: ["myapex"],
+ shared_library: false,
}
java_sdk_library {
@@ -4730,15 +4832,15 @@
}
`
- ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
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")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
-.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
-`)
+ out/soong/.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
+ out/soong/.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
+ `)
})
}
@@ -6305,7 +6407,7 @@
android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
}
-func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer) {
+func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) {
t.Helper()
bp := `
@@ -6324,6 +6426,15 @@
apex_available: [
"some-non-updatable-apex",
],
+ compile_dex: true,
+ }
+
+ bootclasspath_fragment {
+ name: "some-non-updatable-fragment",
+ contents: ["some-non-updatable-apex-lib"],
+ apex_available: [
+ "some-non-updatable-apex",
+ ],
}
java_library {
@@ -6355,7 +6466,7 @@
apex {
name: "some-non-updatable-apex",
key: "some-non-updatable-apex.key",
- java_libs: ["some-non-updatable-apex-lib"],
+ bootclasspath_fragments: ["some-non-updatable-fragment"],
updatable: false,
}
@@ -6370,7 +6481,7 @@
apex {
name: "com.android.art.debug",
key: "com.android.art.debug.key",
- java_libs: ["some-art-lib"],
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
updatable: true,
min_sdk_version: "current",
}
@@ -6403,10 +6514,10 @@
}
`
- testDexpreoptWithApexes(t, bp, errmsg, preparer)
+ testDexpreoptWithApexes(t, bp, errmsg, preparer, fragments...)
}
-func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer) *android.TestContext {
+func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) *android.TestContext {
t.Helper()
fs := android.MockFS{
@@ -6434,11 +6545,22 @@
PrepareForTestWithApexBuildComponents,
preparer,
fs.AddToFixture(),
- android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
- platform_bootclasspath {
- name: "platform-bootclasspath",
+ android.FixtureModifyMockFS(func(fs android.MockFS) {
+ if _, ok := fs["frameworks/base/boot/Android.bp"]; !ok {
+ insert := ""
+ for _, fragment := range fragments {
+ insert += fmt.Sprintf("{apex: %q, module: %q},\n", *fragment.Apex, *fragment.Module)
+ }
+ fs["frameworks/base/boot/Android.bp"] = []byte(fmt.Sprintf(`
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ %s
+ ],
+ }
+ `, insert))
}
- `),
+ }),
).
ExtendWithErrorHandler(errorHandler).
RunTestWithBp(t, bp)
@@ -6505,7 +6627,11 @@
t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
preparer := java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib")
- testNoUpdatableJarsInBootImage(t, "", preparer)
+ fragment := java.ApexVariantReference{
+ Apex: proptools.StringPtr("com.android.art.debug"),
+ Module: proptools.StringPtr("art-bootclasspath-fragment"),
+ }
+ testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
})
t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
@@ -6537,7 +6663,11 @@
t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
preparer := java.FixtureConfigureBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
- testNoUpdatableJarsInBootImage(t, "", preparer)
+ fragment := java.ApexVariantReference{
+ Apex: proptools.StringPtr("some-non-updatable-apex"),
+ Module: proptools.StringPtr("some-non-updatable-fragment"),
+ }
+ testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
})
t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
@@ -6568,6 +6698,11 @@
func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) {
preparer := java.FixtureConfigureBootJars("myapex:libfoo")
t.Run("prebuilt no source", func(t *testing.T) {
+ fragment := java.ApexVariantReference{
+ Apex: proptools.StringPtr("myapex"),
+ Module: proptools.StringPtr("my-bootclasspath-fragment"),
+ }
+
testDexpreoptWithApexes(t, `
prebuilt_apex {
name: "myapex" ,
@@ -6579,36 +6714,21 @@
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
- }
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- }
-`, "", preparer)
- })
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo"],
+ apex_available: ["myapex"],
+ }
- t.Run("prebuilt no source", func(t *testing.T) {
- testDexpreoptWithApexes(t, `
- prebuilt_apex {
- name: "myapex" ,
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["libfoo"],
- }
-
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- }
-`, "", preparer)
+ java_import {
+ name: "libfoo",
+ jars: ["libfoo.jar"],
+ apex_available: ["myapex"],
+ }
+ `, "", preparer, fragment)
})
}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 66bc9e0..4b1600e 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -22,6 +22,7 @@
"android/soong/android"
"android/soong/java"
+ "github.com/google/blueprint/proptools"
)
// Contains tests for bootclasspath_fragment logic from java/bootclasspath_fragment.go as the ART
@@ -216,9 +217,10 @@
`,
)
- checkSdkKindStubs := func(message string, info java.HiddenAPIInfo, kind android.SdkKind, expectedPaths ...string) {
+ checkAPIScopeStubs := func(message string, info java.HiddenAPIInfo, apiScope *java.HiddenAPIScope, expectedPaths ...string) {
t.Helper()
- android.AssertPathsRelativeToTopEquals(t, fmt.Sprintf("%s %s", message, kind), expectedPaths, info.TransitiveStubDexJarsByKind[kind])
+ paths := info.TransitiveStubDexJarsByScope.StubDexJarsForScope(apiScope)
+ android.AssertPathsRelativeToTopEquals(t, fmt.Sprintf("%s %s", message, apiScope), expectedPaths, paths)
}
// Check stub dex paths exported by art.
@@ -229,10 +231,10 @@
bazSystemStubs := "out/soong/.intermediates/baz.stubs.system/android_common/dex/baz.stubs.system.jar"
bazTestStubs := "out/soong/.intermediates/baz.stubs.test/android_common/dex/baz.stubs.test.jar"
- checkSdkKindStubs("art", artInfo, android.SdkPublic, bazPublicStubs)
- checkSdkKindStubs("art", artInfo, android.SdkSystem, bazSystemStubs)
- checkSdkKindStubs("art", artInfo, android.SdkTest, bazTestStubs)
- checkSdkKindStubs("art", artInfo, android.SdkCorePlatform)
+ checkAPIScopeStubs("art", artInfo, java.PublicHiddenAPIScope, bazPublicStubs)
+ checkAPIScopeStubs("art", artInfo, java.SystemHiddenAPIScope, bazSystemStubs)
+ checkAPIScopeStubs("art", artInfo, java.TestHiddenAPIScope, bazTestStubs)
+ checkAPIScopeStubs("art", artInfo, java.CorePlatformHiddenAPIScope)
// Check stub dex paths exported by other.
otherFragment := result.Module("other-bootclasspath-fragment", "android_common")
@@ -241,10 +243,10 @@
fooPublicStubs := "out/soong/.intermediates/foo.stubs/android_common/dex/foo.stubs.jar"
fooSystemStubs := "out/soong/.intermediates/foo.stubs.system/android_common/dex/foo.stubs.system.jar"
- checkSdkKindStubs("other", otherInfo, android.SdkPublic, bazPublicStubs, fooPublicStubs)
- checkSdkKindStubs("other", otherInfo, android.SdkSystem, bazSystemStubs, fooSystemStubs)
- checkSdkKindStubs("other", otherInfo, android.SdkTest, bazTestStubs, fooSystemStubs)
- checkSdkKindStubs("other", otherInfo, android.SdkCorePlatform)
+ checkAPIScopeStubs("other", otherInfo, java.PublicHiddenAPIScope, bazPublicStubs, fooPublicStubs)
+ checkAPIScopeStubs("other", otherInfo, java.SystemHiddenAPIScope, bazSystemStubs, fooSystemStubs)
+ checkAPIScopeStubs("other", otherInfo, java.TestHiddenAPIScope, bazTestStubs, fooSystemStubs)
+ checkAPIScopeStubs("other", otherInfo, java.CorePlatformHiddenAPIScope)
}
func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName, variantName string, expectedConfiguredModules string, expectedBootclasspathFragmentFiles string) {
@@ -718,4 +720,480 @@
checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/bar.jar")
}
+func getDexJarPath(result *android.TestResult, name string) string {
+ module := result.Module(name, "android_common")
+ return module.(java.UsesLibraryDependency).DexJarBuildPath().RelativeToTop().String()
+}
+
+// TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are
+// passed to the hiddenapi list tool.
+func TestBootclasspathFragment_HiddenAPIList(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootclasspathFragment,
+ prepareForTestWithArtApex,
+ prepareForTestWithMyapex,
+ // Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+ java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
+ java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"),
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("foo", "quuz"),
+ ).RunTestWithBp(t, `
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ java_library {
+ name: "baz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ }
+
+ java_sdk_library {
+ name: "quuz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ public: {enabled: true},
+ system: {enabled: true},
+ test: {enabled: true},
+ module_lib: {enabled: true},
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+ contents: ["baz", "quuz"],
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: [
+ "mybootclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["b.java"],
+ shared_library: false,
+ public: {enabled: true},
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: [
+ "foo",
+ "bar",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ }
+ `)
+
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "art-bootclasspath-fragment",
+ "bar",
+ "dex2oatd",
+ "foo",
+ })
+
+ fooStubs := getDexJarPath(result, "foo.stubs")
+ quuzPublicStubs := getDexJarPath(result, "quuz.stubs")
+ quuzSystemStubs := getDexJarPath(result, "quuz.stubs.system")
+ quuzTestStubs := getDexJarPath(result, "quuz.stubs.test")
+ quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.module_lib")
+
+ // Make sure that the fragment uses the quuz stub dex jars when generating the hidden API flags.
+ fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+
+ rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
+ command := rule.RuleParams.Command
+ android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
+
+ // Make sure that the quuz stubs are available for resolving references from the implementation
+ // boot dex jars provided by this module.
+ android.AssertStringDoesContain(t, "quuz widest", command, "--dependency-stub-dex="+quuzModuleLibStubs)
+
+ // Make sure that the quuz stubs are available for resolving references from the different API
+ // stubs provided by this module.
+ android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+quuzPublicStubs+":"+fooStubs)
+ android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+quuzSystemStubs+":"+fooStubs)
+ android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+quuzTestStubs+":"+fooStubs)
+}
+
+// TestBootclasspathFragment_AndroidNonUpdatable checks to make sure that setting
+// additional_stubs: ["android-non-updatable"] causes the source android-non-updatable modules to be
+// added to the hiddenapi list tool.
+func TestBootclasspathFragment_AndroidNonUpdatable(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootclasspathFragment,
+ prepareForTestWithArtApex,
+ prepareForTestWithMyapex,
+ // Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+ java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"),
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("foo", "android-non-updatable"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "android-non-updatable",
+ srcs: ["b.java"],
+ compile_dex: true,
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ }
+
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ java_libs: [
+ "baz",
+ "quuz",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ java_library {
+ name: "baz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ }
+
+ java_library {
+ name: "quuz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+ contents: ["baz", "quuz"],
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: [
+ "mybootclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["b.java"],
+ shared_library: false,
+ public: {enabled: true},
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: [
+ "foo",
+ "bar",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ additional_stubs: ["android-non-updatable"],
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ }
+ `)
+
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "android-non-updatable.stubs",
+ "android-non-updatable.stubs.module_lib",
+ "android-non-updatable.stubs.system",
+ "android-non-updatable.stubs.test",
+ "art-bootclasspath-fragment",
+ "bar",
+ "dex2oatd",
+ "foo",
+ })
+
+ nonUpdatablePublicStubs := getDexJarPath(result, "android-non-updatable.stubs")
+ nonUpdatableSystemStubs := getDexJarPath(result, "android-non-updatable.stubs.system")
+ nonUpdatableTestStubs := getDexJarPath(result, "android-non-updatable.stubs.test")
+ nonUpdatableModuleLibStubs := getDexJarPath(result, "android-non-updatable.stubs.module_lib")
+
+ // Make sure that the fragment uses the android-non-updatable modules when generating the hidden
+ // API flags.
+ fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+
+ rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
+ command := rule.RuleParams.Command
+ android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
+
+ // Make sure that the module_lib non-updatable stubs are available for resolving references from
+ // the implementation boot dex jars provided by this module.
+ android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs)
+
+ // Make sure that the appropriate non-updatable stubs are available for resolving references from
+ // the different API stubs provided by this module.
+ android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs)
+ android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs)
+ android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs)
+}
+
+// TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks checks to make sure that
+// setting additional_stubs: ["android-non-updatable"] causes the prebuilt android-non-updatable
+// modules to be added to the hiddenapi list tool.
+func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootclasspathFragment,
+ java.PrepareForTestWithJavaDefaultModules,
+ prepareForTestWithArtApex,
+ prepareForTestWithMyapex,
+ // Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+ java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"),
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
+ }),
+
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithPrebuiltApis(map[string][]string{
+ "current": {"android-non-updatable"},
+ "30": {"foo"},
+ }),
+ ).RunTestWithBp(t, `
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ java_libs: [
+ "baz",
+ "quuz",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ java_library {
+ name: "baz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ }
+
+ java_library {
+ name: "quuz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+ contents: ["baz", "quuz"],
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: [
+ "mybootclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["b.java"],
+ shared_library: false,
+ public: {enabled: true},
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: [
+ "foo",
+ "bar",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ additional_stubs: ["android-non-updatable"],
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ }
+ `)
+
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "art-bootclasspath-fragment",
+ "bar",
+ "dex2oatd",
+ "foo",
+ "prebuilt_sdk_module-lib_current_android-non-updatable",
+ "prebuilt_sdk_public_current_android-non-updatable",
+ "prebuilt_sdk_system_current_android-non-updatable",
+ "prebuilt_sdk_test_current_android-non-updatable",
+ })
+
+ nonUpdatablePublicStubs := getDexJarPath(result, "sdk_public_current_android-non-updatable")
+ nonUpdatableSystemStubs := getDexJarPath(result, "sdk_system_current_android-non-updatable")
+ nonUpdatableTestStubs := getDexJarPath(result, "sdk_test_current_android-non-updatable")
+ nonUpdatableModuleLibStubs := getDexJarPath(result, "sdk_module-lib_current_android-non-updatable")
+
+ // Make sure that the fragment uses the android-non-updatable modules when generating the hidden
+ // API flags.
+ fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+
+ rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
+ command := rule.RuleParams.Command
+ android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
+
+ // Make sure that the module_lib non-updatable stubs are available for resolving references from
+ // the implementation boot dex jars provided by this module.
+ android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs)
+
+ // Make sure that the appropriate non-updatable stubs are available for resolving references from
+ // the different API stubs provided by this module.
+ android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs)
+ android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs)
+ android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs)
+}
+
// TODO(b/177892522) - add test for host apex.
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 7297926..bd4a9d5 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -234,12 +234,18 @@
apex {
name: "myapex",
key: "myapex.key",
- java_libs: [
- "bar",
+ bootclasspath_fragments: [
+ "my-bootclasspath-fragment",
],
updatable: false,
}
+ bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["bar"],
+ apex_available: ["myapex"],
+ }
+
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
@@ -267,6 +273,10 @@
apex: "com.android.art",
module: "art-bootclasspath-fragment",
},
+ {
+ apex: "myapex",
+ module: "my-bootclasspath-fragment",
+ },
],
}
`,
@@ -283,7 +293,8 @@
})
java.CheckPlatformBootclasspathFragments(t, result, "myplatform-bootclasspath", []string{
- `com.android.art:art-bootclasspath-fragment`,
+ "com.android.art:art-bootclasspath-fragment",
+ "myapex:my-bootclasspath-fragment",
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
@@ -307,6 +318,7 @@
// The fragments.
`com.android.art:art-bootclasspath-fragment`,
+ `myapex:my-bootclasspath-fragment`,
})
}
@@ -410,6 +422,12 @@
platform_bootclasspath {
name: "myplatform-bootclasspath",
+ fragments: [
+ {
+ apex: "myapex",
+ module:"mybootclasspath-fragment",
+ },
+ ],
}
`,
)
@@ -431,7 +449,7 @@
"platform:legacy.core.platform.api.stubs",
// Needed for generating the boot image.
- `platform:dex2oatd`,
+ "platform:dex2oatd",
// The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
// modules when available as it does not know which one will be preferred.
@@ -442,6 +460,9 @@
// Only a source module exists.
"myapex:bar",
+
+ // The fragments.
+ "myapex:mybootclasspath-fragment",
})
}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 9504b07..30fd359 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -23,7 +23,6 @@
"android/soong/android"
"android/soong/java"
"github.com/google/blueprint"
-
"github.com/google/blueprint/proptools"
)
@@ -75,6 +74,10 @@
type PrebuiltCommonProperties struct {
SelectedApexProperties
+ // Canonical name of this APEX. Used to determine the path to the activated APEX on
+ // device (/apex/<apex_name>). If unspecified, follows the name property.
+ Apex_name *string
+
ForceDisable bool `blueprint:"mutated"`
// whether the extracted apex file is installable.
@@ -109,6 +112,10 @@
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
}
+func (p *prebuiltCommon) ApexVariationName() string {
+ return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.ModuleBase.BaseModuleName())
+}
+
func (p *prebuiltCommon) Prebuilt() *android.Prebuilt {
return &p.prebuilt
}
@@ -368,6 +375,12 @@
}
}
+ // Ignore any modules that do not implement ApexModule as they cannot have an APEX specific
+ // variant.
+ if _, ok := child.(android.ApexModule); !ok {
+ return false
+ }
+
// Strip off the prebuilt_ prefix if present before storing content to ensure consistent
// behavior whether there is a corresponding source module present or not.
depName = android.RemoveOptionalPrebuiltPrefix(depName)
@@ -389,11 +402,11 @@
})
// Create an ApexInfo for the prebuilt_apex.
- apexVariationName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName())
+ apexVariationName := p.ApexVariationName()
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
InApexVariants: []string{apexVariationName},
- InApexModules: []string{apexVariationName},
+ InApexModules: []string{p.ModuleBase.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix.
ApexContents: []*android.ApexContents{apexContents},
ForPrebuiltApex: true,
}
diff --git a/cc/cc.go b/cc/cc.go
index be2c0a3..c62fd6c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3355,6 +3355,7 @@
&android.ProtoProperties{},
// RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules.
&RustBindgenClangProperties{},
+ &prebuiltLinkerProperties{},
)
// Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
diff --git a/cc/config/global.go b/cc/config/global.go
index 59fe8e1..ae731b2 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -145,8 +145,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r416183b"
- ClangDefaultShortVersion = "12.0.5"
+ ClangDefaultVersion = "clang-r416183b1"
+ ClangDefaultShortVersion = "12.0.7"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f486ee4..941a955 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -485,6 +485,11 @@
if Bool(s.Hwaddress) {
s.Address = nil
s.Thread = nil
+ // Disable ubsan diagnosic as a workaround for a compiler bug.
+ // TODO(b/191808836): re-enable.
+ s.Diag.Undefined = nil
+ s.Diag.Integer_overflow = nil
+ s.Diag.Misc_undefined = nil
}
// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
diff --git a/java/base.go b/java/base.go
index cf6fafa..df70efb 100644
--- a/java/base.go
+++ b/java/base.go
@@ -253,8 +253,8 @@
EmbeddableSdkLibraryComponent
}
-func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) {
- e.initSdkLibraryComponent(moduleBase)
+func (e *embeddableInModuleAndImport) initModuleAndImport(module android.Module) {
+ e.initSdkLibraryComponent(module)
}
// Module/Import's DepIsInSameApex(...) delegates to this method.
@@ -1275,6 +1275,7 @@
j.linter.minSdkVersion = lintSDKVersionString(j.MinSdkVersion(ctx))
j.linter.targetSdkVersion = lintSDKVersionString(j.TargetSdkVersion(ctx))
j.linter.compileSdkVersion = lintSDKVersionString(j.SdkVersion(ctx))
+ j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index eddcc83..d754fe6 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -225,13 +225,13 @@
Core_platform_api BootclasspathNestedAPIProperties
}
-// sdkKindToStubLibs calculates the stub library modules for each relevant android.SdkKind from the
+// apiScopeToStubLibs calculates the stub library modules for each relevant *HiddenAPIScope from the
// Stub_libs properties.
-func (p BootclasspathAPIProperties) sdkKindToStubLibs() map[android.SdkKind][]string {
- m := map[android.SdkKind][]string{}
- for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
- m[kind] = p.Api.Stub_libs
+func (p BootclasspathAPIProperties) apiScopeToStubLibs() map[*HiddenAPIScope][]string {
+ m := map[*HiddenAPIScope][]string{}
+ for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+ m[apiScope] = p.Api.Stub_libs
}
- m[android.SdkCorePlatform] = p.Core_platform_api.Stub_libs
+ m[CorePlatformHiddenAPIScope] = p.Core_platform_api.Stub_libs
return m
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 03faf34..5392953 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -121,8 +121,18 @@
BootclasspathFragmentCoverageAffectedProperties
Coverage BootclasspathFragmentCoverageAffectedProperties
+ // Hidden API related properties.
Hidden_api HiddenAPIFlagFileProperties
+ // The list of additional stub libraries which this fragment's contents use but which are not
+ // provided by another bootclasspath_fragment.
+ //
+ // Note, "android-non-updatable" is treated specially. While no such module exists it is treated
+ // as if it was a java_sdk_library. So, when public API stubs are needed then it will be replaced
+ // with "android-non-updatable.stubs", with "androidn-non-updatable.system.stubs" when the system
+ // stubs are needed and so on.
+ Additional_stubs []string
+
// Properties that allow a fragment to depend on other fragments. This is needed for hidden API
// processing as it needs access to all the classes used by a fragment including those provided
// by other fragments.
@@ -149,11 +159,12 @@
// versioned sdk.
produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
- // produceBootImageFiles produces the boot image (i.e. .art, .oat and .vdex) files for each of the
- // required android.ArchType values in the returned map.
+ // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths
+ // predefined in the bootImageConfig.
//
- // It must return nil if the boot image files cannot be produced for whatever reason.
- produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch
+ // If it could not create the files then it will return nil. Otherwise, it will return a map from
+ // android.ArchType to the predefined paths of the boot image files.
+ produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch
}
var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
@@ -375,7 +386,16 @@
func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies onto all the modules that provide the API stubs for classes on this
// bootclasspath fragment.
- hiddenAPIAddStubLibDependencies(ctx, b.properties.sdkKindToStubLibs())
+ hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs())
+
+ for _, additionalStubModule := range b.properties.Additional_stubs {
+ for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+ // Add a dependency onto a possibly scope specific stub library.
+ scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule)
+ tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true}
+ ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency)
+ }
+ }
if SkipDexpreoptBootJars(ctx) {
return
@@ -429,9 +449,13 @@
if imageConfig != nil {
// Delegate the production of the boot image files to a module type specific method.
common := ctx.Module().(commonBootclasspathFragment)
- bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig, contents)
+ bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig)
if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
+ // Zip the boot image files up, if available. This will generate the zip file in a
+ // predefined location.
+ buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFilesByArch)
+
// Copy the dex jars of this fragment's content modules to their predefined locations.
copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
}
@@ -506,27 +530,18 @@
global := dexpreopt.GetGlobalConfig(ctx)
- // Convert content names to their appropriate stems, in case a test library is overriding an actual boot jar
- var stems []string
- for _, name := range b.properties.Contents {
- dep := ctx.GetDirectDepWithTag(name, bootclasspathFragmentContentDepTag)
- if m, ok := dep.(ModuleWithStem); ok {
- stems = append(stems, m.Stem())
- } else {
- ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
- }
- }
+ possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
// Only create configs for updatable boot jars. Non-updatable boot jars must be part of the
// platform_bootclasspath's classpath proto config to guarantee that they come before any
// updatable jars at runtime.
- jars := global.UpdatableBootJars.Filter(stems)
+ jars := global.UpdatableBootJars.Filter(possibleUpdatableModules)
// TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths
// config. However, any test specific jars would not be present in UpdatableBootJars. Instead,
// we should check if we are creating a config for apex_test via ApexInfo and amend the values.
// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
- if android.InList("test_framework-sdkextensions", stems) {
+ if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
}
return jars
@@ -557,25 +572,9 @@
// Create hidden API input structure.
input := b.createHiddenAPIFlagInput(ctx, contents, fragments)
- var output *HiddenAPIOutput
-
- // Hidden API processing is conditional as a temporary workaround as not all
- // bootclasspath_fragments provide the appropriate information needed for hidden API processing
- // which leads to breakages of the build.
- // TODO(b/179354495): Stop hidden API processing being conditional once all bootclasspath_fragment
- // modules have been updated to support it.
- if input.canPerformHiddenAPIProcessing(ctx, b.properties) {
- // Delegate the production of the hidden API all-flags.csv file to a module type specific method.
- common := ctx.Module().(commonBootclasspathFragment)
- output = common.produceHiddenAPIOutput(ctx, contents, input)
- } else {
- // As hidden API processing cannot be performed fall back to trying to retrieve the legacy
- // encoded boot dex files, i.e. those files encoded by the individual libraries and returned
- // from the DexJarBuildPath() method.
- output = &HiddenAPIOutput{
- EncodedBootDexFilesByModule: retrieveLegacyEncodedBootDexFiles(ctx, contents),
- }
- }
+ // Delegate the production of the hidden API all-flags.csv file to a module type specific method.
+ common := ctx.Module().(commonBootclasspathFragment)
+ output := common.produceHiddenAPIOutput(ctx, contents, input)
// Initialize a HiddenAPIInfo structure.
hiddenAPIInfo := HiddenAPIInfo{
@@ -588,7 +587,7 @@
// Other bootclasspath_fragments that depend on this need the transitive set of stub dex jars
// from this to resolve any references from their code to classes provided by this fragment
// and the fragments this depends upon.
- TransitiveStubDexJarsByKind: input.transitiveStubDexJarsByKind(),
+ TransitiveStubDexJarsByScope: input.transitiveStubDexJarsByScope(),
}
// The monolithic hidden API processing also needs access to all the output files produced by
@@ -632,8 +631,8 @@
// Populate with flag file paths from the properties.
input.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api)
- // Store the stub dex jars from this module's fragment dependencies.
- input.DependencyStubDexJarsByKind = dependencyHiddenApiInfo.TransitiveStubDexJarsByKind
+ // Add the stub dex jars from this module's fragment dependencies.
+ input.DependencyStubDexJarsByScope.addStubDexJarsByModule(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope)
return input
}
@@ -647,7 +646,7 @@
}
// produceBootImageFiles builds the boot image files from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch {
+func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
if SkipDexpreoptBootJars(ctx) {
return nil
}
@@ -657,45 +656,34 @@
dexpreopt.GetGlobalSoongConfig(ctx)
// Only generate the boot image if the configuration does not skip it.
- if !b.generateBootImageBuildActions(ctx, contents, imageConfig) {
- return nil
- }
-
- // Only make the files available to an apex if they were actually generated.
- files := bootImageFilesByArch{}
- for _, variant := range imageConfig.apexVariants() {
- files[variant.target.Arch.ArchType] = variant.imagesDeps.Paths()
- }
-
- return files
+ return b.generateBootImageBuildActions(ctx, imageConfig)
}
// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
// module.
//
-// Returns true if the boot image is created, false otherwise.
-func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, contents []android.Module, imageConfig *bootImageConfig) bool {
+// If it could not create the files then it will return nil. Otherwise, it will return a map from
+// android.ArchType to the predefined paths of the boot image files.
+func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
global := dexpreopt.GetGlobalConfig(ctx)
if !shouldBuildBootImages(ctx.Config(), global) {
- return false
+ return nil
}
// Bootclasspath fragment modules that are for the platform do not produce a boot image.
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if apexInfo.IsForPlatform() {
- return false
+ return nil
}
// Bootclasspath fragment modules that are versioned do not produce a boot image.
if android.IsModuleInVersionedSdk(ctx.Module()) {
- return false
+ return nil
}
// Build a profile for the image config and then use that to build the boot image.
profile := bootImageProfileRule(ctx, imageConfig)
- buildBootImage(ctx, imageConfig, profile)
-
- return true
+ return buildBootImage(ctx, imageConfig, profile)
}
type bootclasspathFragmentMemberType struct {
@@ -908,7 +896,7 @@
}
// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch {
+func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
return nil
}
@@ -930,6 +918,7 @@
}
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
+ files := bootImageFilesByArch{}
for _, variant := range imageConfig.apexVariants() {
arch := variant.target.Arch.ArchType
for _, toPath := range variant.imagesDeps {
@@ -937,6 +926,10 @@
// Get the path to the file that the deapexer extracted from the prebuilt apex file.
fromPath := di.PrebuiltExportPath(apexRelativePath)
+ // Return the toPath as the calling code expects the paths in the returned map to be the
+ // paths predefined in the bootImageConfig.
+ files[arch] = append(files[arch], toPath)
+
// Copy the file to the predefined location.
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
@@ -946,10 +939,7 @@
}
}
- // The returned files will be made available to APEXes that include a bootclasspath_fragment.
- // However, as a prebuilt_bootclasspath_fragment can never contribute to an APEX there is no point
- // in returning any files.
- return nil
+ return files
}
var _ commonBootclasspathFragment = (*prebuiltBootclasspathFragmentModule)(nil)
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index fba7d1a..3d0e155 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -197,7 +197,7 @@
],
},
core_platform_api: {
- stub_libs: ["mycoreplatform"],
+ stub_libs: ["mycoreplatform.stubs"],
},
}
@@ -245,17 +245,34 @@
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.TransitiveStubDexJarsByKind[android.SdkPublic])
+ android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(PublicHiddenAPIScope))
// 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.TransitiveStubDexJarsByKind[android.SdkSystem])
+ android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(SystemHiddenAPIScope))
// 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.TransitiveStubDexJarsByKind[android.SdkTest])
+ android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(TestHiddenAPIScope))
// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
- android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.TransitiveStubDexJarsByKind[android.SdkCorePlatform])
+ android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(CorePlatformHiddenAPIScope))
+
+ // Check the widest stubs.. The list contains the widest stub dex jar provided by each module.
+ expectedWidestPaths := []string{
+ // mycoreplatform's widest API is core platform.
+ corePlatformStubsJar,
+
+ // myothersdklibrary's widest API is public.
+ otherPublicStubsJar,
+
+ // sdklibrary's widest API is system.
+ systemStubsJar,
+
+ // mystublib's only provides one API and so it must be the widest.
+ stubsJar,
+ }
+
+ android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope())
}
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 0e14d24..ecfdfb7 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -89,6 +89,29 @@
maxSdkVersion int32
}
+// gatherPossibleUpdatableModuleNamesAndStems returns a set of module and stem names from the
+// supplied contents that may be in the updatable boot jars.
+//
+// The module names are included because sometimes the stem is set to just change the name of
+// the installed file and it expects the configuration to still use the actual module name.
+//
+// The stem names are included because sometimes the stem is set to change the effective name of the
+// module that is used in the configuration as well,e .g. when a test library is overriding an
+// actual boot jar
+func gatherPossibleUpdatableModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string {
+ set := map[string]struct{}{}
+ for _, name := range contents {
+ dep := ctx.GetDirectDepWithTag(name, tag)
+ set[name] = struct{}{}
+ if m, ok := dep.(ModuleWithStem); ok {
+ set[m.Stem()] = struct{}{}
+ } else {
+ ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
+ }
+ }
+ return android.SortedStringKeys(set)
+}
+
// Converts android.ConfiguredJarList into a list of classpathJars for each given classpathType.
func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, classpaths ...classpathType) []classpathJar {
paths := configuredJars.DevicePaths(ctx.Config(), android.Android)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index bb85784..cb5b6be 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -503,29 +503,47 @@
}
// buildBootImage takes a bootImageConfig, and creates rules to build it.
-func buildBootImage(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) {
- var zipFiles android.Paths
+//
+// It returns a map from android.ArchType to the predefined paths of the boot image files.
+func buildBootImage(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageFilesByArch {
+ filesByArch := bootImageFilesByArch{}
for _, variant := range image.variants {
- files := buildBootImageVariant(ctx, variant, profile)
+ buildBootImageVariant(ctx, variant, profile)
if variant.target.Os == android.Android {
- zipFiles = append(zipFiles, files.Paths()...)
+ filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths()
}
}
- if image.zip != nil {
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- BuiltTool("soong_zip").
- FlagWithOutput("-o ", image.zip).
- FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()).
- FlagWithInputList("-f ", zipFiles, " -f ")
+ return filesByArch
+}
- rule.Build("zip_"+image.name, "zip "+image.name+" image")
+// buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files.
+//
+// The supplied filesByArch is nil when the boot image files have not been generated. Otherwise, it
+// is a map from android.ArchType to the predefined locations.
+func buildBootImageZipInPredefinedLocation(ctx android.ModuleContext, image *bootImageConfig, filesByArch bootImageFilesByArch) {
+ if filesByArch == nil {
+ return
}
+
+ // Compute the list of files from all the architectures.
+ zipFiles := android.Paths{}
+ for _, archType := range android.ArchTypeList() {
+ zipFiles = append(zipFiles, filesByArch[archType]...)
+ }
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("soong_zip").
+ FlagWithOutput("-o ", image.zip).
+ FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()).
+ FlagWithInputList("-f ", zipFiles, " -f ")
+
+ rule.Build("zip_"+image.name, "zip "+image.name+" image")
}
// Generate boot image build rules for a specific target.
-func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) android.WritablePaths {
+func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) {
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
@@ -641,11 +659,8 @@
var vdexInstalls android.RuleBuilderInstalls
var unstrippedInstalls android.RuleBuilderInstalls
- var zipFiles android.WritablePaths
-
for _, artOrOat := range image.moduleFiles(ctx, outputDir, ".art", ".oat") {
cmd.ImplicitOutput(artOrOat)
- zipFiles = append(zipFiles, artOrOat)
// Install the .oat and .art files
rule.Install(artOrOat, filepath.Join(installDir, artOrOat.Base()))
@@ -653,7 +668,6 @@
for _, vdex := range image.moduleFiles(ctx, outputDir, ".vdex") {
cmd.ImplicitOutput(vdex)
- zipFiles = append(zipFiles, vdex)
// Note that the vdex files are identical between architectures.
// Make rules will create symlinks to share them between architectures.
@@ -675,8 +689,6 @@
image.installs = rule.Installs()
image.vdexInstalls = vdexInstalls
image.unstrippedInstalls = unstrippedInstalls
-
- return zipFiles
}
const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
@@ -884,8 +896,9 @@
ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String())
ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String())
}
- imageLocationsOnHost, _ := current.getAnyAndroidVariant().imageLocations()
- ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocationsOnHost, ":"))
+ imageLocationsOnHost, imageLocationsOnDevice := current.getAnyAndroidVariant().imageLocations()
+ ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_HOST"+current.name, strings.Join(imageLocationsOnHost, ":"))
+ ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE"+current.name, strings.Join(imageLocationsOnDevice, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index de72b39..654ebb7 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -20,14 +20,164 @@
"android/soong/android"
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
// Contains support for processing hiddenAPI in a modular fashion.
+// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
+// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
+// not provide the information needed by hidden API processing.
+type HiddenAPIScope struct {
+ // The name of the scope, used for debug purposes.
+ name string
+
+ // The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
+ sdkKind android.SdkKind
+
+ // The option needed to passed to "hiddenapi list".
+ hiddenAPIListOption string
+
+ // The name sof the source stub library modules that contain the API provided by the platform,
+ // i.e. by modules that are not in an APEX.
+ nonUpdatableSourceModule string
+
+ // The names of the prebuilt stub library modules that contain the API provided by the platform,
+ // i.e. by modules that are not in an APEX.
+ nonUpdatablePrebuiltModule string
+}
+
+// initHiddenAPIScope initializes the scope.
+func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
+ sdkKind := apiScope.sdkKind
+ // The platform does not provide a core platform API.
+ if sdkKind != android.SdkCorePlatform {
+ kindAsString := sdkKind.String()
+ var insert string
+ if sdkKind == android.SdkPublic {
+ insert = ""
+ } else {
+ insert = "." + strings.ReplaceAll(kindAsString, "-", "_")
+ }
+
+ nonUpdatableModule := "android-non-updatable"
+
+ // Construct the name of the android-non-updatable source module for this scope.
+ apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert)
+
+ prebuiltModuleName := func(name string, kind string) string {
+ return fmt.Sprintf("sdk_%s_current_%s", kind, name)
+ }
+
+ // Construct the name of the android-non-updatable prebuilt module for this scope.
+ apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString)
+ }
+
+ return apiScope
+}
+
+// android-non-updatable takes the name of a module and returns a possibly scope specific name of
+// the module.
+func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string {
+ // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for
+ // each scope.
+ // TODO(b/192067200): Remove special handling of android-non-updatable.
+ if name == "android-non-updatable" {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
+ return l.nonUpdatablePrebuiltModule
+ } else {
+ return l.nonUpdatableSourceModule
+ }
+ } else {
+ // Assume that the module is either a java_sdk_library (or equivalent) and so will provide
+ // separate stub jars for each scope or is a java_library (or equivalent) in which case it will
+ // have the same stub jar for each scope.
+ return name
+ }
+}
+
+func (l *HiddenAPIScope) String() string {
+ return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
+}
+
+var (
+ PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "public",
+ sdkKind: android.SdkPublic,
+ hiddenAPIListOption: "--public-stub-classpath",
+ })
+ SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "system",
+ sdkKind: android.SdkSystem,
+ hiddenAPIListOption: "--system-stub-classpath",
+ })
+ TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "test",
+ sdkKind: android.SdkTest,
+ hiddenAPIListOption: "--test-stub-classpath",
+ })
+ ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "module-lib",
+ sdkKind: android.SdkModule,
+ })
+ CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "core-platform",
+ sdkKind: android.SdkCorePlatform,
+ hiddenAPIListOption: "--core-platform-stub-classpath",
+ })
+
+ // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
+ // API processing.
+ //
+ // These are roughly in order from narrowest API surface to widest. Widest means the API stubs
+ // with the biggest API surface, e.g. test is wider than system is wider than public.
+ //
+ // Core platform is considered wider than system/module-lib because those modules that provide
+ // core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
+ // because the core platform API is being converted to system/module-lib APIs. In either case the
+ // system/module-lib APIs are subsets of the core platform API.
+ //
+ // This is not strictly in order from narrowest to widest as the Test API is wider than system but
+ // is neither wider or narrower than the module-lib or core platform APIs. However, this works
+ // well enough at the moment.
+ // TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
+ hiddenAPIScopes = []*HiddenAPIScope{
+ PublicHiddenAPIScope,
+ SystemHiddenAPIScope,
+ TestHiddenAPIScope,
+ ModuleLibHiddenAPIScope,
+ CorePlatformHiddenAPIScope,
+ }
+
+ // The HiddenAPIScope instances that are supported by a java_sdk_library.
+ //
+ // CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
+ // for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
+ hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
+ PublicHiddenAPIScope,
+ SystemHiddenAPIScope,
+ TestHiddenAPIScope,
+ ModuleLibHiddenAPIScope,
+ }
+
+ // The HiddenAPIScope instances that are supported by the `hiddenapi list`.
+ hiddenAPIFlagScopes = []*HiddenAPIScope{
+ PublicHiddenAPIScope,
+ SystemHiddenAPIScope,
+ TestHiddenAPIScope,
+ CorePlatformHiddenAPIScope,
+ }
+)
+
type hiddenAPIStubsDependencyTag struct {
blueprint.BaseDependencyTag
- sdkKind android.SdkKind
+
+ // The api scope for which this dependency was added.
+ apiScope *HiddenAPIScope
+
+ // Indicates that the dependency is not for an API provided by the current bootclasspath fragment
+ // but is an additional API provided by a module that is not part of the current bootclasspath
+ // fragment.
+ fromAdditionalDependency bool
}
func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
@@ -38,6 +188,11 @@
}
func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+ // Do not add additional dependencies to the sdk.
+ if b.fromAdditionalDependency {
+ return nil
+ }
+
// If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
// property, otherwise treat if it was specified in the java_header_libs property.
if javaSdkLibrarySdkMemberType.IsInstance(child) {
@@ -65,24 +220,9 @@
var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
-// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
-// API processing.
-//
-// These are in order from narrowest API surface to widest. Widest means the API stubs with the
-// biggest API surface, e.g. test is wider than system is wider than public. Core platform is
-// considered wider than test even though it has no relationship with test because the libraries
-// that provide core platform API don't provide test. While the core platform API is being converted
-// to a system API the system API is still a subset of core platform.
-var hiddenAPIRelevantSdkKinds = []android.SdkKind{
- android.SdkPublic,
- android.SdkSystem,
- android.SdkTest,
- android.SdkCorePlatform,
-}
-
// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
// needed to produce the hidden API monolithic stub flags file.
-func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
+func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
var publicStubModules []string
var systemStubModules []string
var testStubModules []string
@@ -115,22 +255,22 @@
testStubModules = append(testStubModules, "jacoco-stubs")
}
- m := map[android.SdkKind][]string{}
- m[android.SdkPublic] = publicStubModules
- m[android.SdkSystem] = systemStubModules
- m[android.SdkTest] = testStubModules
- m[android.SdkCorePlatform] = corePlatformStubModules
+ m := map[*HiddenAPIScope][]string{}
+ m[PublicHiddenAPIScope] = publicStubModules
+ m[SystemHiddenAPIScope] = systemStubModules
+ m[TestHiddenAPIScope] = testStubModules
+ m[CorePlatformHiddenAPIScope] = corePlatformStubModules
return m
}
// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
-// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
-// identify the source of the dependency.
-func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
+// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
+// tag to identify the source of the dependency.
+func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
module := ctx.Module()
- for _, sdkKind := range hiddenAPIRelevantSdkKinds {
- modules := sdkKindToStubLibModules[sdkKind]
- ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
+ for _, apiScope := range hiddenAPIScopes {
+ modules := apiScopeToStubLibModules[apiScope]
+ ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
}
}
@@ -153,33 +293,21 @@
return dexJar
}
-var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
- android.SdkPublic: "public-stub-classpath",
- android.SdkSystem: "system-stub-classpath",
- android.SdkTest: "test-stub-classpath",
- android.SdkCorePlatform: "core-platform-stub-classpath",
-}
-
-// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
+// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
//
// 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.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
+func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, moduleStubFlagsPaths android.Paths) {
// Singleton rule which applies hiddenapi on all boot class path dex files.
rule := android.NewRuleBuilder(pctx, ctx)
tempPath := tempPathForRestat(ctx, outputPath)
// Find the widest API stubs provided by the fragments on which this depends, if any.
- var dependencyStubDexJars android.Paths
- for i := len(hiddenAPIRelevantSdkKinds) - 1; i >= 0; i-- {
- kind := hiddenAPIRelevantSdkKinds[i]
- stubsForKind := input.DependencyStubDexJarsByKind[kind]
- if len(stubsForKind) != 0 {
- dependencyStubDexJars = stubsForKind
- break
- }
- }
+ dependencyStubDexJars := input.DependencyStubDexJarsByScope.StubDexJarsForWidestAPIScope()
+
+ // Add widest API stubs from the additional dependencies of this, if any.
+ dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.StubDexJarsForWidestAPIScope()...)
command := rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
@@ -187,24 +315,46 @@
FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
FlagForEachInput("--boot-dex=", bootDexJars)
- // Iterate over the sdk kinds in a fixed order.
- for _, sdkKind := range hiddenAPIRelevantSdkKinds {
- // Merge in the stub dex jar paths for this kind from the fragments on which it depends. They
- // will be needed to resolve dependencies from this fragment's stubs to classes in the other
- // fragment's APIs.
- dependencyPaths := input.DependencyStubDexJarsByKind[sdkKind]
- paths := append(dependencyPaths, input.StubDexJarsByKind[sdkKind]...)
+ // If no module stub flags paths are provided then this must be being called for a
+ // bootclasspath_fragment and not the whole platform_bootclasspath.
+ if moduleStubFlagsPaths == nil {
+ // This is being run on a fragment of the bootclasspath.
+ command.Flag("--fragment")
+ }
+
+ // Iterate over the api scopes in a fixed order.
+ for _, apiScope := range hiddenAPIFlagScopes {
+ // Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
+ // They will be needed to resolve dependencies from this fragment's stubs to classes in the
+ // other fragment's APIs.
+ var paths android.Paths
+ paths = append(paths, input.DependencyStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
+ paths = append(paths, input.AdditionalStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
+ paths = append(paths, input.StubDexJarsByScope.StubDexJarsForScope(apiScope)...)
if len(paths) > 0 {
- option := sdkKindToHiddenapiListOption[sdkKind]
- command.FlagWithInputList("--"+option+"=", paths, ":")
+ option := apiScope.hiddenAPIListOption
+ command.FlagWithInputList(option+"=", paths, ":")
}
}
// Add the output path.
command.FlagWithOutput("--out-api-flags=", tempPath)
+ // If there are stub flag files that have been generated by fragments on which this depends then
+ // use them to validate the stub flag file generated by the rules created by this method.
+ if len(moduleStubFlagsPaths) > 0 {
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, moduleStubFlagsPaths)
+
+ // 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)
+ }
+
commitChangeForRestat(rule, tempPath, outputPath)
- return rule
+
+ rule.Build(name, desc)
}
// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
@@ -377,8 +527,9 @@
// that category.
FlagFilesByCategory FlagFilesByCategory
- // The paths to the stub dex jars for each of the android.SdkKind in hiddenAPIRelevantSdkKinds.
- TransitiveStubDexJarsByKind StubDexJarsByKind
+ // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes provided by
+ // this fragment and the fragments on which this depends.
+ TransitiveStubDexJarsByScope StubDexJarsByModule
// The output from the hidden API processing needs to be made available to other modules.
HiddenAPIFlagOutput
@@ -386,8 +537,8 @@
func newHiddenAPIInfo() *HiddenAPIInfo {
info := HiddenAPIInfo{
- FlagFilesByCategory: FlagFilesByCategory{},
- TransitiveStubDexJarsByKind: StubDexJarsByKind{},
+ FlagFilesByCategory: FlagFilesByCategory{},
+ TransitiveStubDexJarsByScope: StubDexJarsByModule{},
}
return &info
}
@@ -398,34 +549,126 @@
for _, fragment := range fragments {
if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
- i.TransitiveStubDexJarsByKind.append(info.TransitiveStubDexJarsByKind)
+ i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
}
}
-
- // Dedup and sort paths.
- i.TransitiveStubDexJarsByKind.dedupAndSort()
}
var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
-// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
-// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
-type StubDexJarsByKind map[android.SdkKind]android.Paths
+// ModuleStubDexJars contains the stub dex jars provided by a single module.
+//
+// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
+// hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
+type ModuleStubDexJars map[*HiddenAPIScope]android.Path
-// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
+// stubDexJarForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
// map.
-func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
- for _, kind := range hiddenAPIRelevantSdkKinds {
- s[kind] = append(s[kind], other[kind]...)
+//
+// The relative width of APIs is determined by their order in hiddenAPIScopes.
+func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
+ for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
+ apiScope := hiddenAPIScopes[i]
+ if stubsForAPIScope, ok := s[apiScope]; ok {
+ return stubsForAPIScope
+ }
+ }
+
+ return nil
+}
+
+// StubDexJarsByModule contains the stub dex jars provided by a set of modules.
+//
+// It maps a module name to the path to the stub dex jars provided by that module.
+type StubDexJarsByModule map[string]ModuleStubDexJars
+
+// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
+func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+
+ // Each named module provides one dex jar for each scope. However, in some cases different API
+ // versions of a single classes are provided by separate modules. e.g. the core platform
+ // version of java.lang.Object is provided by the legacy.art.module.platform.api module but the
+ // public version is provided by the art.module.public.api module. In those cases it is necessary
+ // to treat all those modules as they were the same name, otherwise it will result in multiple
+ // definitions of a single class being passed to hidden API processing which will cause an error.
+ if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
+ // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
+ // java_sdk_library.
+ // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
+ name = "android-non-updatable"
+ } else if name == "legacy.art.module.platform.api" {
+ // Treat legacy.art.module.platform.api as if it was an API scope provided by the
+ // art.module.public.api java_sdk_library which will be the case once the former has been
+ // migrated to a module_lib API.
+ name = "art.module.public.api"
+ } else if name == "legacy.i18n.module.platform.api" {
+ // Treat legacy.i18n.module.platform.api as if it was an API scope provided by the
+ // i18n.module.public.api java_sdk_library which will be the case once the former has been
+ // migrated to a module_lib API.
+ name = "i18n.module.public.api"
+ } else if name == "conscrypt.module.platform.api" {
+ // Treat conscrypt.module.platform.api as if it was an API scope provided by the
+ // conscrypt.module.public.api java_sdk_library which will be the case once the former has been
+ // migrated to a module_lib API.
+ name = "conscrypt.module.public.api"
+ } else if d, ok := module.(SdkLibraryComponentDependency); ok {
+ sdkLibraryName := d.SdkLibraryName()
+ if sdkLibraryName != nil {
+ // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
+ // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
+ // use `foo` as the name.
+ name = *sdkLibraryName
+ }
+ }
+ stubDexJarsByScope := s[name]
+ if stubDexJarsByScope == nil {
+ stubDexJarsByScope = ModuleStubDexJars{}
+ s[name] = stubDexJarsByScope
+ }
+ stubDexJarsByScope[scope] = stubDexJar
+}
+
+// addStubDexJarsByModule adds the stub dex jars in the supplied StubDexJarsByModule to this map.
+func (s StubDexJarsByModule) addStubDexJarsByModule(other StubDexJarsByModule) {
+ for module, stubDexJarsByScope := range other {
+ s[module] = stubDexJarsByScope
}
}
-// dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
-// deterministic order.
-func (s StubDexJarsByKind) dedupAndSort() {
- for kind, paths := range s {
- s[kind] = android.SortedUniquePaths(paths)
+// StubDexJarsForWidestAPIScope returns a list of stub dex jars containing the widest API scope
+// provided by each module.
+//
+// The relative width of APIs is determined by their order in hiddenAPIScopes.
+func (s StubDexJarsByModule) StubDexJarsForWidestAPIScope() android.Paths {
+ stubDexJars := android.Paths{}
+ modules := android.SortedStringKeys(s)
+ for _, module := range modules {
+ stubDexJarsByScope := s[module]
+
+ stubDexJars = append(stubDexJars, stubDexJarsByScope.stubDexJarForWidestAPIScope())
}
+
+ return stubDexJars
+}
+
+// StubDexJarsForScope returns a list of stub dex jars containing the stub dex jars provided by each
+// module for the specified scope.
+//
+// If a module does not provide a stub dex jar for the supplied scope then it does not contribute to
+// the returned list.
+func (s StubDexJarsByModule) StubDexJarsForScope(scope *HiddenAPIScope) android.Paths {
+ stubDexJars := android.Paths{}
+ modules := android.SortedStringKeys(s)
+ for _, module := range modules {
+ stubDexJarsByScope := s[module]
+ // Not every module will have the same set of
+ if jars, ok := stubDexJarsByScope[scope]; ok {
+ stubDexJars = append(stubDexJars, jars)
+ }
+ }
+
+ return stubDexJars
}
// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
@@ -435,14 +678,21 @@
// from the stub dex files.
FlagFilesByCategory FlagFilesByCategory
- // StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
+ // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
// the initial flags for each dex member.
- StubDexJarsByKind StubDexJarsByKind
+ StubDexJarsByScope StubDexJarsByModule
- // DependencyStubDexJarsByKind contains the stub dex jars provided by the fragments on which this
- // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByKind from each
+ // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
+ // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
// fragment on which this depends.
- DependencyStubDexJarsByKind StubDexJarsByKind
+ DependencyStubDexJarsByScope StubDexJarsByModule
+
+ // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
+ // the ones that are obtained from fragments on which this depends.
+ //
+ // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
+ // as there are not propagated transitively to other fragments that depend on this.
+ AdditionalStubDexJarsByScope StubDexJarsByModule
// RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
// specified in the bootclasspath_fragment's stub_libs and contents properties.
@@ -452,62 +702,29 @@
// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
func newHiddenAPIFlagInput() HiddenAPIFlagInput {
input := HiddenAPIFlagInput{
- FlagFilesByCategory: FlagFilesByCategory{},
- StubDexJarsByKind: StubDexJarsByKind{},
+ FlagFilesByCategory: FlagFilesByCategory{},
+ StubDexJarsByScope: StubDexJarsByModule{},
+ DependencyStubDexJarsByScope: StubDexJarsByModule{},
+ AdditionalStubDexJarsByScope: StubDexJarsByModule{},
}
return input
}
-// canPerformHiddenAPIProcessing determines whether hidden API processing should be performed.
-//
-// A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
-// appropriate information needed for hidden API processing breaking the build.
-// TODO(b/179354495): Remove this workaround.
-func (i *HiddenAPIFlagInput) canPerformHiddenAPIProcessing(ctx android.ModuleContext, properties bootclasspathFragmentProperties) bool {
- // Performing hidden API processing without stubs is not supported and it is unlikely to ever be
- // required as the whole point of adding something to the bootclasspath fragment is to add it to
- // the bootclasspath in order to be used by something else in the system. Without any stubs it
- // cannot do that.
- if len(i.StubDexJarsByKind) == 0 {
- return false
- }
-
- // Hidden API processing is always enabled in tests.
- if ctx.Config().TestProductVariables != nil {
- return true
- }
-
- // A module that has fragments should have access to the information it needs in order to perform
- // hidden API processing.
- if len(properties.Fragments) != 0 {
- return true
- }
-
- // The art bootclasspath fragment does not depend on any other fragments but already supports
- // hidden API processing.
- imageName := proptools.String(properties.Image_name)
- if imageName == "art" {
- return true
- }
-
- // Disable it for everything else.
- return false
-}
-
// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
// dependencies added in hiddenAPIAddStubLibDependencies.
//
// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
- addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
- dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
+ addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
+ sdkKind := apiScope.sdkKind
+ dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
if dexJar != nil {
- i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
+ i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
}
if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
- removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, kind)
+ removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
}
}
@@ -515,25 +732,29 @@
// If the contents includes any java_sdk_library modules then add them to the stubs.
for _, module := range contents {
if _, ok := module.(SdkLibraryDependency); ok {
- // Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
- // as the java_sdk_library does not have special support for core_platform API, instead it is
- // implemented as a customized form of SdkPublic.
- for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
- addFromModule(ctx, module, kind)
+ // Add information for every possible API scope needed by hidden API.
+ for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+ addFromModule(ctx, module, apiScope)
}
}
}
- ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
+ ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
- kind := hiddenAPIStubsTag.sdkKind
- addFromModule(ctx, module, kind)
+ apiScope := hiddenAPIStubsTag.apiScope
+ if hiddenAPIStubsTag.fromAdditionalDependency {
+ dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
+ if dexJar != nil {
+ i.AdditionalStubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
+ }
+ } else {
+ addFromModule(ctx, module, apiScope)
+ }
}
})
// Normalize the paths, i.e. remove duplicates and sort.
- i.StubDexJarsByKind.dedupAndSort()
i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
}
@@ -546,9 +767,9 @@
}
}
-func (i *HiddenAPIFlagInput) transitiveStubDexJarsByKind() StubDexJarsByKind {
- transitive := i.DependencyStubDexJarsByKind
- transitive.append(i.StubDexJarsByKind)
+func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByModule {
+ transitive := i.DependencyStubDexJarsByScope
+ transitive.addStubDexJarsByModule(i.StubDexJarsByScope)
return transitive
}
@@ -634,38 +855,16 @@
// hiddenAPIInfo 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,
+ outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
- // 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 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).
- Input(annotationFlags).
+ Inputs(annotationFlagPaths).
FlagWithOutput("--output ", tempPath)
// Add the options for the different categories of flag files.
@@ -684,7 +883,11 @@
commitChangeForRestat(rule, tempPath, outputPath)
- if validFile != nil {
+ // 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 len(allFlagsPaths) > 0 {
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, allFlagsPaths)
+
// 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
@@ -695,6 +898,25 @@
rule.Build(name, desc)
}
+// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
+// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
+func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, modularFilePaths android.Paths) android.WritablePath {
+ // The file which is used to record that the flags file is valid.
+ validFile := pathForValidation(ctx, monolithicFilePath)
+
+ // Create a rule to validate the output from the following rule.
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("verify_overlaps").
+ Input(monolithicFilePath).
+ Inputs(modularFilePaths).
+ // If validation passes then update the file that records that.
+ Text("&& touch").Output(validFile)
+ rule.Build(name+"Validation", desc+" validation")
+
+ return validFile
+}
+
// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
// bootclasspath and then encode the flags into the boot dex files.
//
@@ -718,8 +940,7 @@
// Generate the stub-flags.csv.
stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
- rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input)
- rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
+ buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
// Extract the classes jars from the contents.
classesJars := extractClassesJarsFromModules(contents)
@@ -747,7 +968,7 @@
// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
// files.
allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
- buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil, removedDexSignatures)
+ buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
// Encode the flags into the boot dex files.
encodedBootDexJarsByModule := map[string]android.Path{}
@@ -903,6 +1124,14 @@
return true
}
+ // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
+ // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
+ // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
+ // failures missing boot dex jars need to be deferred.
+ if android.IsModuleInVersionedSdk(ctx.Module()) {
+ return true
+ }
+
// This is called for both platform_bootclasspath and bootclasspath_fragment modules.
//
// A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
@@ -939,6 +1168,14 @@
//
// TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
if android.IsModulePrebuilt(module) {
+ // An inactive source module can still contribute to the APEX but an inactive prebuilt module
+ // should not contribute to anything. So, rather than have a missing dex jar cause a Soong
+ // failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
+ // built Ninja should never use the dex jar file.
+ if !isActiveModule(module) {
+ return true
+ }
+
if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
if apexInfo.IsForPlatform() {
@@ -947,14 +1184,6 @@
}
}
- // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
- // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
- // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
- // failures missing boot dex jars need to be deferred.
- if android.IsModuleInVersionedSdk(ctx.Module()) {
- return true
- }
-
return false
}
diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go
index edf4235..52f0770 100644
--- a/java/hiddenapi_monolithic.go
+++ b/java/hiddenapi_monolithic.go
@@ -43,22 +43,45 @@
// The paths to the generated all-flags.csv files.
AllFlagsPaths android.Paths
+
+ // The classes jars from the libraries on the platform bootclasspath.
+ ClassesJars android.Paths
}
// newMonolithicHiddenAPIInfo creates a new MonolithicHiddenAPIInfo from the flagFilesByCategory
// plus information provided by each of the fragments.
-func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory FlagFilesByCategory, fragments []android.Module) MonolithicHiddenAPIInfo {
+func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory FlagFilesByCategory, classpathElements ClasspathElements) MonolithicHiddenAPIInfo {
monolithicInfo := MonolithicHiddenAPIInfo{}
monolithicInfo.FlagsFilesByCategory = flagFilesByCategory
- // Merge all the information from the fragments. The fragments form a DAG so it is possible that
- // this will introduce duplicates so they will be resolved after processing all the fragments.
- for _, fragment := range fragments {
- if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
- info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
- monolithicInfo.append(&info)
+ // Merge all the information from the classpathElements. The fragments form a DAG so it is possible that
+ // this will introduce duplicates so they will be resolved after processing all the classpathElements.
+ for _, element := range classpathElements {
+ var classesJars android.Paths
+ switch e := element.(type) {
+ case *ClasspathLibraryElement:
+ classesJars = retrieveClassesJarsFromModule(e.Module())
+
+ case *ClasspathFragmentElement:
+ fragment := e.Module()
+ if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
+ info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ monolithicInfo.append(&info)
+
+ // If the bootclasspath fragment actually perform hidden API processing itself then use the
+ // CSV files it provides and do not bother processing the classesJars files. This ensures
+ // consistent behavior between source and prebuilt as prebuilt modules do not provide
+ // classesJars.
+ if info.AllFlagsPath != nil {
+ continue
+ }
+ }
+
+ classesJars = extractClassesJarsFromModules(e.Contents)
}
+
+ monolithicInfo.ClassesJars = append(monolithicInfo.ClassesJars, classesJars...)
}
// Dedup paths.
diff --git a/java/java.go b/java/java.go
index ae8adf2..71c1b33 100644
--- a/java/java.go
+++ b/java/java.go
@@ -643,7 +643,7 @@
module.addHostAndDeviceProperties()
- module.initModuleAndImport(&module.ModuleBase)
+ module.initModuleAndImport(module)
android.InitApexModule(module)
android.InitSdkAwareModule(module)
@@ -1496,7 +1496,7 @@
&module.dexer.dexProperties,
)
- module.initModuleAndImport(&module.ModuleBase)
+ module.initModuleAndImport(module)
module.dexProperties.Optimize.EnabledByDefault = false
diff --git a/java/lint.go b/java/lint.go
index 1511cfe..fe3218e 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -78,6 +78,7 @@
minSdkVersion string
targetSdkVersion string
compileSdkVersion string
+ compileSdkKind android.SdkKind
javaLanguageLevel string
kotlinLanguageLevel string
outputs lintOutputs
@@ -389,13 +390,26 @@
rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Command().Text("rm -f").Output(html).Output(text).Output(xml)
+ var apiVersionsName, apiVersionsPrebuilt string
+ if l.compileSdkKind == android.SdkModule || l.compileSdkKind == android.SdkSystemServer {
+ // When compiling an SDK module (or system server) we use the filtered
+ // database because otherwise lint's
+ // NewApi check produces too many false positives; This database excludes information
+ // about classes created in mainline modules hence removing those false positives.
+ apiVersionsName = "api_versions_public_filtered.xml"
+ apiVersionsPrebuilt = "prebuilts/sdk/current/public/data/api-versions-filtered.xml"
+ } else {
+ apiVersionsName = "api_versions.xml"
+ apiVersionsPrebuilt = "prebuilts/sdk/current/public/data/api-versions.xml"
+ }
+
var annotationsZipPath, apiVersionsXMLPath android.Path
if ctx.Config().AlwaysUsePrebuiltSdks() {
annotationsZipPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/annotations.zip")
- apiVersionsXMLPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/api-versions.xml")
+ apiVersionsXMLPath = android.PathForSource(ctx, apiVersionsPrebuilt)
} else {
annotationsZipPath = copiedAnnotationsZipPath(ctx)
- apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
+ apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx, apiVersionsName)
}
cmd := rule.Command()
@@ -487,23 +501,27 @@
l.copyLintDependencies(ctx)
}
+func findModuleOrErr(ctx android.SingletonContext, moduleName string) android.Module {
+ var res android.Module
+ ctx.VisitAllModules(func(m android.Module) {
+ if ctx.ModuleName(m) == moduleName {
+ if res == nil {
+ res = m
+ } else {
+ ctx.Errorf("lint: multiple %s modules found: %s and %s", moduleName,
+ ctx.ModuleSubDir(m), ctx.ModuleSubDir(res))
+ }
+ }
+ })
+ return res
+}
+
func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
if ctx.Config().AlwaysUsePrebuiltSdks() {
return
}
- var frameworkDocStubs android.Module
- ctx.VisitAllModules(func(m android.Module) {
- if ctx.ModuleName(m) == "framework-doc-stubs" {
- if frameworkDocStubs == nil {
- frameworkDocStubs = m
- } else {
- ctx.Errorf("lint: multiple framework-doc-stubs modules found: %s and %s",
- ctx.ModuleSubDir(m), ctx.ModuleSubDir(frameworkDocStubs))
- }
- }
- })
-
+ frameworkDocStubs := findModuleOrErr(ctx, "framework-doc-stubs")
if frameworkDocStubs == nil {
if !ctx.Config().AllowMissingDependencies() {
ctx.Errorf("lint: missing framework-doc-stubs")
@@ -511,6 +529,14 @@
return
}
+ filteredDb := findModuleOrErr(ctx, "api-versions-xml-public-filtered")
+ if filteredDb == nil {
+ if !ctx.Config().AllowMissingDependencies() {
+ ctx.Errorf("lint: missing api-versions-xml-public-filtered")
+ }
+ return
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: android.CpIfChanged,
Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"),
@@ -520,7 +546,13 @@
ctx.Build(pctx, android.BuildParams{
Rule: android.CpIfChanged,
Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"),
- Output: copiedAPIVersionsXmlPath(ctx),
+ Output: copiedAPIVersionsXmlPath(ctx, "api_versions.xml"),
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: android.OutputFileForModule(ctx, filteredDb, ""),
+ Output: copiedAPIVersionsXmlPath(ctx, "api_versions_public_filtered.xml"),
})
}
@@ -528,8 +560,8 @@
return android.PathForOutput(ctx, "lint", "annotations.zip")
}
-func copiedAPIVersionsXmlPath(ctx android.PathContext) android.WritablePath {
- return android.PathForOutput(ctx, "lint", "api_versions.xml")
+func copiedAPIVersionsXmlPath(ctx android.PathContext, name string) android.WritablePath {
+ return android.PathForOutput(ctx, "lint", name)
}
func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
diff --git a/java/lint_test.go b/java/lint_test.go
index 6d64de7..456e6ba 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -219,3 +219,78 @@
t.Error("did not restrict baselining NewApi")
}
}
+
+func TestJavaLintDatabaseSelectionFull(t *testing.T) {
+ testCases := []string{
+ "current", "core_platform", "system_current", "S", "30", "10000",
+ }
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "XXX",
+ lint: {
+ strict_updatability_linting: true,
+ },
+ }
+`
+ for _, testCase := range testCases {
+ thisBp := strings.Replace(bp, "XXX", testCase, 1)
+
+ result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"foo"},
+ "10000": {"foo"},
+ })).
+ RunTestWithBp(t, thisBp)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions_public_filtered.xml") {
+ t.Error("used public-filtered lint api database for case", testCase)
+ }
+ if !strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions.xml") {
+ t.Error("did not use full api database for case", testCase)
+ }
+ }
+
+}
+
+func TestJavaLintDatabaseSelectionPublicFiltered(t *testing.T) {
+ testCases := []string{
+ "module_current", "system_server_current",
+ }
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "module_current",
+ lint: {
+ strict_updatability_linting: true,
+ },
+ }
+`
+ for _, testCase := range testCases {
+ thisBp := strings.Replace(bp, "XXX", testCase, 1)
+ result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules).
+ RunTestWithBp(t, thisBp)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions_public_filtered.xml") {
+ t.Error("did not use public-filtered lint api database for case", testCase)
+ }
+ if strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions.xml") {
+ t.Error("used full api database for case", testCase)
+ }
+ }
+}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 48da29e..cb92922 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -44,13 +44,9 @@
properties platformBootclasspathProperties
// The apex:module pairs obtained from the configured modules.
- //
- // Currently only for testing.
configuredModules []android.Module
// The apex:module pairs obtained from the fragments.
- //
- // Currently only for testing.
fragments []android.Module
// Path to the monolithic hiddenapi-flags.csv file.
@@ -123,8 +119,8 @@
}
// Add dependencies onto the stub lib modules.
- sdkKindToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
- hiddenAPIAddStubLibDependencies(ctx, sdkKindToStubLibModules)
+ apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
+ hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules)
}
func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -282,8 +278,16 @@
return bootDexJarByModule
}
- monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments)
- // Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile
+ // Construct a list of ClasspathElement objects from the modules and fragments.
+ classpathElements := CreateClasspathElements(ctx, modules, fragments)
+
+ monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, classpathElements)
+
+ // Extract the classes jars only from those libraries that do not have corresponding fragments as
+ // the fragments will have already provided the flags that are needed.
+ classesJars := monolithicInfo.ClassesJars
+
+ // Create the input to pass to buildRuleToGenerateHiddenAPIStubFlagsFile
input := newHiddenAPIFlagInput()
// Gather stub library information from the dependencies on modules provided by
@@ -295,42 +299,58 @@
// Generate the monolithic stub-flags.csv file.
stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
- rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJarByModule.bootDexJars(), input)
- rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
-
- // Extract the classes jars from the contents.
- classesJars := extractClassesJarsFromModules(modules)
+ buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags", stubFlags, bootDexJarByModule.bootDexJars(), input, monolithicInfo.StubFlagsPaths)
// 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)
+ annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags-from-classes.csv")
+ buildRuleToGenerateAnnotationFlags(ctx, "intermediate hidden API flags", classesJars, stubFlags, annotationFlags)
- // Generate the monotlithic hiddenapi-flags.csv file.
+ // Generate the monolithic hiddenapi-flags.csv file.
+ //
+ // Use annotation flags generated directly from the classes jars as well as annotation flag files
+ // provided by prebuilts.
+ allAnnotationFlagFiles := android.Paths{annotationFlags}
+ allAnnotationFlagFiles = append(allAnnotationFlagFiles, monolithicInfo.AnnotationFlagsPaths...)
allFlags := hiddenAPISingletonPaths(ctx).flags
- buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "hiddenapi flags", allFlags, stubFlags, annotationFlags, monolithicInfo.FlagsFilesByCategory, monolithicInfo.AllFlagsPaths, android.OptionalPath{})
+ buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "monolithic hidden API flags", allFlags, stubFlags, allAnnotationFlagFiles, monolithicInfo.FlagsFilesByCategory, monolithicInfo.AllFlagsPaths, android.OptionalPath{})
// 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)
+ intermediateMetadataCSV := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "metadata-from-classes.csv")
+ buildRuleToGenerateMetadata(ctx, "intermediate 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.
+ // Generate the monolithic hiddenapi-metadata.csv file.
+ //
+ // Use metadata files generated directly from the classes jars as well as metadata files provided
+ // by prebuilts.
+ //
+ // This has the side effect of ensuring that the output file uses | quotes just in case that is
+ // important for the tools that consume the metadata file.
+ allMetadataFlagFiles := android.Paths{intermediateMetadataCSV}
+ allMetadataFlagFiles = append(allMetadataFlagFiles, monolithicInfo.MetadataPaths...)
metadataCSV := hiddenAPISingletonPaths(ctx).metadata
- b.buildRuleMergeCSV(ctx, "reformat monolithic hidden API metadata", android.Paths{intermediateMetadataCSV}, metadataCSV)
+ b.buildRuleMergeCSV(ctx, "monolithic hidden API metadata", allMetadataFlagFiles, metadataCSV)
- // Generate the monolithic hiddenapi-index.csv file directly from the CSV files in the classes
- // jars.
+ // Generate an intermediate monolithic hiddenapi-index.csv file directly from the CSV files in the
+ // classes jars.
+ intermediateIndexCSV := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "index-from-classes.csv")
+ buildRuleToGenerateIndex(ctx, "intermediate hidden API index", classesJars, intermediateIndexCSV)
+
+ // Generate the monolithic hiddenapi-index.csv file.
+ //
+ // Use index files generated directly from the classes jars as well as index files provided
+ // by prebuilts.
+ allIndexFlagFiles := android.Paths{intermediateIndexCSV}
+ allIndexFlagFiles = append(allIndexFlagFiles, monolithicInfo.IndexPaths...)
indexCSV := hiddenAPISingletonPaths(ctx).index
- buildRuleToGenerateIndex(ctx, "monolithic hidden API index", classesJars, indexCSV)
+ b.buildRuleMergeCSV(ctx, "monolithic hidden API index", allIndexFlagFiles, indexCSV)
return bootDexJarByModule
}
// createAndProvideMonolithicHiddenAPIInfo creates a MonolithicHiddenAPIInfo and provides it for
// testing.
-func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, fragments []android.Module) MonolithicHiddenAPIInfo {
+func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, classpathElements ClasspathElements) MonolithicHiddenAPIInfo {
// Create a temporary input structure in which to collate information provided directly by this
// module, either through properties or direct dependencies.
temporaryInput := newHiddenAPIFlagInput()
@@ -340,7 +360,7 @@
// Create the monolithic info, by starting with the flag files specified on this and then merging
// in information from all the fragment dependencies of this.
- monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, fragments)
+ monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, classpathElements)
// Store the information for testing.
ctx.SetProvider(MonolithicHiddenAPIInfoProvider, monolithicInfo)
@@ -401,7 +421,10 @@
// Build a profile for the image config and then use that to build the boot image.
profile := bootImageProfileRule(ctx, imageConfig)
- buildBootImage(ctx, imageConfig, profile)
+ bootImageFilesByArch := buildBootImage(ctx, imageConfig, profile)
+
+ // Zip the boot image files up.
+ buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFilesByArch)
dumpOatRules(ctx, imageConfig)
}
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 0318a07..1c2a3ae 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -318,11 +318,41 @@
// Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that
// creates the index.csv file.
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
-`,
- indexRule)
+
+ var rule android.TestingBuildParams
+
+ // All the intermediate rules use the same inputs.
+ expectedIntermediateInputs := `
+ out/soong/.intermediates/bar/android_common/javac/bar.jar
+ out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar
+ out/soong/.intermediates/foo/android_common/javac/foo.jar
+ `
+
+ // Check flags output.
+ rule = platformBootclasspath.Output("hiddenapi-monolithic/annotation-flags-from-classes.csv")
+ CheckHiddenAPIRuleInputs(t, "intermediate flags", expectedIntermediateInputs, rule)
+
+ rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-flags.csv")
+ CheckHiddenAPIRuleInputs(t, "monolithic flags", `
+ out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv
+ out/soong/hiddenapi/hiddenapi-stub-flags.txt
+ `, rule)
+
+ // Check metadata output.
+ rule = platformBootclasspath.Output("hiddenapi-monolithic/metadata-from-classes.csv")
+ CheckHiddenAPIRuleInputs(t, "intermediate metadata", expectedIntermediateInputs, rule)
+
+ rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv")
+ CheckHiddenAPIRuleInputs(t, "monolithic metadata", `
+ out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv
+ `, rule)
+
+ // Check index output.
+ rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv")
+ CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule)
+
+ rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-index.csv")
+ CheckHiddenAPIRuleInputs(t, "monolithic index", `
+ out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
+ `, rule)
}
diff --git a/java/sdk.go b/java/sdk.go
index cbd873d..d1b899e 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -175,10 +175,24 @@
}
case android.SdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx))
+ return sdkDep{
+ useModule: true,
+ bootclasspath: []string{"android_module_lib_stubs_current", config.DefaultLambdaStubsLibrary},
+ systemModules: "core-module-lib-stubs-system-modules",
+ java9Classpath: []string{"android_module_lib_stubs_current"},
+ frameworkResModule: "framework-res",
+ aidl: android.OptionalPathForPath(nonUpdatableFrameworkAidlPath(ctx)),
+ }
case android.SdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ return sdkDep{
+ useModule: true,
+ bootclasspath: []string{"android_system_server_stubs_current", config.DefaultLambdaStubsLibrary},
+ systemModules: "core-module-lib-stubs-system-modules",
+ java9Classpath: []string{"android_system_server_stubs_current"},
+ frameworkResModule: "framework-res",
+ aidl: android.OptionalPathForPath(sdkFrameworkAidlPath(ctx)),
+ }
default:
panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 1213d3f..d7f53ec 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -631,9 +631,17 @@
Doctag_files []string `android:"path"`
}
+// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
+// embeds the commonToSdkLibraryAndImport struct.
+type commonSdkLibraryAndImportModule interface {
+ android.SdkAware
+
+ BaseModuleName() string
+}
+
// Common code between sdk library and sdk library import
type commonToSdkLibraryAndImport struct {
- moduleBase *android.ModuleBase
+ module commonSdkLibraryAndImportModule
scopePaths map[*apiScope]*scopePaths
@@ -648,13 +656,13 @@
EmbeddableSdkLibraryComponent
}
-func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) {
- c.moduleBase = moduleBase
+func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
+ c.module = module
- moduleBase.AddProperties(&c.commonSdkLibraryProperties)
+ module.AddProperties(&c.commonSdkLibraryProperties)
// Initialize this as an sdk library component.
- c.initSdkLibraryComponent(moduleBase)
+ c.initSdkLibraryComponent(module)
}
func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool {
@@ -667,44 +675,56 @@
return false
}
+ namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
+
// Only track this sdk library if this can be used as a shared library.
if c.sharedLibrary() {
// Use the name specified in the module definition as the owner.
- c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName())
+ c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = namePtr
}
return true
}
+// uniqueApexVariations provides common implementation of the ApexModule.UniqueApexVariations
+// method.
+func (c *commonToSdkLibraryAndImport) uniqueApexVariations() bool {
+ // A java_sdk_library that is a shared library produces an XML file that makes the shared library
+ // usable from an AndroidManifest.xml's <uses-library> entry. That XML file contains the name of
+ // the APEX and so it needs a unique variation per APEX.
+ return c.sharedLibrary()
+}
+
func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) {
c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
}
// Module name of the runtime implementation library
func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
- return c.moduleBase.BaseModuleName() + ".impl"
+ return c.module.BaseModuleName() + ".impl"
}
// Module name of the XML file for the lib
func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
- return c.moduleBase.BaseModuleName() + sdkXmlFileSuffix
+ return c.module.BaseModuleName() + sdkXmlFileSuffix
}
// Name of the java_library module that compiles the stubs source.
func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
- return c.namingScheme.stubsLibraryModuleName(apiScope, c.moduleBase.BaseModuleName())
+ baseName := c.module.BaseModuleName()
+ return c.module.SdkMemberComponentName(baseName, func(name string) string {
+ return c.namingScheme.stubsLibraryModuleName(apiScope, name)
+ })
}
// Name of the droidstubs module that generates the stubs source and may also
// generate/check the API.
func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
- return c.namingScheme.stubsSourceModuleName(apiScope, c.moduleBase.BaseModuleName())
-}
-
-// Name of the droidstubs module that generates/checks the API. Only used if it
-// requires different arts to the stubs source generating module.
-func (c *commonToSdkLibraryAndImport) apiModuleName(apiScope *apiScope) string {
- return c.namingScheme.apiModuleName(apiScope, c.moduleBase.BaseModuleName())
+ baseName := c.module.BaseModuleName()
+ return c.module.SdkMemberComponentName(baseName, func(name string) string {
+ return c.namingScheme.stubsSourceModuleName(apiScope, name)
+ })
}
// The component names for different outputs of the java_sdk_library.
@@ -753,7 +773,7 @@
if scope, ok := scopeByName[scopeName]; ok {
paths := c.findScopePaths(scope)
if paths == nil {
- return nil, fmt.Errorf("%q does not provide api scope %s", c.moduleBase.BaseModuleName(), scopeName)
+ return nil, fmt.Errorf("%q does not provide api scope %s", c.module.BaseModuleName(), scopeName)
}
switch component {
@@ -784,7 +804,7 @@
if c.doctagPaths != nil {
return c.doctagPaths, nil
} else {
- return nil, fmt.Errorf("no doctag_files specified on %s", c.moduleBase.BaseModuleName())
+ return nil, fmt.Errorf("no doctag_files specified on %s", c.module.BaseModuleName())
}
}
return nil, nil
@@ -830,7 +850,7 @@
// If a specific numeric version has been requested then use prebuilt versions of the sdk.
if !sdkVersion.ApiLevel.IsPreview() {
- return PrebuiltJars(ctx, c.moduleBase.BaseModuleName(), sdkVersion)
+ return PrebuiltJars(ctx, c.module.BaseModuleName(), sdkVersion)
}
paths := c.selectScopePaths(ctx, sdkVersion.Kind)
@@ -857,7 +877,7 @@
scopes = append(scopes, s.name)
}
}
- ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.moduleBase.BaseModuleName(), scopes)
+ ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.BaseModuleName(), scopes)
return nil
}
@@ -905,15 +925,19 @@
func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
componentProps := &struct {
+ SdkLibraryName *string
SdkLibraryToImplicitlyTrack *string
}{}
+ namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ componentProps.SdkLibraryName = namePtr
+
if c.sharedLibrary() {
// Mark the stubs library as being components of this java_sdk_library so that
// any app that includes code which depends (directly or indirectly) on the stubs
// library will have the appropriate <uses-library> invocation inserted into its
// manifest if necessary.
- componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName())
+ componentProps.SdkLibraryToImplicitlyTrack = namePtr
}
return componentProps
@@ -932,6 +956,8 @@
// Properties related to the use of a module as an component of a java_sdk_library.
type SdkLibraryComponentProperties struct {
+ // The name of the java_sdk_library/_import module.
+ SdkLibraryName *string `blueprint:"mutated"`
// The name of the java_sdk_library/_import to add to a <uses-library> entry
// in the AndroidManifest.xml of any Android app that includes code that references
@@ -945,8 +971,13 @@
sdkLibraryComponentProperties SdkLibraryComponentProperties
}
-func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) {
- moduleBase.AddProperties(&e.sdkLibraryComponentProperties)
+func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.Module) {
+ module.AddProperties(&e.sdkLibraryComponentProperties)
+}
+
+// to satisfy SdkLibraryComponentDependency
+func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string {
+ return e.sdkLibraryComponentProperties.SdkLibraryName
}
// to satisfy SdkLibraryComponentDependency
@@ -965,6 +996,9 @@
type SdkLibraryComponentDependency interface {
UsesLibraryDependency
+ // SdkLibraryName returns the name of the java_sdk_library/_import module.
+ SdkLibraryName() *string
+
// The optional name of the sdk library that should be implicitly added to the
// AndroidManifest of an app that contains code which references the sdk library.
//
@@ -1168,6 +1202,10 @@
module.Library.GenerateAndroidBuildActions(ctx)
}
+ // Collate the components exported by this module. All scope specific modules are exported but
+ // the impl and xml component modules are not.
+ exportedComponents := map[string]struct{}{}
+
// Record the paths to the header jars of the library (stubs and impl).
// When this java_sdk_library is depended upon from others via "libs" property,
// the recorded paths will be returned depending on the link type of the caller.
@@ -1182,8 +1220,14 @@
// Extract information from the dependency. The exact information extracted
// is determined by the nature of the dependency which is determined by the tag.
scopeTag.extractDepInfo(ctx, to, scopePaths)
+
+ exportedComponents[ctx.OtherModuleName(to)] = struct{}{}
}
})
+
+ // Make the set of components exported by this module available for use elsewhere.
+ exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedStringKeys(exportedComponents)}
+ ctx.SetProvider(android.ExportedComponentsInfoProvider, exportedComponentInfo)
}
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
@@ -1510,6 +1554,7 @@
mctx.CreateModule(DroidstubsFactory, &props)
}
+// Implements android.ApexModule
func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
depTag := mctx.OtherModuleDependencyTag(dep)
if depTag == xmlPermissionsFileTag {
@@ -1518,6 +1563,11 @@
return module.Library.DepIsInSameApex(mctx, dep)
}
+// Implements android.ApexModule
+func (module *SdkLibrary) UniqueApexVariations() bool {
+ return module.uniqueApexVariations()
+}
+
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
props := struct {
@@ -1709,7 +1759,7 @@
module.addHostAndDeviceProperties()
module.AddProperties(&module.sdkLibraryProperties)
- module.initSdkLibraryComponent(&module.ModuleBase)
+ module.initSdkLibraryComponent(module)
module.properties.Installable = proptools.BoolPtr(true)
module.deviceProperties.IsSDKLibrary = true
@@ -1728,8 +1778,6 @@
stubsLibraryModuleName(scope *apiScope, baseName string) string
stubsSourceModuleName(scope *apiScope, baseName string) string
-
- apiModuleName(scope *apiScope, baseName string) string
}
type defaultNamingScheme struct {
@@ -1743,10 +1791,6 @@
return scope.stubsSourceModuleName(baseName)
}
-func (s *defaultNamingScheme) apiModuleName(scope *apiScope, baseName string) string {
- return scope.apiModuleName(baseName)
-}
-
var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)
func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
@@ -1780,7 +1824,7 @@
module := &SdkLibrary{}
// Initialize information common between source and prebuilt.
- module.initCommon(&module.ModuleBase)
+ module.initCommon(module)
module.InitSdkLibraryProperties()
android.InitApexModule(module)
@@ -1928,7 +1972,7 @@
module.AddProperties(&module.properties, allScopeProperties)
// Initialize information common between source and prebuilt.
- module.initCommon(&module.ModuleBase)
+ module.initCommon(module)
android.InitPrebuiltModule(module, &[]string{""})
android.InitApexModule(module)
@@ -2074,6 +2118,11 @@
return nil
}
+// Implements android.ApexModule
+func (module *SdkLibraryImport) UniqueApexVariations() bool {
+ return module.uniqueApexVariations()
+}
+
func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
return module.commonOutputFiles(tag)
}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 2520dde..65af953 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -110,7 +110,7 @@
`)
// check the existence of the internal modules
- result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests("foo", "android_common")
result.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common")
result.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common")
result.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common")
@@ -122,6 +122,17 @@
result.ModuleForTests("foo.api.system.28", "")
result.ModuleForTests("foo.api.test.28", "")
+ exportedComponentsInfo := result.ModuleProvider(foo.Module(), ExportedComponentsInfoProvider).(ExportedComponentsInfo)
+ expectedFooExportedComponents := []string{
+ "foo.stubs",
+ "foo.stubs.source",
+ "foo.stubs.source.system",
+ "foo.stubs.source.test",
+ "foo.stubs.system",
+ "foo.stubs.test",
+ }
+ android.AssertArrayString(t, "foo exported components", expectedFooExportedComponents, exportedComponentsInfo.Components)
+
bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
// tests if baz is actually linked to the stubs lib
android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.jar")
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 2b18465..bb595a5 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -219,7 +219,7 @@
name: "module_current",
properties: `sdk_version: "module_current",`,
bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-module-lib-stubs-system-modules",
java9classpath: []string{"android_module_lib_stubs_current"},
aidl: "-pout/soong/framework_non_updatable.aidl",
},
@@ -227,7 +227,7 @@
name: "system_server_current",
properties: `sdk_version: "system_server_current",`,
bootclasspath: []string{"android_system_server_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-module-lib-stubs-system-modules",
java9classpath: []string{"android_system_server_stubs_current"},
aidl: "-pout/soong/framework.aidl",
},
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 7ffb056..a2006b7 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -98,27 +98,23 @@
func (s *SystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
global := dexpreopt.GetGlobalConfig(ctx)
- // Convert content names to their appropriate stems, in case a test library is overriding an actual boot jar
- var stems []string
- for _, name := range s.properties.Contents {
- dep := ctx.GetDirectDepWithTag(name, systemServerClasspathFragmentContentDepTag)
- if m, ok := dep.(ModuleWithStem); ok {
- stems = append(stems, m.Stem())
- } else {
- ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
- }
- }
+ possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag)
// Only create configs for updatable boot jars. Non-updatable system server jars must be part of the
// platform_systemserverclasspath's classpath proto config to guarantee that they come before any
// updatable jars at runtime.
- return global.UpdatableSystemServerJars.Filter(stems)
+ return global.UpdatableSystemServerJars.Filter(possibleUpdatableModules)
}
type systemServerClasspathFragmentContentDependencyTag struct {
blueprint.BaseDependencyTag
}
+// The systemserverclasspath_fragment contents must never depend on prebuilts.
+func (systemServerClasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() bool {
+ return false
+}
+
// Contents of system server fragments in an apex are considered to be directly in the apex, as if
// they were listed in java_libs.
func (systemServerClasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {}
diff --git a/java/testing.go b/java/testing.go
index 1fef337..3ef51bd 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -17,6 +17,7 @@
import (
"fmt"
"reflect"
+ "regexp"
"sort"
"strings"
"testing"
@@ -311,6 +312,7 @@
systemModules := []string{
"core-current-stubs-system-modules",
+ "core-module-lib-stubs-system-modules",
"legacy-core-platform-api-stubs-system-modules",
"stable-core-platform-api-stubs-system-modules",
}
@@ -393,12 +395,20 @@
android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs)
}
-func CheckHiddenAPIRuleInputs(t *testing.T, expected string, hiddenAPIRule android.TestingBuildParams) {
+func CheckHiddenAPIRuleInputs(t *testing.T, message string, expected string, hiddenAPIRule android.TestingBuildParams) {
t.Helper()
- actual := strings.TrimSpace(strings.Join(android.NormalizePathsForTesting(hiddenAPIRule.Implicits), "\n"))
- expected = strings.TrimSpace(expected)
+ inputs := android.Paths{}
+ if hiddenAPIRule.Input != nil {
+ inputs = append(inputs, hiddenAPIRule.Input)
+ }
+ inputs = append(inputs, hiddenAPIRule.Inputs...)
+ inputs = append(inputs, hiddenAPIRule.Implicits...)
+ inputs = android.SortedUniquePaths(inputs)
+ actual := strings.TrimSpace(strings.Join(inputs.RelativeToTop().Strings(), "\n"))
+ re := regexp.MustCompile(`\n\s+`)
+ expected = strings.TrimSpace(re.ReplaceAllString(expected, "\n"))
if actual != expected {
- t.Errorf("Expected hiddenapi rule inputs:\n%s\nactual inputs:\n%s", expected, actual)
+ t.Errorf("Expected hiddenapi rule inputs - %s:\n%s\nactual inputs:\n%s", message, expected, actual)
}
}
diff --git a/scripts/hiddenapi/verify_overlaps.py b/scripts/hiddenapi/verify_overlaps.py
index c8e3879..bb0917e 100755
--- a/scripts/hiddenapi/verify_overlaps.py
+++ b/scripts/hiddenapi/verify_overlaps.py
@@ -47,9 +47,9 @@
if signature in allFlagsBySignature:
allFlags = allFlagsBySignature.get(signature)
if allFlags != row:
- mismatchingSignatures.append((signature, row[None], allFlags[None]))
+ mismatchingSignatures.append((signature, row.get(None, []), allFlags.get(None, [])))
else:
- mismatchingSignatures.append((signature, row[None], []))
+ mismatchingSignatures.append((signature, row.get(None, []), []))
if mismatchingSignatures:
@@ -60,7 +60,7 @@
for mismatch in mismatchingSignatures:
print()
print("< " + mismatch[0] + "," + ",".join(mismatch[1]))
- if mismatch[2] != None:
+ if mismatch[2] != []:
print("> " + mismatch[0] + "," + ",".join(mismatch[2]))
else:
print("> " + mismatch[0] + " - missing")
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 1f28ed3..9b7b868 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -133,6 +133,13 @@
apex_available: ["com.android.art"],
image_name: "art",
contents: ["mybootlib"],
+ 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 {
@@ -153,6 +160,13 @@
apex_available: ["com.android.art"],
image_name: "art",
contents: ["mysdk_mybootlib@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 {
@@ -171,8 +185,13 @@
}
`),
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
-`),
+ `),
snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
// Check the behavior of the snapshot without the source.
@@ -273,7 +292,7 @@
name: "myothersdklibrary",
apex_available: ["myapex"],
srcs: ["Test.java"],
- shared_library: false,
+ compile_dex: true,
public: {enabled: true},
min_sdk_version: "2",
permitted_packages: ["myothersdklibrary"],
@@ -283,7 +302,7 @@
name: "mycoreplatform",
apex_available: ["myapex"],
srcs: ["Test.java"],
- shared_library: false,
+ compile_dex: true,
public: {enabled: true},
min_sdk_version: "2",
}
@@ -334,7 +353,8 @@
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["myapex"],
- shared_library: false,
+ shared_library: true,
+ compile_dex: true,
public: {
jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/myothersdklibrary_stub_sources"],
@@ -364,7 +384,8 @@
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["myapex"],
- shared_library: false,
+ shared_library: true,
+ compile_dex: true,
public: {
jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
@@ -414,7 +435,8 @@
sdk_member_name: "myothersdklibrary",
visibility: ["//visibility:public"],
apex_available: ["myapex"],
- shared_library: false,
+ shared_library: true,
+ compile_dex: true,
public: {
jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/myothersdklibrary_stub_sources"],
@@ -444,7 +466,8 @@
sdk_member_name: "mycoreplatform",
visibility: ["//visibility:public"],
apex_available: ["myapex"],
- shared_library: false,
+ shared_library: true,
+ compile_dex: true,
public: {
jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
@@ -484,6 +507,28 @@
.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
`),
snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
+ snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
+ module := result.ModuleForTests("platform-bootclasspath", "android_common")
+ var rule android.TestingBuildParams
+ rule = module.Output("out/soong/hiddenapi/hiddenapi-flags.csv")
+ java.CheckHiddenAPIRuleInputs(t, "monolithic flags", `
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv
+ out/soong/hiddenapi/hiddenapi-stub-flags.txt
+ snapshot/hiddenapi/annotation-flags.csv
+ `, rule)
+
+ rule = module.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv")
+ java.CheckHiddenAPIRuleInputs(t, "monolithic metadata", `
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv
+ snapshot/hiddenapi/metadata.csv
+ `, rule)
+
+ rule = module.Output("out/soong/hiddenapi/hiddenapi-index.csv")
+ java.CheckHiddenAPIRuleInputs(t, "monolithic index", `
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
+ snapshot/hiddenapi/index.csv
+ `, rule)
+ }),
snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
)
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 6f769a3..a2cfe6d 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -663,16 +663,28 @@
}
func TestSnapshotWithJavaSystemModules(t *testing.T) {
- result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
+ result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
java_header_libs: ["exported-system-module"],
+ java_sdk_libs: ["myjavalib"],
java_system_modules: ["my-system-modules"],
}
+ java_sdk_library {
+ name: "myjavalib",
+ apex_available: ["//apex_available:anyapex"],
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ shared_library: false,
+ public: {
+ enabled: true,
+ },
+ }
+
java_system_modules {
name: "my-system-modules",
- libs: ["system-module", "exported-system-module"],
+ libs: ["system-module", "exported-system-module", "myjavalib.stubs"],
}
java_library {
@@ -710,6 +722,21 @@
jars: ["java/system-module.jar"],
}
+java_sdk_library_import {
+ name: "myjavalib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:anyapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+}
+
java_system_modules_import {
name: "my-system-modules",
prefer: false,
@@ -717,6 +744,7 @@
libs: [
"mysdk_system-module",
"exported-system-module",
+ "myjavalib.stubs",
],
}
`),
@@ -739,6 +767,21 @@
jars: ["java/system-module.jar"],
}
+java_sdk_library_import {
+ name: "mysdk_myjavalib@current",
+ sdk_member_name: "myjavalib",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:anyapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+}
+
java_system_modules_import {
name: "mysdk_my-system-modules@current",
sdk_member_name: "my-system-modules",
@@ -746,6 +789,7 @@
libs: [
"mysdk_system-module@current",
"mysdk_exported-system-module@current",
+ "mysdk_myjavalib.stubs@current",
],
}
@@ -753,12 +797,16 @@
name: "mysdk@current",
visibility: ["//visibility:public"],
java_header_libs: ["mysdk_exported-system-module@current"],
+ java_sdk_libs: ["mysdk_myjavalib@current"],
java_system_modules: ["mysdk_my-system-modules@current"],
}
`),
checkAllCopyRules(`
.intermediates/exported-system-module/android_common/turbine-combined/exported-system-module.jar -> java/exported-system-module.jar
.intermediates/system-module/android_common/turbine-combined/system-module.jar -> java/system-module.jar
+.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
)
}
@@ -1085,7 +1133,14 @@
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
".intermediates/mysdk/common_os/tmp/sdk_library/system/myjavalib_stub_sources.zip",
- ".intermediates/mysdk/common_os/tmp/sdk_library/test/myjavalib_stub_sources.zip"),
+ ".intermediates/mysdk/common_os/tmp/sdk_library/test/myjavalib_stub_sources.zip",
+ ),
+ snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
+ // Make sure that the name of the child modules created by a versioned java_sdk_library_import
+ // module is correct, i.e. the suffix is added before the version and not after.
+ result.Module("mysdk_myjavalib.stubs@current", "android_common")
+ result.Module("mysdk_myjavalib.stubs.source@current", "android_common")
+ }),
)
}
diff --git a/sdk/update.go b/sdk/update.go
index 36b564f..84f0e4e 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -22,7 +22,6 @@
"android/soong/apex"
"android/soong/cc"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -140,8 +139,8 @@
// Collect all the members.
//
-// Updates the sdk module with a list of sdkMemberVariantDeps and details as to which multilibs
-// (32/64/both) are used by this sdk variant.
+// Updates the sdk module with a list of sdkMemberVariantDep instances and details as to which
+// multilibs (32/64/both) are used by this sdk variant.
func (s *sdk) collectMembers(ctx android.ModuleContext) {
s.multilibUsages = multilibNone
ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
@@ -149,6 +148,11 @@
if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok {
memberType := memberTag.SdkMemberType(child)
+ // If a nil SdkMemberType was returned then this module should not be added to the sdk.
+ if memberType == nil {
+ return false
+ }
+
// Make sure that the resolved module is allowed in the member list property.
if !memberType.IsInstance(child) {
ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName())
@@ -157,8 +161,15 @@
// Keep track of which multilib variants are used by the sdk.
s.multilibUsages = s.multilibUsages.addArchType(child.Target().Arch.ArchType)
+ var exportedComponentsInfo android.ExportedComponentsInfo
+ if ctx.OtherModuleHasProvider(child, android.ExportedComponentsInfoProvider) {
+ exportedComponentsInfo = ctx.OtherModuleProvider(child, android.ExportedComponentsInfoProvider).(android.ExportedComponentsInfo)
+ }
+
export := memberTag.ExportMember()
- s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{s, memberType, child.(android.SdkAware), export})
+ s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{
+ s, memberType, child.(android.SdkAware), export, exportedComponentsInfo,
+ })
// Recurse down into the member's dependencies as it may have dependencies that need to be
// automatically added to the sdk.
@@ -245,26 +256,41 @@
// the contents (header files, stub libraries, etc) into the zip file.
func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) android.OutputPath {
- allMembersByName := make(map[string]struct{})
- exportedMembersByName := make(map[string]struct{})
+ // Aggregate all the sdkMemberVariantDep instances from all the sdk variants.
hasLicenses := false
var memberVariantDeps []sdkMemberVariantDep
for _, sdkVariant := range sdkVariants {
memberVariantDeps = append(memberVariantDeps, sdkVariant.memberVariantDeps...)
+ }
- // Record the names of all the members, both explicitly specified and implicitly
- // included.
- for _, memberVariantDep := range sdkVariant.memberVariantDeps {
- name := memberVariantDep.variant.Name()
- allMembersByName[name] = struct{}{}
+ // Filter out any sdkMemberVariantDep that is a component of another.
+ memberVariantDeps = filterOutComponents(ctx, memberVariantDeps)
- if memberVariantDep.export {
- exportedMembersByName[name] = struct{}{}
- }
+ // Record the names of all the members, both explicitly specified and implicitly
+ // included.
+ allMembersByName := make(map[string]struct{})
+ exportedMembersByName := make(map[string]struct{})
- if memberVariantDep.memberType == android.LicenseModuleSdkMemberType {
- hasLicenses = true
- }
+ addMember := func(name string, export bool) {
+ allMembersByName[name] = struct{}{}
+ if export {
+ exportedMembersByName[name] = struct{}{}
+ }
+ }
+
+ for _, memberVariantDep := range memberVariantDeps {
+ name := memberVariantDep.variant.Name()
+ export := memberVariantDep.export
+
+ addMember(name, export)
+
+ // Add any components provided by the module.
+ for _, component := range memberVariantDep.exportedComponentsInfo.Components {
+ addMember(component, export)
+ }
+
+ if memberVariantDep.memberType == android.LicenseModuleSdkMemberType {
+ hasLicenses = true
}
}
@@ -423,6 +449,47 @@
return outputZipFile
}
+// filterOutComponents removes any item from the deps list that is a component of another item in
+// the deps list, e.g. if the deps list contains "foo" and "foo.stubs" which is component of "foo"
+// then it will remove "foo.stubs" from the deps.
+func filterOutComponents(ctx android.ModuleContext, deps []sdkMemberVariantDep) []sdkMemberVariantDep {
+ // Collate the set of components that all the modules added to the sdk provide.
+ components := map[string]*sdkMemberVariantDep{}
+ for i, _ := range deps {
+ dep := &deps[i]
+ for _, c := range dep.exportedComponentsInfo.Components {
+ components[c] = dep
+ }
+ }
+
+ // If no module provides components then return the input deps unfiltered.
+ if len(components) == 0 {
+ return deps
+ }
+
+ filtered := make([]sdkMemberVariantDep, 0, len(deps))
+ for _, dep := range deps {
+ name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(dep.variant))
+ if owner, ok := components[name]; ok {
+ // This is a component of another module that is a member of the sdk.
+
+ // If the component is exported but the owning module is not then the configuration is not
+ // supported.
+ if dep.export && !owner.export {
+ ctx.ModuleErrorf("Module %s is internal to the SDK but provides component %s which is used outside the SDK")
+ continue
+ }
+
+ // This module must not be added to the list of members of the sdk as that would result in a
+ // duplicate module in the sdk snapshot.
+ continue
+ }
+
+ filtered = append(filtered, dep)
+ }
+ return filtered
+}
+
// addSnapshotModule adds the sdk_snapshot/module_exports_snapshot module to the builder.
func (s *sdk) addSnapshotModule(ctx android.ModuleContext, builder *snapshotBuilder, sdkVariants []*sdk, memberVariantDeps []sdkMemberVariantDep) {
bpFile := builder.bpFile
@@ -1086,9 +1153,18 @@
type sdkMemberVariantDep struct {
// The sdk variant that depends (possibly indirectly) on the member variant.
sdkVariant *sdk
+
+ // The type of sdk member the variant is to be treated as.
memberType android.SdkMemberType
- variant android.SdkAware
- export bool
+
+ // The variant that is added to the sdk.
+ variant android.SdkAware
+
+ // True if the member should be exported, i.e. accessible, from outside the sdk.
+ export bool
+
+ // The names of additional component modules provided by the variant.
+ exportedComponentsInfo android.ExportedComponentsInfo
}
var _ android.SdkMember = (*sdkMember)(nil)