Merge "Return starlarkNodes from the functions that parse them"
diff --git a/android/bazel.go b/android/bazel.go
index 0940205..8e2e350 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -291,7 +291,7 @@
"external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
"external/conscrypt": Bp2BuildDefaultTrue,
- "external/error_prone": Bp2BuildDefaultTrue,
+ "external/error_prone": Bp2BuildDefaultTrueRecursively,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
"external/googletest": Bp2BuildDefaultTrueRecursively,
@@ -431,8 +431,19 @@
"libprotobuf-internal-protos", // b/210751803, we don't handle path property for filegroups
"libprotobuf-internal-python-srcs", // b/210751803, we don't handle path property for filegroups
"libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
+ "host-libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
"libprotobuf-java-util-full", // b/210751803, we don't handle path property for filegroups
- "conscrypt", // b/210751803, we don't handle path property for filegroups
+
+ "conscrypt", // b/210751803, we don't handle path property for filegroups
+ "conscrypt-for-host", // b/210751803, we don't handle path property for filegroups
+
+ "host-libprotobuf-java-lite", // b/217236083, java_library cannot have deps without srcs
+ "host-libprotobuf-java-micro", // b/217236083, java_library cannot have deps without srcs
+ "host-libprotobuf-java-nano", // b/217236083, java_library cannot have deps without srcs
+ "error_prone_core", // b/217236083, java_library cannot have deps without srcs
+ "bouncycastle-host", // b/217236083, java_library cannot have deps without srcs
+
+ "apex_manifest_proto_java", // b/215230097, we don't handle .proto files in java_library srcs attribute
// python protos
"libprotobuf-python", // contains .proto sources
diff --git a/android/testing.go b/android/testing.go
index 8daf6b7..39864e1 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -781,19 +781,21 @@
return p
}
-func (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) TestingBuildParams {
+func (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) (TestingBuildParams, []string) {
+ var searchedDescriptions []string
for _, p := range b.provider.BuildParamsForTests() {
+ searchedDescriptions = append(searchedDescriptions, p.Description)
if strings.Contains(p.Description, desc) {
- return b.newTestingBuildParams(p)
+ return b.newTestingBuildParams(p), searchedDescriptions
}
}
- return TestingBuildParams{}
+ return TestingBuildParams{}, searchedDescriptions
}
func (b baseTestingComponent) buildParamsFromDescription(desc string) TestingBuildParams {
- p := b.maybeBuildParamsFromDescription(desc)
+ p, searchedDescriptions := b.maybeBuildParamsFromDescription(desc)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find description %q", desc))
+ panic(fmt.Errorf("couldn't find description %q\nall descriptions:\n%s", desc, strings.Join(searchedDescriptions, "\n")))
}
return p
}
@@ -860,7 +862,8 @@
// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
// BuildParams if no rule is found.
func (b baseTestingComponent) MaybeDescription(desc string) TestingBuildParams {
- return b.maybeBuildParamsFromDescription(desc)
+ p, _ := b.maybeBuildParamsFromDescription(desc)
+ return p
}
// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go
new file mode 100644
index 0000000..ff13bb0
--- /dev/null
+++ b/bp2build/java_plugin_conversion_test.go
@@ -0,0 +1,72 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+func runJavaPluginTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ (&tc).moduleTypeUnderTest = "java_plugin"
+ (&tc).moduleTypeUnderTestFactory = java.PluginFactory
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("java_library", java.LibraryFactory)
+ }, tc)
+}
+
+func TestJavaPlugin(t *testing.T) {
+ runJavaPluginTestCase(t, bp2buildTestCase{
+ description: "java_plugin with srcs, libs, static_libs",
+ blueprint: `java_plugin {
+ name: "java-plug-1",
+ srcs: ["a.java", "b.java"],
+ libs: ["java-lib-1"],
+ static_libs: ["java-lib-2"],
+ bazel_module: { bp2build_available: true },
+}
+
+java_library {
+ name: "java-lib-1",
+ srcs: ["b.java"],
+ bazel_module: { bp2build_available: false },
+}
+
+java_library {
+ name: "java-lib-2",
+ srcs: ["c.java"],
+ bazel_module: { bp2build_available: false },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("java_plugin", "java-plug-1", attrNameToString{
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ "deps": `[
+ ":java-lib-1",
+ ":java-lib-2",
+ ]`,
+ "srcs": `[
+ "a.java",
+ "b.java",
+ ]`,
+ }),
+ },
+ })
+}
diff --git a/java/base.go b/java/base.go
index a3eb8de..42d7733 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1969,7 +1969,7 @@
func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
switch ctx.ModuleType() {
- case "java_library", "java_library_host":
+ case "java_library", "java_library_host", "java_library_static":
if lib, ok := ctx.Module().(*Library); ok {
javaLibraryBp2Build(ctx, lib)
}
@@ -1978,5 +1978,4 @@
javaBinaryHostBp2Build(ctx, binary)
}
}
-
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 7ad316f..f9dcfd6 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -334,7 +334,11 @@
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
FlagWithArg("--hide ", "SuperfluousPrefix").
- FlagWithArg("--hide ", "AnnotationExtraction")
+ FlagWithArg("--hide ", "AnnotationExtraction").
+ // (b/217545629)
+ FlagWithArg("--hide ", "ChangedThrows").
+ // (b/217552813)
+ FlagWithArg("--hide ", "ChangedAbstract")
}
}
diff --git a/java/java.go b/java/java.go
index fef9912..7a2a991 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2010,7 +2010,7 @@
Javacopts bazel.StringListAttribute
}
-func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
+func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) *javaLibraryAttributes {
srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs))
attrs := &javaLibraryAttributes{
Srcs: srcs,
@@ -2020,9 +2020,21 @@
attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
}
+ var deps bazel.LabelList
if m.properties.Libs != nil {
- attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
+ deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
}
+ if m.properties.Static_libs != nil {
+ //TODO(b/217236083) handle static libs similarly to Soong
+ deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs))
+ }
+ attrs.Deps = bazel.MakeLabelListAttribute(deps)
+
+ return attrs
+}
+
+func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
+ attrs := m.convertLibraryAttrsBp2Build(ctx)
props := bazel.BazelTargetModuleProperties{
Rule_class: "java_library",
diff --git a/java/plugin.go b/java/plugin.go
index 297ac2c..f1a5ec4 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -14,7 +14,12 @@
package java
-import "android/soong/android"
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+
+ "github.com/google/blueprint/proptools"
+)
func init() {
registerJavaPluginBuildComponents(android.InitRegistrationContext)
@@ -24,7 +29,6 @@
ctx.RegisterModuleType("java_plugin", PluginFactory)
}
-// A java_plugin module describes a host java library that will be used by javac as an annotation processor.
func PluginFactory() android.Module {
module := &Plugin{}
@@ -32,9 +36,13 @@
module.AddProperties(&module.pluginProperties)
InitJavaModule(module, android.HostSupported)
+
+ android.InitBazelModule(module)
+
return module
}
+// Plugin describes a java_plugin module, a host java library that will be used by javac as an annotation processor.
type Plugin struct {
Library
@@ -50,3 +58,32 @@
// parallelism and cause more recompilation for modules that depend on modules that use this plugin.
Generates_api *bool
}
+
+type pluginAttributes struct {
+ *javaLibraryAttributes
+ Processor_class *string
+ Target_compatible_with bazel.LabelListAttribute
+}
+
+// ConvertWithBp2build is used to convert android_app to Bazel.
+func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ libAttrs := p.convertLibraryAttrsBp2Build(ctx)
+ attrs := &pluginAttributes{
+ libAttrs,
+ nil,
+ bazel.LabelListAttribute{},
+ }
+
+ if p.pluginProperties.Processor_class != nil {
+ attrs.Processor_class = p.pluginProperties.Processor_class
+ }
+
+ var enabledProperty bazel.BoolAttribute
+ enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, proptools.BoolPtr(false))
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "java_plugin",
+ }
+
+ ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: p.Name()}, attrs, enabledProperty)
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 57ab268..6a2a7a8 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2755,7 +2755,7 @@
android.SdkMemberPropertiesBase
// Scope to per scope properties.
- Scopes map[*apiScope]scopeProperties
+ Scopes map[*apiScope]*scopeProperties
// The Java stubs source files.
Stub_srcs []string
@@ -2808,14 +2808,14 @@
StubsSrcJar android.Path
CurrentApiFile android.Path
RemovedApiFile android.Path
- AnnotationsZip android.Path
+ AnnotationsZip android.Path `supported_build_releases:"T+"`
SdkVersion string
}
func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
sdk := variant.(*SdkLibrary)
- s.Scopes = make(map[*apiScope]scopeProperties)
+ s.Scopes = make(map[*apiScope]*scopeProperties)
for _, apiScope := range allApiScopes {
paths := sdk.findScopePaths(apiScope)
if paths == nil {
@@ -2838,7 +2838,7 @@
if paths.annotationsZip.Valid() {
properties.AnnotationsZip = paths.annotationsZip.Path()
}
- s.Scopes[apiScope] = properties
+ s.Scopes[apiScope] = &properties
}
}
diff --git a/sdk/build_release.go b/sdk/build_release.go
index a3f0899..2bcdc6f 100644
--- a/sdk/build_release.go
+++ b/sdk/build_release.go
@@ -230,51 +230,108 @@
return container.Field(fieldIndex)
}
- zeroValue := reflect.Zero(field.Type)
- fieldPruner := func(container reflect.Value) {
- if containingStructAccessor != nil {
- // This is an embedded structure so first access the field for the embedded
- // structure.
- container = containingStructAccessor(container)
+ fieldType := field.Type
+ if selector(name, field) {
+ zeroValue := reflect.Zero(fieldType)
+ fieldPruner := func(container reflect.Value) {
+ if containingStructAccessor != nil {
+ // This is an embedded structure so first access the field for the embedded
+ // structure.
+ container = containingStructAccessor(container)
+ }
+
+ // Skip through interface and pointer values to find the structure.
+ container = getStructValue(container)
+
+ defer func() {
+ if r := recover(); r != nil {
+ panic(fmt.Errorf("%s\n\tfor field (index %d, name %s)", r, fieldIndex, name))
+ }
+ }()
+
+ // Set the field.
+ container.Field(fieldIndex).Set(zeroValue)
}
- // Skip through interface and pointer values to find the structure.
- container = getStructValue(container)
-
- defer func() {
- if r := recover(); r != nil {
- panic(fmt.Errorf("%s for fieldIndex %d of field %s of container %#v", r, fieldIndex, name, container.Interface()))
- }
- }()
-
- // Set the field.
- container.Field(fieldIndex).Set(zeroValue)
- }
-
- if selector(name, field) {
property := prunerProperty{
name,
fieldPruner,
}
p.properties = append(p.properties, property)
- } else if field.Type.Kind() == reflect.Struct {
- // Gather fields from the nested or embedded structure.
- var subNamePrefix string
- if field.Anonymous {
- subNamePrefix = namePrefix
- } else {
- subNamePrefix = name + "."
+ } else {
+ switch fieldType.Kind() {
+ case reflect.Struct:
+ // Gather fields from the nested or embedded structure.
+ var subNamePrefix string
+ if field.Anonymous {
+ subNamePrefix = namePrefix
+ } else {
+ subNamePrefix = name + "."
+ }
+ p.gatherFields(fieldType, fieldGetter, subNamePrefix, selector)
+
+ case reflect.Map:
+ // Get the type of the values stored in the map.
+ valueType := fieldType.Elem()
+ // Skip over * types.
+ if valueType.Kind() == reflect.Ptr {
+ valueType = valueType.Elem()
+ }
+ if valueType.Kind() == reflect.Struct {
+ // If this is not referenced by a pointer then it is an error as it is impossible to
+ // modify a struct that is stored directly as a value in a map.
+ if fieldType.Elem().Kind() != reflect.Ptr {
+ panic(fmt.Errorf("Cannot prune struct %s stored by value in map %s, map values must"+
+ " be pointers to structs",
+ fieldType.Elem(), name))
+ }
+
+ // Create a new pruner for the values of the map.
+ valuePruner := newPropertyPrunerForStructType(valueType, selector)
+
+ // Create a new fieldPruner that will iterate over all the items in the map and call the
+ // pruner on them.
+ fieldPruner := func(container reflect.Value) {
+ mapValue := fieldGetter(container)
+
+ for _, keyValue := range mapValue.MapKeys() {
+ itemValue := mapValue.MapIndex(keyValue)
+
+ defer func() {
+ if r := recover(); r != nil {
+ panic(fmt.Errorf("%s\n\tfor key %q", r, keyValue))
+ }
+ }()
+
+ valuePruner.pruneProperties(itemValue.Interface())
+ }
+ }
+
+ // Add the map field pruner to the list of property pruners.
+ property := prunerProperty{
+ name + "[*]",
+ fieldPruner,
+ }
+ p.properties = append(p.properties, property)
+ }
}
- p.gatherFields(field.Type, fieldGetter, subNamePrefix, selector)
}
}
}
-// pruneProperties will prune (set to zero value) any properties in the supplied struct.
+// pruneProperties will prune (set to zero value) any properties in the struct referenced by the
+// supplied struct pointer.
//
// The struct must be of the same type as was originally passed to newPropertyPruner to create this
// propertyPruner.
func (p *propertyPruner) pruneProperties(propertiesStruct interface{}) {
+
+ defer func() {
+ if r := recover(); r != nil {
+ panic(fmt.Errorf("%s\n\tof container %#v", r, propertiesStruct))
+ }
+ }()
+
structValue := reflect.ValueOf(propertiesStruct)
for _, property := range p.properties {
property.prunerFunc(structValue)
@@ -292,6 +349,13 @@
// of properties.
func newPropertyPruner(propertiesStruct interface{}, selector fieldSelectorFunc) *propertyPruner {
structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type()
+ return newPropertyPrunerForStructType(structType, selector)
+}
+
+// newPropertyPruner creates a new property pruner for the supplied properties struct type.
+//
+// The returned pruner can be used on any properties structure of the supplied type.
+func newPropertyPrunerForStructType(structType reflect.Type, selector fieldSelectorFunc) *propertyPruner {
pruner := &propertyPruner{}
pruner.gatherFields(structType, nil, "", selector)
return pruner
diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go
index dff276d..6608be4 100644
--- a/sdk/build_release_test.go
+++ b/sdk/build_release_test.go
@@ -15,6 +15,7 @@
package sdk
import (
+ "encoding/json"
"fmt"
"testing"
@@ -125,61 +126,102 @@
F1_only string `supported_build_releases:"F1"`
}
+ type mapped struct {
+ Default string
+ T_only string `supported_build_releases:"T"`
+ }
+
type testBuildReleasePruner struct {
Default string
S_and_T_only string `supported_build_releases:"S-T"`
T_later string `supported_build_releases:"T+"`
Nested nested
+ Mapped map[string]*mapped
}
- input := testBuildReleasePruner{
- Default: "Default",
- S_and_T_only: "S_and_T_only",
- T_later: "T_later",
- Nested: nested{
- F1_only: "F1_only",
- },
+ inputFactory := func() testBuildReleasePruner {
+ return testBuildReleasePruner{
+ Default: "Default",
+ S_and_T_only: "S_and_T_only",
+ T_later: "T_later",
+ Nested: nested{
+ F1_only: "F1_only",
+ },
+ Mapped: map[string]*mapped{
+ "one": {
+ Default: "one-default",
+ T_only: "one-t-only",
+ },
+ "two": {
+ Default: "two-default",
+ T_only: "two-t-only",
+ },
+ },
+ }
+ }
+
+ marshal := func(t interface{}) string {
+ bytes, err := json.MarshalIndent(t, "", " ")
+ if err != nil {
+ panic(err)
+ }
+ return string(bytes)
+ }
+
+ assertJsonEquals := func(t *testing.T, expected, actual interface{}) {
+ t.Helper()
+ expectedJson := marshal(expected)
+ actualJson := marshal(actual)
+ if actualJson != expectedJson {
+ t.Errorf("test struct: expected:\n%s\n got:\n%s", expectedJson, actualJson)
+ }
}
t.Run("target S", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseS)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.T_later = ""
expected.Nested.F1_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ expected.Mapped["one"].T_only = ""
+ expected.Mapped["two"].T_only = ""
+ assertJsonEquals(t, expected, testStruct)
})
t.Run("target T", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseT)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.Nested.F1_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ assertJsonEquals(t, expected, testStruct)
})
t.Run("target F1", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture1)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.S_and_T_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ expected.Mapped["one"].T_only = ""
+ expected.Mapped["two"].T_only = ""
+ assertJsonEquals(t, expected, testStruct)
})
t.Run("target F2", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture2)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.S_and_T_only = ""
expected.Nested.F1_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ expected.Mapped["one"].T_only = ""
+ expected.Mapped["two"].T_only = ""
+ assertJsonEquals(t, expected, testStruct)
})
}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 0d9b4a0..f0d3b35 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -1319,6 +1319,58 @@
)
}
+func TestSnapshotWithJavaSdkLibrary_AnnotationsZip_PreT(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJavaSdkLibrary,
+ android.FixtureMergeEnv(map[string]string{
+ "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
+ }),
+ ).RunTestWithBp(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib",
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ shared_library: false,
+ annotations_enabled: true,
+ public: {
+ enabled: true,
+ },
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "myjavalib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ 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",
+ },
+}
+ `),
+ checkAllCopyRules(`
+.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
+ `),
+ checkMergeZips(".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip"),
+ )
+}
+
func TestSnapshotWithJavaSdkLibrary_CompileDex(t *testing.T) {
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {