From 81d95c58244782c6ae1f19de033920bbe6d7a73d Mon Sep 17 00:00:00 2001 From: Spandan Das Date: Thu, 1 Feb 2024 23:41:11 +0000 Subject: [PATCH] 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 --- android/prebuilt.go | 19 ++++++++++++- java/sdk_library_test.go | 58 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/android/prebuilt.go b/android/prebuilt.go index a94f5b75a..2896dbd53 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -547,13 +547,29 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { 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 @@ func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool { 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 3326ec575..0a113b6d5 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -1772,3 +1772,61 @@ func TestSdkLibraryExportableStubsLibrary(t *testing.T) { "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") +}