Do not replace the direct edge between rdeps and java_sdk_library
android/prebuilt.go#isSelected has a special-case inside it to ignore
apex_contributions contents for the top-level java_sdk_library hook.
This was necessary because even though we might want source stubs in
next builds, we still needed the top-level prebuilt hook to be active to
emit the dexpreopt rules to .mk.
This worked fine for rdeps that create a dependency edge on the child
stub modules of java_sdk_library. Notable examples include the full
android api stubs created by f/b/api.go. In postdeps mutator, these
expanded deps get rewritten to source/prebuilt if necesssry.
The exception to this are workflows which depend on the top-level hook
directly via `libs`. We resolve these rdeps to an appropriate provider
during GenerateAndroidBuildActions stage. This meant that rdeps were
getting prebuilt stubs of these even in next builds.
Bug: 323454855
Test: Added a unit test
Test: lunch cf_x86_64_only_phone-next-userdebug
Test: aninja -t query
out/soong/.intermediates/packages/modules/Permission/SafetyCenter/Config/safety-center-config/android_common/javac/safety-center-config.jar
| grep prebilts/module_sdk # empty now
Change-Id: Id91333d88055519f3c58ab40466f9628085f5180
diff --git a/android/prebuilt.go b/android/prebuilt.go
index a94f5b7..2896dbd 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -547,13 +547,29 @@
if p := GetEmbeddedPrebuilt(m); p != nil {
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
+ psi := PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) {
+ psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
+ })
+
if p.properties.UsePrebuilt {
if p.properties.SourceExists {
ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
+ if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
+ // Do not replace deps to the top-level prebuilt java_sdk_library hook.
+ // This hook has been special-cased in #isSelected to be _always_ active, even in next builds
+ // for dexpreopt and hiddenapi processing.
+ // If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs
+ // will get prebuilt stubs
+ // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
+ if psi.IsSelected(*sdkLibrary.SdkLibraryName()) {
+ return false
+ }
+ }
+
if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
return t.ReplaceSourceWithPrebuilt()
}
-
return true
})
}
@@ -584,6 +600,7 @@
sln := proptools.String(sdkLibrary.SdkLibraryName())
// This is the top-level library
// Do not supersede the existing prebuilts vs source selection mechanisms
+ // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
if sln == m.base().BaseModuleName() {
return false
}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 3326ec5..0a113b6 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -1772,3 +1772,61 @@
"top level exportable stubs library", []string{exportableSourceStubsLibraryModuleName},
topLevelModule.Module().(*Library).properties.Static_libs)
}
+
+// For java libraries depending on java_sdk_library(_import) via libs, assert that
+// rdep gets stubs of source if source is listed in apex_contributions and prebuilt has prefer (legacy mechanism)
+func TestStubResolutionOfJavaSdkLibraryInLibs(t *testing.T) {
+ bp := `
+ apex_contributions {
+ name: "my_mainline_module_contributions",
+ api_domain: "my_mainline_module",
+ contents: ["sdklib"], // source is selected using apex_contributions, but prebuilt is selected using prefer
+ }
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+ java_sdk_library_import {
+ name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ prefer: true, // Set prefer explicitly on the prebuilt. We will assert that rdep gets source in a test case.
+ }
+ // rdeps
+ java_library {
+ name: "mymodule",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ libs: ["sdklib",], // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
+ }
+ `
+
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ // We can use any of the apex contribution build flags from build/soong/android/config.go#mainlineApexContributionBuildFlags here
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
+ }
+ }),
+ )
+
+ result := fixture.RunTestWithBp(t, bp)
+ // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
+ public := result.ModuleForTests("mymodule", "android_common")
+ rule := public.Output("javac/mymodule.jar")
+ inputs := rule.Implicits.Strings()
+ android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar")
+}