Merge "enable exportable check" into main
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 13cda9d..5a94a0f 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -534,6 +534,35 @@
 		for _, moduleInFamily := range allModulesInFamily {
 			if moduleInFamily.Name() != selectedModuleInFamily.Name() {
 				moduleInFamily.HideFromMake()
+				// If this is a prebuilt module, unset properties.UsePrebuilt
+				// properties.UsePrebuilt might evaluate to true via soong config var fallback mechanism
+				// Set it to false explicitly so that the following mutator does not replace rdeps to this unselected prebuilt
+				if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil {
+					p.properties.UsePrebuilt = false
+				}
+			}
+		}
+	}
+	// Do a validation pass to make sure that multiple prebuilts of a specific module are not selected.
+	// This might happen if the prebuilts share the same soong config var namespace.
+	// This should be an error, unless one of the prebuilts has been explicitly declared in apex_contributions
+	var selectedPrebuilt Module
+	for _, moduleInFamily := range allModulesInFamily {
+		// Skip if this module is in a different namespace
+		if !moduleInFamily.ExportedToMake() {
+			continue
+		}
+		// Skip for the top-level java_sdk_library_(_import). This has some special cases that need to be addressed first.
+		// This does not run into non-determinism because PrebuiltPostDepsMutator also has the special case
+		if sdkLibrary, ok := moduleInFamily.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
+			continue
+		}
+		if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt {
+			if selectedPrebuilt == nil {
+				selectedPrebuilt = moduleInFamily
+			} else {
+				ctx.ModuleErrorf("Multiple prebuilt modules %v and %v have been marked as preferred for this source module. "+
+					"Please add the appropriate prebuilt module to apex_contributions for this release config.", selectedPrebuilt.Name(), moduleInFamily.Name())
 			}
 		}
 	}
@@ -562,7 +591,7 @@
 						// 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()) {
+						if psi.IsSelected(name) {
 							return false
 						}
 					}
@@ -625,6 +654,17 @@
 	CreatedByJavaSdkLibraryName() *string
 }
 
+// Returns true if the prebuilt variant is disabled
+// e.g. for a cc_prebuilt_library_shared, this will return
+// - true for the static variant of the module
+// - false for the shared variant of the module
+//
+// Even though this is a cc_prebuilt_library_shared, we create both the variants today
+// https://source.corp.google.com/h/googleplex-android/platform/build/soong/+/e08e32b45a18a77bc3c3e751f730539b1b374f1b:cc/library.go;l=2113-2116;drc=2c4a9779cd1921d0397a12b3d3521f4c9b30d747;bpv=1;bpt=0
+func (p *Prebuilt) variantIsDisabled(ctx BaseMutatorContext, prebuilt Module) bool {
+	return p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0
+}
+
 // usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
 // will be used if it is marked "prefer" or if the source module is disabled.
 func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt Module) bool {
@@ -639,7 +679,7 @@
 		return false
 	}
 	// If the prebuilt module is explicitly listed in the metadata module, use that
-	if isSelected(psi, prebuilt) {
+	if isSelected(psi, prebuilt) && !p.variantIsDisabled(ctx, prebuilt) {
 		return true
 	}
 
@@ -647,7 +687,7 @@
 	// fall back to the existing source vs prebuilt selection.
 	// TODO: Drop the fallback mechanisms
 
-	if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
+	if p.variantIsDisabled(ctx, prebuilt) {
 		return false
 	}
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 97b9c84..54d2d08 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6199,7 +6199,7 @@
 		`)
 	})
 
-	t.Run("Co-existing unflagged apexes should create a duplicate deapexer error in hiddenapi processing", func(t *testing.T) {
+	t.Run("Co-existing unflagged apexes should create a duplicate module error", func(t *testing.T) {
 		bp := `
 		// Source
 		apex {
@@ -6273,7 +6273,7 @@
 		}
 	`
 
-		testDexpreoptWithApexes(t, bp, "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_myapex.v1 and prebuilt_myapex.v2", preparer, fragment)
+		testDexpreoptWithApexes(t, bp, "Multiple prebuilt modules prebuilt_myapex.v1 and prebuilt_myapex.v2 have been marked as preferred for this source module", preparer, fragment)
 	})
 
 }
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index f6b5ed5..71b7e43 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -610,3 +610,153 @@
 		android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
 	}
 }
+
+// Setting prefer on multiple prebuilts is an error, unless one of them is also listed in apex_contributions
+func TestMultiplePrebuiltsPreferredUsingLegacyFlags(t *testing.T) {
+	bp := `
+		// an rdep
+		cc_library {
+			name: "libfoo",
+			shared_libs: ["libbar"],
+		}
+
+		// multiple variations of dep
+		// source
+		cc_library {
+			name: "libbar",
+		}
+		// prebuilt "v1"
+		cc_prebuilt_library_shared {
+			name: "libbar",
+			srcs: ["libbar.so"],
+			prefer: true,
+		}
+		// prebuilt "v2"
+		cc_prebuilt_library_shared {
+			name: "libbar.v2",
+			stem: "libbar",
+			source_module_name: "libbar",
+			srcs: ["libbar.so"],
+			prefer: true,
+		}
+
+		// selectors
+		apex_contributions {
+			name: "myapex_contributions",
+			contents: [%v],
+		}
+		all_apex_contributions {name: "all_apex_contributions"}
+	`
+	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
+		t.Helper()
+		var found bool
+		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+			if dep == wantDep {
+				found = true
+			}
+		})
+		return found
+	}
+
+	testCases := []struct {
+		desc                   string
+		selectedDependencyName string
+		expectedDependencyName string
+		expectedErr            string
+	}{
+		{
+			desc:        "Multiple prebuilts have prefer: true",
+			expectedErr: "Multiple prebuilt modules prebuilt_libbar and prebuilt_libbar.v2 have been marked as preferred for this source module",
+		},
+		{
+			desc:                   "Multiple prebuilts have prefer: true. The prebuilt listed in apex_contributions wins.",
+			selectedDependencyName: `"prebuilt_libbar"`,
+			expectedDependencyName: "prebuilt_libbar",
+		},
+	}
+
+	for _, tc := range testCases {
+		preparer := android.GroupFixturePreparers(
+			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+				android.RegisterApexContributionsBuildComponents(ctx)
+			}),
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				variables.BuildFlags = map[string]string{
+					"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+				}
+			}),
+		)
+		if tc.expectedErr != "" {
+			preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedErr))
+		}
+
+		ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
+			"libbar.so": nil,
+			"crtx.o":    nil,
+		}, preparer)
+		if tc.expectedErr != "" {
+			return // the fixture will assert that the excepted err has been raised
+		}
+		libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+		expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
+		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
+	}
+}
+
+// If module sdk cannot provide a cc module variant (e.g. static), then the module variant from source should be used
+func TestMissingVariantInModuleSdk(t *testing.T) {
+	bp := `
+		// an rdep
+		cc_library {
+			name: "libfoo",
+			static_libs: ["libbar"],
+		}
+
+		// source
+		cc_library {
+			name: "libbar",
+		}
+		// prebuilt
+		// libbar only exists as a shared library
+		cc_prebuilt_library_shared {
+			name: "libbar",
+			srcs: ["libbar.so"],
+		}
+		// selectors
+		apex_contributions {
+			name: "myapex_contributions",
+			contents: ["prebuilt_libbar"],
+		}
+		all_apex_contributions {name: "all_apex_contributions"}
+	`
+	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
+		t.Helper()
+		var found bool
+		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+			if dep == wantDep {
+				found = true
+			}
+		})
+		return found
+	}
+
+	preparer := android.GroupFixturePreparers(
+		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+			android.RegisterApexContributionsBuildComponents(ctx)
+		}),
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.BuildFlags = map[string]string{
+				"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+			}
+		}),
+	)
+	ctx := testPrebuilt(t, bp, map[string][]byte{
+		"libbar.so": nil,
+		"crtx.o":    nil,
+	}, preparer)
+	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+	sourceLibBar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module()
+	// Even though the prebuilt is listed in apex_contributions, the prebuilt does not have a static variant.
+	// Therefore source of libbar should be used.
+	android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from libfoo to source libbar"), true, hasDep(ctx, libfoo, sourceLibBar))
+}
diff --git a/java/androidmk.go b/java/androidmk.go
index b7df9bf..498962f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -691,9 +691,10 @@
 		return nil
 	}
 	return []android.AndroidMkEntries{android.AndroidMkEntries{
-		Class:      "APPS",
-		OutputFile: android.OptionalPathForPath(a.outputFile),
-		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
+		Class:        "APPS",
+		OutputFile:   android.OptionalPathForPath(a.outputFile),
+		OverrideName: a.BaseModuleName(), // TODO (spandandas): Add a test
+		Include:      "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", a.Privileged())
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 1cfa642..38ed856 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -187,6 +187,33 @@
 	return apexInfo.ForPrebuiltApex
 }
 
+// For apex variant of modules, this returns true on the source variant if the prebuilt apex
+// has been selected using apex_contributions.
+// The prebuilt apex will be responsible for generating the dexpreopt rules of the deapexed java lib.
+func disableSourceApexVariant(ctx android.BaseModuleContext) bool {
+	if !isApexVariant(ctx) {
+		return false // platform variant
+	}
+	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+	psi := android.PrebuiltSelectionInfoMap{}
+	ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(am android.Module) {
+		psi, _ = android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider)
+	})
+	// Find the apex variant for this module
+	_, apexVariantsWithoutTestApexes, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes)
+	disableSource := false
+	// find the selected apexes
+	for _, apexVariant := range apexVariantsWithoutTestApexes {
+		for _, selected := range psi.GetSelectedModulesForApiDomain(apexVariant) {
+			// If the apex_contribution for this api domain contains a prebuilt apex, disable the source variant
+			if strings.HasPrefix(selected, "prebuilt_com.google.android") {
+				disableSource = true
+			}
+		}
+	}
+	return disableSource
+}
+
 // Returns whether dexpreopt is applicable to the module.
 // When it returns true, neither profile nor dexpreopt artifacts will be generated.
 func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName string) bool {
@@ -216,6 +243,10 @@
 		return true
 	}
 
+	if disableSourceApexVariant(ctx) {
+		return true
+	}
+
 	if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex {
 		// dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes
 		return false
diff --git a/java/droiddoc.go b/java/droiddoc.go
index df40d01..6a66f45 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -222,8 +222,6 @@
 	stubsSrcJar android.WritablePath
 
 	exportableStubsSrcJar android.WritablePath
-
-	runtimeStubsSrcJar android.WritablePath
 }
 
 func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index f4bcaca..76c8d88 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -227,7 +227,6 @@
 type annotationFlagsParams struct {
 	migratingNullability    bool
 	validatingNullability   bool
-	extractAnnotations      bool
 	nullabilityWarningsFile android.WritablePath
 	annotationsZip          android.WritablePath
 }
@@ -243,19 +242,16 @@
 	stubConfig              stubsCommandConfigParams
 }
 type stubsCommandConfigParams struct {
-	stubsType                   StubsType
-	javaVersion                 javaVersion
-	deps                        deps
-	checkApi                    bool
-	generateStubs               bool
-	doApiLint                   bool
-	doCheckReleased             bool
-	writeSdkValues              bool
-	migratingNullability        bool
-	validatingNullability       bool
-	annotationsEnabled          bool
-	apiLevelsAnnotationsEnabled bool
-	extractAnnotations          bool
+	stubsType             StubsType
+	javaVersion           javaVersion
+	deps                  deps
+	checkApi              bool
+	generateStubs         bool
+	doApiLint             bool
+	doCheckReleased       bool
+	writeSdkValues        bool
+	migratingNullability  bool
+	validatingNullability bool
 }
 
 // droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
@@ -525,30 +521,30 @@
 }
 
 func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
-	cmd.Flag(config.MetalavaAnnotationsFlags)
+	if Bool(d.properties.Annotations_enabled) {
+		cmd.Flag(config.MetalavaAnnotationsFlags)
 
-	if params.migratingNullability {
-		previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
-		cmd.FlagWithInput("--migrate-nullness ", previousApi)
-	}
+		if params.migratingNullability {
+			previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
+			cmd.FlagWithInput("--migrate-nullness ", previousApi)
+		}
 
-	if s := String(d.properties.Validate_nullability_from_list); s != "" {
-		cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
-	}
+		if s := String(d.properties.Validate_nullability_from_list); s != "" {
+			cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
+		}
 
-	if params.validatingNullability {
-		cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
-	}
+		if params.validatingNullability {
+			cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
+		}
 
-	if params.extractAnnotations {
 		cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
-	}
 
-	if len(d.properties.Merge_annotations_dirs) != 0 {
-		d.mergeAnnoDirFlags(ctx, cmd)
-	}
+		if len(d.properties.Merge_annotations_dirs) != 0 {
+			d.mergeAnnoDirFlags(ctx, cmd)
+		}
 
-	cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
+		cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
+	}
 }
 
 func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
@@ -573,11 +569,9 @@
 	})
 }
 
-func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params stubsCommandParams) {
+func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
 	var apiVersions android.Path
-	stubsType := params.stubConfig.stubsType
-	apiVersionsXml := params.apiVersionsXml
-	if params.stubConfig.apiLevelsAnnotationsEnabled {
+	if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
 		d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
 		apiVersions = apiVersionsXml
 	} else {
@@ -588,9 +582,7 @@
 				} else if stubsType == Exportable {
 					apiVersions = s.exportableArtifacts.apiVersionsXml
 				} else {
-					// if the stubs type does not generate api-versions.xml file, default to using the
-					// everything artifacts
-					apiVersions = s.everythingArtifacts.apiVersionsXml
+					ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
 				}
 			} else {
 				ctx.PropertyErrorf("api_levels_module",
@@ -824,16 +816,13 @@
 	annotationParams := annotationFlagsParams{
 		migratingNullability:    params.stubConfig.migratingNullability,
 		validatingNullability:   params.stubConfig.validatingNullability,
-		extractAnnotations:      params.stubConfig.extractAnnotations,
 		nullabilityWarningsFile: params.nullabilityWarningsFile,
 		annotationsZip:          params.annotationsZip,
 	}
 
-	if params.stubConfig.annotationsEnabled {
-		d.annotationsFlags(ctx, cmd, annotationParams)
-	}
+	d.annotationsFlags(ctx, cmd, annotationParams)
 	d.inclusionAnnotationsFlags(ctx, cmd)
-	d.apiLevelsAnnotationsFlags(ctx, cmd, params)
+	d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
 
 	d.expandArgs(ctx, cmd)
 
@@ -863,13 +852,13 @@
 		d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
 	}
 
-	if params.annotationsEnabled {
+	if Bool(d.properties.Annotations_enabled) {
 		if params.validatingNullability {
 			d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
 		}
 		d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
 	}
-	if params.apiLevelsAnnotationsEnabled {
+	if Bool(d.properties.Api_levels_annotations_enabled) {
 		d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
 	}
 
@@ -1047,7 +1036,7 @@
 		optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
 	}
 
-	if params.annotationsEnabled {
+	if Bool(d.properties.Annotations_enabled) {
 		if params.validatingNullability {
 			d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
 			optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
@@ -1055,7 +1044,7 @@
 		d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
 		optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
 	}
-	if params.apiLevelsAnnotationsEnabled {
+	if Bool(d.properties.Api_levels_annotations_enabled) {
 		d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
 		optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
 	}
@@ -1073,38 +1062,6 @@
 	d.optionalStubCmd(ctx, optionalCmdParams)
 }
 
-// Sandbox rule for generating runtime stubs
-func (d *Droidstubs) runtimeStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
-
-	// We are only interested in generating the stubs srcjar,
-	// not other artifacts for the runtime stubs
-	params.checkApi = false
-	params.writeSdkValues = false
-	params.validatingNullability = false
-	params.extractAnnotations = false
-	params.apiLevelsAnnotationsEnabled = false
-
-	optionalCmdParams := stubsCommandParams{
-		stubConfig: params,
-	}
-
-	d.Javadoc.runtimeStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
-	optionalCmdParams.stubsSrcJar = d.Javadoc.runtimeStubsSrcJar
-
-	// If aconfig_declarations property is not defined, all flagged apis symbols are stripped
-	// as no aconfig flags are enabled. In such case, the runtime stubs are identical to the
-	// exportable stubs, thus no additional metalava invocation is needed.
-	if len(d.properties.Aconfig_declarations) == 0 {
-		rule := android.NewRuleBuilder(pctx, ctx)
-		rule.Command().
-			Text("cp").Flag("-f").
-			Input(d.exportableStubsSrcJar).Output(d.runtimeStubsSrcJar)
-		rule.Build(fmt.Sprintf("metalava_%s", params.stubsType.String()), "metalava merged")
-	} else {
-		d.optionalStubCmd(ctx, optionalCmdParams)
-	}
-}
-
 func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
 
 	params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
@@ -1176,8 +1133,6 @@
 
 	annotationsEnabled := Bool(d.properties.Annotations_enabled)
 
-	extractAnnotations := annotationsEnabled
-
 	migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
 	validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
 		String(d.properties.Validate_nullability_from_list) != "")
@@ -1185,40 +1140,27 @@
 	checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
 		apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
 
-	apiLevelsAnnotationsEnabled := proptools.Bool(d.properties.Api_levels_annotations_enabled)
-
 	stubCmdParams := stubsCommandConfigParams{
-		javaVersion:                 javaVersion,
-		deps:                        deps,
-		checkApi:                    checkApi,
-		generateStubs:               generateStubs,
-		doApiLint:                   doApiLint,
-		doCheckReleased:             doCheckReleased,
-		writeSdkValues:              writeSdkValues,
-		migratingNullability:        migratingNullability,
-		validatingNullability:       validatingNullability,
-		annotationsEnabled:          annotationsEnabled,
-		apiLevelsAnnotationsEnabled: apiLevelsAnnotationsEnabled,
-		extractAnnotations:          extractAnnotations,
+		javaVersion:           javaVersion,
+		deps:                  deps,
+		checkApi:              checkApi,
+		generateStubs:         generateStubs,
+		doApiLint:             doApiLint,
+		doCheckReleased:       doCheckReleased,
+		writeSdkValues:        writeSdkValues,
+		migratingNullability:  migratingNullability,
+		validatingNullability: validatingNullability,
 	}
 	stubCmdParams.stubsType = Everything
 	// Create default (i.e. "everything" stubs) rule for metalava
 	d.everythingStubCmd(ctx, stubCmdParams)
 
-	// The module generates "exportable" stubs regardless of whether
+	// The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
 	// aconfig_declarations property is defined or not. If the property is not defined, the module simply
 	// strips all flagged apis to generate the "exportable" stubs
 	stubCmdParams.stubsType = Exportable
 	d.exportableStubCmd(ctx, stubCmdParams)
 
-	// "runtime" stubs do not generate any other artifacts than the stubs.
-	// Therefore, metalava does not have to run for "runtime" configuration
-	// when the module does not generate stubs.
-	if stubCmdParams.generateStubs {
-		stubCmdParams.stubsType = Runtime
-		d.runtimeStubCmd(ctx, stubCmdParams)
-	}
-
 	if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
 
 		if len(d.Javadoc.properties.Out) > 0 {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index c86e8bf..8da695f 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -397,47 +397,23 @@
 			"bar",
 		],
 	}
-	droidstubs {
-		name: "baz",
-		srcs: ["a/A.java"],
-		api_surface: "public",
-		check_api: {
-			current: {
-				api_file: "a/current.txt",
-				removed_api_file: "a/removed.txt",
-			}
-		},
-	}
 	`)
 
 	// Check that droidstubs depend on aconfig_declarations
 	android.AssertBoolEquals(t, "foo expected to depend on bar",
 		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
 
-	fooModule := result.ModuleForTests("foo", "android_common")
+	m := result.ModuleForTests("foo", "android_common")
 	android.AssertStringDoesContain(t, "foo generates revert annotations file",
-		strings.Join(fooModule.AllOutputs(), ""), "revert-annotations-exportable.txt")
+		strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
 
 	// revert-annotations.txt passed to exportable stubs generation metalava command
-	exportableManifest := fooModule.Output("metalava_exportable.sbox.textproto")
-	exportableCmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, exportableManifest).Commands[0].Command)
-	android.AssertStringDoesContain(t, "flagged api hide command not included", exportableCmdline, "revert-annotations-exportable.txt")
+	manifest := m.Output("metalava_exportable.sbox.textproto")
+	cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
+	android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
 
 	android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
-		strings.Join(fooModule.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
-
-	// revert-annotations.txt passed to runtime stubs generation metalava command
-	runtimeManifest := fooModule.Output("metalava_runtime.sbox.textproto")
-	runtimeCmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, runtimeManifest).Commands[0].Command)
-	android.AssertStringDoesContain(t, "flagged api hide command not included", runtimeCmdline, "revert-annotations-runtime.txt")
-
-	android.AssertStringDoesContain(t, "foo generates runtime stubs jar",
-		strings.Join(fooModule.AllOutputs(), ""), "runtime/foo-stubs.srcjar")
-
-	// If aconfig_declarations property is not defined, the runtime stubs is a copy of the exportable stubs
-	bazModule := result.ModuleForTests("baz", "android_common")
-	bazRuntimeCmdline := bazModule.Rule("metalava_runtime").RuleParams.Command
-	android.AssertStringDoesContain(t, "copy command should include the input stub", bazRuntimeCmdline, "exportable/baz-stubs.srcjar")
+		strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
 }
 
 func TestReleaseExportRuntimeApis(t *testing.T) {