Merge "Output bootclasspath_fragment's fragments property to sdk snapshot"

This commit is contained in:
Paul Duffin 2021-06-23 17:47:49 +00:00 committed by Gerrit Code Review
commit 94b51488d9
5 changed files with 194 additions and 13 deletions

View file

@ -300,6 +300,22 @@ type BpModule interface {
Name() string
}
// BpPrintable is a marker interface that must be implemented by any struct that is added as a
// property value.
type BpPrintable interface {
bpPrintable()
}
// BpPrintableBase must be embedded within any struct that is added as a
// property value.
type BpPrintableBase struct {
}
func (b BpPrintableBase) bpPrintable() {
}
var _ BpPrintable = BpPrintableBase{}
// An individual member of the SDK, includes all of the variants that the SDK
// requires.
type SdkMember interface {

View file

@ -144,6 +144,8 @@ func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprin
// ApexVariantReference specifies a particular apex variant of a module.
type ApexVariantReference struct {
android.BpPrintableBase
// The name of the module apex variant, i.e. the apex containing the module variant.
//
// If this is not specified then it defaults to "platform" which will cause a dependency to be

View file

@ -749,6 +749,9 @@ type bootclasspathFragmentSdkMemberProperties struct {
Stub_libs []string
Core_platform_stub_libs []string
// Fragment properties
Fragments []ApexVariantReference
// Flag files by *hiddenAPIFlagFileCategory
Flag_files_by_category FlagFilesByCategory
@ -789,6 +792,9 @@ func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx andro
// Copy stub_libs properties.
b.Stub_libs = module.properties.Api.Stub_libs
b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs
// Copy fragment properties.
b.Fragments = module.properties.Fragments
}
func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@ -811,6 +817,9 @@ func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.
corePlatformApiPropertySet := propertySet.AddPropertySet("core_platform_api")
corePlatformApiPropertySet.AddPropertyWithTag("stub_libs", b.Core_platform_stub_libs, requiredMemberDependency)
}
if len(b.Fragments) > 0 {
propertySet.AddProperty("fragments", b.Fragments)
}
hiddenAPISet := propertySet.AddPropertySet("hidden_api")
hiddenAPIDir := "hiddenapi"

View file

@ -511,6 +511,127 @@ sdk_snapshot {
)
}
// TestSnapshotWithBootClasspathFragment_Fragments makes sure that the fragments property of a
// bootclasspath_fragment is correctly output to the sdk snapshot.
func TestSnapshotWithBootClasspathFragment_Fragments(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"),
prepareForSdkTestWithApex,
// Some additional files needed for the myotherapex.
android.FixtureMergeMockFs(android.MockFS{
"system/sepolicy/apex/myotherapex-file_contexts": nil,
"myotherapex/apex_manifest.json": nil,
"myotherapex/Test.java": nil,
}),
android.FixtureAddTextFile("myotherapex/Android.bp", `
apex {
name: "myotherapex",
key: "myapex.key",
min_sdk_version: "2",
bootclasspath_fragments: ["myotherbootclasspathfragment"],
}
bootclasspath_fragment {
name: "myotherbootclasspathfragment",
apex_available: ["myotherapex"],
contents: [
"myotherlib",
],
}
java_library {
name: "myotherlib",
apex_available: ["myotherapex"],
srcs: ["Test.java"],
min_sdk_version: "2",
permitted_packages: ["myothersdklibrary"],
compile_dex: true,
}
`),
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
bootclasspath_fragments: ["mybootclasspathfragment"],
}
bootclasspath_fragment {
name: "mybootclasspathfragment",
contents: [
"mysdklibrary",
],
fragments: [
{
apex: "myotherapex",
module: "myotherbootclasspathfragment"
},
],
}
java_sdk_library {
name: "mysdklibrary",
srcs: ["Test.java"],
shared_library: false,
public: {enabled: true},
min_sdk_version: "2",
}
`),
).RunTest(t)
// A preparer to update the test fixture used when processing an unpackage snapshot.
preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("myapex", "mybootclasspathfragment")
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
prebuilt_bootclasspath_fragment {
name: "mybootclasspathfragment",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
contents: ["mysdklibrary"],
fragments: [
{
apex: "myotherapex",
module: "myotherbootclasspathfragment",
},
],
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_sdk_library_import {
name: "mysdklibrary",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
shared_library: false,
public: {
jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
current_api: "sdk_library/public/mysdklibrary.txt",
removed_api: "sdk_library/public/mysdklibrary-removed.txt",
sdk_version: "current",
},
}
`),
snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
)
}
// Test that bootclasspath_fragment works with sdk.
func TestBasicSdkWithBootclasspathFragment(t *testing.T) {
android.GroupFixturePreparers(

View file

@ -824,32 +824,65 @@ func outputUnnamedValue(contents *generatedContents, value reflect.Value) {
case reflect.String:
contents.UnindentedPrintf("%q", value)
case reflect.Ptr:
outputUnnamedValue(contents, value.Elem())
case reflect.Slice:
length := value.Len()
if length == 0 {
contents.UnindentedPrintf("[]")
} else if length == 1 {
contents.UnindentedPrintf("[")
outputUnnamedValue(contents, value.Index(0))
contents.UnindentedPrintf("]")
} else {
contents.UnindentedPrintf("[\n")
contents.Indent()
for i := 0; i < length; i++ {
itemValue := value.Index(i)
contents.IndentedPrintf("")
outputUnnamedValue(contents, itemValue)
contents.UnindentedPrintf(",\n")
firstValue := value.Index(0)
if length == 1 && !multiLineValue(firstValue) {
contents.UnindentedPrintf("[")
outputUnnamedValue(contents, firstValue)
contents.UnindentedPrintf("]")
} else {
contents.UnindentedPrintf("[\n")
contents.Indent()
for i := 0; i < length; i++ {
itemValue := value.Index(i)
contents.IndentedPrintf("")
outputUnnamedValue(contents, itemValue)
contents.UnindentedPrintf(",\n")
}
contents.Dedent()
contents.IndentedPrintf("]")
}
contents.Dedent()
contents.IndentedPrintf("]")
}
case reflect.Struct:
// Avoid unlimited recursion by requiring every structure to implement android.BpPrintable.
v := value.Interface()
if _, ok := v.(android.BpPrintable); !ok {
panic(fmt.Errorf("property value %#v of type %T does not implement android.BpPrintable", v, v))
}
contents.UnindentedPrintf("{\n")
contents.Indent()
for f := 0; f < valueType.NumField(); f++ {
fieldType := valueType.Field(f)
if fieldType.Anonymous {
continue
}
fieldValue := value.Field(f)
fieldName := fieldType.Name
propertyName := proptools.PropertyNameForField(fieldName)
outputNamedValue(contents, propertyName, fieldValue)
}
contents.Dedent()
contents.IndentedPrintf("}")
default:
panic(fmt.Errorf("Unknown type: %T of value %#v", value, value))
}
}
// multiLineValue returns true if the supplied value may require multiple lines in the output.
func multiLineValue(value reflect.Value) bool {
kind := value.Kind()
return kind == reflect.Slice || kind == reflect.Struct
}
func (s *sdk) GetAndroidBpContentsForTests() string {
contents := &generatedContents{}
generateBpContents(contents, s.builderForTests.bpFile)