Merge "Remove VSDK related code from build" into main
diff --git a/Android.bp b/Android.bp
index 682711d..0d1ff02 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,7 +132,7 @@
     product_config: ":product_config",
 
     // Currently, only microdroid can refer to buildinfo.prop
-    visibility: ["//packages/modules/Virtualization/microdroid"],
+    visibility: ["//packages/modules/Virtualization/build/microdroid"],
 }
 
 // container for apex_contributions selected using build flags
diff --git a/android/neverallow.go b/android/neverallow.go
index ef4b8b8..0f363e7 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -212,7 +212,7 @@
 
 func createCcStubsRule() Rule {
 	ccStubsImplementationInstallableProjectsAllowedList := []string{
-		"packages/modules/Virtualization/vm_payload",
+		"packages/modules/Virtualization/libs/libvm_payload",
 	}
 
 	return NeverAllow().
diff --git a/apex/apex_test.go b/apex/apex_test.go
index a2dbbfc..f62ee68 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -11738,3 +11738,121 @@
 		}
 	`)
 }
+
+func TestPrebuiltStubNoinstall(t *testing.T) {
+	testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
+		result := android.GroupFixturePreparers(
+			prepareForApexTest,
+			android.PrepareForTestWithAndroidMk,
+			android.PrepareForTestWithMakevars,
+			android.FixtureMergeMockFs(fs),
+		).RunTest(t)
+
+		ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
+		android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
+
+		installRules := result.InstallMakeRulesForTesting(t)
+
+		var installedlibRule *android.InstallMakeRule
+		for i, rule := range installRules {
+			if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" {
+				if installedlibRule != nil {
+					t.Errorf("Duplicate install rules for %s", rule.Target)
+				}
+				installedlibRule = &installRules[i]
+			}
+		}
+		if installedlibRule == nil {
+			t.Errorf("No install rule found for installedlib")
+			return
+		}
+
+		if expectLibfooOnSystemLib {
+			android.AssertStringListContains(t,
+				"installedlib doesn't have install dependency on libfoo impl",
+				installedlibRule.OrderOnlyDeps,
+				"out/target/product/test_device/system/lib/libfoo.so")
+		} else {
+			android.AssertStringListDoesNotContain(t,
+				"installedlib has install dependency on libfoo stub",
+				installedlibRule.Deps,
+				"out/target/product/test_device/system/lib/libfoo.so")
+			android.AssertStringListDoesNotContain(t,
+				"installedlib has order-only install dependency on libfoo stub",
+				installedlibRule.OrderOnlyDeps,
+				"out/target/product/test_device/system/lib/libfoo.so")
+		}
+	}
+
+	prebuiltLibfooBp := []byte(`
+		cc_prebuilt_library {
+			name: "libfoo",
+			prefer: true,
+			srcs: ["libfoo.so"],
+			stubs: {
+				versions: ["1"],
+			},
+			apex_available: ["apexfoo"],
+		}
+	`)
+
+	apexfooBp := []byte(`
+		apex {
+			name: "apexfoo",
+			key: "apexfoo.key",
+			native_shared_libs: ["libfoo"],
+			updatable: false,
+			compile_multilib: "both",
+		}
+		apex_key {
+			name: "apexfoo.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+	`)
+
+	installedlibBp := []byte(`
+		cc_library {
+			name: "installedlib",
+			shared_libs: ["libfoo"],
+		}
+	`)
+
+	t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
+		testFunc(
+			t,
+			/*expectLibfooOnSystemLib=*/ false,
+			android.MockFS{
+				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+				"apexfoo/Android.bp":                          apexfooBp,
+				"system/sepolicy/apex/apexfoo-file_contexts":  nil,
+				"Android.bp": installedlibBp,
+			},
+		)
+	})
+
+	disabledSourceLibfooBp := []byte(`
+		cc_library {
+			name: "libfoo",
+			enabled: false,
+			stubs: {
+				versions: ["1"],
+			},
+			apex_available: ["apexfoo"],
+		}
+	`)
+
+	t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
+		testFunc(
+			t,
+			/*expectLibfooOnSystemLib=*/ false,
+			android.MockFS{
+				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+				"impl/Android.bp":                            disabledSourceLibfooBp,
+				"apexfoo/Android.bp":                         apexfooBp,
+				"system/sepolicy/apex/apexfoo-file_contexts": nil,
+				"Android.bp":                                 installedlibBp,
+			},
+		)
+	})
+}
diff --git a/cc/cc.go b/cc/cc.go
index 64b2465..3c17be6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -4079,6 +4079,13 @@
 	return c.ModuleBase.BaseModuleName()
 }
 
+func (c *Module) stubsSymbolFilePath() android.Path {
+	if library, ok := c.linker.(*libraryDecorator); ok {
+		return library.stubsSymbolFilePath
+	}
+	return android.OptionalPath{}.Path()
+}
+
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var BoolPtr = proptools.BoolPtr
diff --git a/cc/library.go b/cc/library.go
index 6dd5b56..ff21cc3 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -428,6 +428,9 @@
 	*baseInstaller
 
 	apiListCoverageXmlPath android.ModuleOutPath
+
+	// Path to the file containing the APIs exported by this library
+	stubsSymbolFilePath android.Path
 }
 
 // linkerProps returns the list of properties structs relevant for this library. (For example, if
@@ -596,6 +599,7 @@
 			ctx.PropertyErrorf("symbol_file", "%q doesn't have .map.txt suffix", symbolFile)
 			return Objects{}
 		}
+		library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile)
 		// b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
 		// systemapi, respectively. The former is for symbols defined in platform libraries
 		// and the latter is for symbols defined in APEXes.
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 1f71c19..e8a9827 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -406,6 +406,9 @@
 	if len(libInfo.StubsVersions) > 0 {
 		stubsSet := outputProperties.AddPropertySet("stubs")
 		stubsSet.AddProperty("versions", libInfo.StubsVersions)
+		// The symbol file will be copied next to the Android.bp file
+		stubsSet.AddProperty("symbol_file", libInfo.StubsSymbolFilePath.Base())
+		builder.CopyToSnapshot(libInfo.StubsSymbolFilePath, libInfo.StubsSymbolFilePath.Base())
 	}
 }
 
@@ -481,6 +484,9 @@
 	// is written to does not vary by arch so cannot be android specific.
 	StubsVersions []string `sdk:"ignored-on-host"`
 
+	// The symbol file containing the APIs exported by this library.
+	StubsSymbolFilePath android.Path `sdk:"ignored-on-host"`
+
 	// Value of SanitizeProperties.Sanitize. Several - but not all - of these
 	// affect the expanded variants. All are propagated to avoid entangling the
 	// sanitizer logic with the snapshot generation.
@@ -549,6 +555,11 @@
 				// the versioned stub libs are retained in the prebuilt tree; currently only
 				// the stub corresponding to ccModule.StubsVersion() is.
 				p.StubsVersions = lib.allStubsVersions()
+				if lib.buildStubs() && ccModule.stubsSymbolFilePath() == nil {
+					ctx.ModuleErrorf("Could not determine symbol_file")
+				} else {
+					p.StubsSymbolFilePath = ccModule.stubsSymbolFilePath()
+				}
 			}
 		}
 		p.SystemSharedLibs = specifiedDeps.systemSharedLibs
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index e9f790f..e023a32 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -205,17 +205,6 @@
 				TableOfContents: p.tocFile,
 			})
 
-			// TODO(b/220898484): Mainline module sdk prebuilts of stub libraries use a stub
-			// library as their source and must not be installed, but other prebuilts like
-			// libclang_rt.* libraries set `stubs` property because they are LLNDK libraries,
-			// but use an implementation library as their source and need to be installed.
-			// This discrepancy should be resolved without the prefix hack below.
-			isModuleSdkPrebuilts := android.HasAnyPrefix(ctx.ModuleDir(), []string{
-				"prebuilts/runtime/mainline/", "prebuilts/module_sdk/"})
-			if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() && isModuleSdkPrebuilts {
-				ctx.Module().MakeUninstallable()
-			}
-
 			return outputFile
 		}
 	}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 71b7e43..86e6af9 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -385,112 +385,6 @@
 	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
 }
 
-func TestPrebuiltStubNoinstall(t *testing.T) {
-	testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
-		result := android.GroupFixturePreparers(
-			prepareForPrebuiltTest,
-			android.PrepareForTestWithMakevars,
-			android.FixtureMergeMockFs(fs),
-		).RunTest(t)
-
-		ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
-		android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
-
-		installRules := result.InstallMakeRulesForTesting(t)
-		var installedlibRule *android.InstallMakeRule
-		for i, rule := range installRules {
-			if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" {
-				if installedlibRule != nil {
-					t.Errorf("Duplicate install rules for %s", rule.Target)
-				}
-				installedlibRule = &installRules[i]
-			}
-		}
-		if installedlibRule == nil {
-			t.Errorf("No install rule found for installedlib")
-			return
-		}
-
-		if expectLibfooOnSystemLib {
-			android.AssertStringListContains(t,
-				"installedlib doesn't have install dependency on libfoo impl",
-				installedlibRule.OrderOnlyDeps,
-				"out/target/product/test_device/system/lib/libfoo.so")
-		} else {
-			android.AssertStringListDoesNotContain(t,
-				"installedlib has install dependency on libfoo stub",
-				installedlibRule.Deps,
-				"out/target/product/test_device/system/lib/libfoo.so")
-			android.AssertStringListDoesNotContain(t,
-				"installedlib has order-only install dependency on libfoo stub",
-				installedlibRule.OrderOnlyDeps,
-				"out/target/product/test_device/system/lib/libfoo.so")
-		}
-	}
-
-	prebuiltLibfooBp := []byte(`
-		cc_prebuilt_library {
-			name: "libfoo",
-			prefer: true,
-			srcs: ["libfoo.so"],
-			stubs: {
-				versions: ["1"],
-			},
-		}
-	`)
-
-	installedlibBp := []byte(`
-		cc_library {
-			name: "installedlib",
-			shared_libs: ["libfoo"],
-		}
-	`)
-
-	t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
-		testFunc(
-			t,
-			/*expectLibfooOnSystemLib=*/ false,
-			android.MockFS{
-				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
-				"Android.bp": installedlibBp,
-			},
-		)
-	})
-
-	disabledSourceLibfooBp := []byte(`
-		cc_library {
-			name: "libfoo",
-			enabled: false,
-			stubs: {
-				versions: ["1"],
-			},
-		}
-	`)
-
-	t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
-		testFunc(
-			t,
-			/*expectLibfooOnSystemLib=*/ false,
-			android.MockFS{
-				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
-				"impl/Android.bp": disabledSourceLibfooBp,
-				"Android.bp":      installedlibBp,
-			},
-		)
-	})
-
-	t.Run("prebuilt impl (with `stubs` property set): install", func(t *testing.T) {
-		testFunc(
-			t,
-			/*expectLibfooOnSystemLib=*/ true,
-			android.MockFS{
-				"impl/Android.bp": prebuiltLibfooBp,
-				"Android.bp":      installedlibBp,
-			},
-		)
-	})
-}
-
 func TestPrebuiltBinaryNoSrcsNoError(t *testing.T) {
 	const bp = `
 cc_prebuilt_binary {
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index b69a76f..5616483 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -244,6 +244,7 @@
 	}
 
 	odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex"))
+	odexSymbolsPath := odexPath.ReplaceExtension(ctx, "symbols.odex")
 	odexInstallPath := ToOdexPath(module.DexLocation, arch)
 	if odexOnSystemOther(module, global) {
 		odexInstallPath = filepath.Join(SystemOtherPartition, odexInstallPath)
@@ -258,7 +259,8 @@
 	systemServerClasspathJars := global.AllSystemServerClasspathJars(ctx)
 
 	rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
-	rule.Command().FlagWithOutput("rm -f ", odexPath)
+	rule.Command().FlagWithOutput("rm -f ", odexPath).
+		FlagWithArg("rm -f ", odexSymbolsPath.String())
 
 	if jarIndex := systemServerJars.IndexOfJar(module.Name); jarIndex >= 0 {
 		// System server jars should be dexpreopted together: class loader context of each jar
@@ -386,7 +388,9 @@
 		FlagWithArg("--instruction-set=", arch.String()).
 		FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]).
 		FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]).
-		Flag("--no-generate-debug-info").
+		FlagWithOutput("--oat-symbols=", odexSymbolsPath).
+		Flag("--generate-debug-info").
+		Flag("--strip").
 		Flag("--generate-build-id").
 		Flag("--abort-on-hard-verifier-error").
 		Flag("--force-determinism").
diff --git a/java/droidstubs.go b/java/droidstubs.go
index a8e0a22..d622903 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -197,6 +197,10 @@
 	// a list of aconfig_declarations module names that the stubs generated in this module
 	// depend on.
 	Aconfig_declarations []string
+
+	// List of hard coded filegroups containing Metalava config files that are passed to every
+	// Metalava invocation that this module performs. See addMetalavaConfigFilesToCmd.
+	ConfigFiles []string `android:"path" blueprint:"mutated"`
 }
 
 // Used by xsd_config
@@ -259,6 +263,7 @@
 
 	module.AddProperties(&module.properties,
 		&module.Javadoc.properties)
+	module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
 	module.initModuleAndImport(module)
 
 	InitDroiddocModule(module, android.HostAndDeviceSupported)
@@ -279,6 +284,7 @@
 	module.AddProperties(&module.properties,
 		&module.Javadoc.properties)
 
+	module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
 	InitDroiddocModule(module, android.HostSupported)
 	return module
 }
@@ -694,7 +700,7 @@
 }
 
 func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
-	srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams) *android.RuleBuilderCommand {
+	srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams, configFiles android.Paths) *android.RuleBuilderCommand {
 	rule.Command().Text("rm -rf").Flag(homeDir.String())
 	rule.Command().Text("mkdir -p").Flag(homeDir.String())
 
@@ -738,9 +744,26 @@
 
 	cmd.Flag(config.MetalavaFlags)
 
+	addMetalavaConfigFilesToCmd(cmd, configFiles)
+
 	return cmd
 }
 
+// MetalavaConfigFilegroup is the name of the filegroup in build/soong/java/metalava that lists
+// the configuration files to pass to Metalava.
+const MetalavaConfigFilegroup = "metalava-config-files"
+
+// Get a reference to the MetalavaConfigFilegroup suitable for use in a property.
+func getMetalavaConfigFilegroupReference() []string {
+	return []string{":" + MetalavaConfigFilegroup}
+}
+
+// addMetalavaConfigFilesToCmd adds --config-file options to use the config files list in the
+// MetalavaConfigFilegroup filegroup.
+func addMetalavaConfigFilesToCmd(cmd *android.RuleBuilderCommand, configFiles android.Paths) {
+	cmd.FlagForEachInput("--config-file ", configFiles)
+}
+
 // Pass flagged apis related flags to metalava. When aconfig_declarations property is not
 // defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
 // property is defined, apply transformations and only revert the flagged apis that are not
@@ -812,7 +835,10 @@
 	srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
 
 	homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
-	cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig)
+
+	configFiles := android.PathsForModuleSrc(ctx, d.properties.ConfigFiles)
+
+	cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig, configFiles)
 	cmd.Implicits(d.Javadoc.implicits)
 
 	d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
diff --git a/java/java.go b/java/java.go
index 3dae4e4..b320732 100644
--- a/java/java.go
+++ b/java/java.go
@@ -269,7 +269,7 @@
 	ImplementationAndResourcesJars android.Paths
 
 	// ImplementationJars is a list of jars that contain the implementations of classes in the
-	//module.
+	// module.
 	ImplementationJars android.Paths
 
 	// ResourceJars is a list of jars that contain the resources included in the module.
@@ -2039,12 +2039,17 @@
 	// List of aconfig_declarations module names that the stubs generated in this module
 	// depend on.
 	Aconfig_declarations []string
+
+	// List of hard coded filegroups containing Metalava config files that are passed to every
+	// Metalava invocation that this module performs. See addMetalavaConfigFilesToCmd.
+	ConfigFiles []string `android:"path" blueprint:"mutated"`
 }
 
 func ApiLibraryFactory() android.Module {
 	module := &ApiLibrary{}
-	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	module.AddProperties(&module.properties)
+	module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	module.initModuleAndImport(module)
 	android.InitDefaultableModule(module)
 	return module
@@ -2060,7 +2065,7 @@
 
 func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
 	srcs android.Paths, homeDir android.WritablePath,
-	classpath android.Paths) *android.RuleBuilderCommand {
+	classpath android.Paths, configFiles android.Paths) *android.RuleBuilderCommand {
 	rule.Command().Text("rm -rf").Flag(homeDir.String())
 	rule.Command().Text("mkdir -p").Flag(homeDir.String())
 
@@ -2099,6 +2104,8 @@
 		FlagWithArg("--hide ", "InvalidNullabilityOverride").
 		FlagWithArg("--hide ", "ChangedDefault")
 
+	addMetalavaConfigFilesToCmd(cmd, configFiles)
+
 	if len(classpath) == 0 {
 		// The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
 		// classes on the classpath when an API file contains missing classes. However, as this command
@@ -2310,7 +2317,9 @@
 		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
 	}
 
-	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths)
+	configFiles := android.PathsForModuleSrc(ctx, al.properties.ConfigFiles)
+
+	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths, configFiles)
 
 	al.stubsFlags(ctx, cmd, stubsDir)
 
diff --git a/java/metalava/Android.bp b/java/metalava/Android.bp
new file mode 100644
index 0000000..ccbd191
--- /dev/null
+++ b/java/metalava/Android.bp
@@ -0,0 +1,18 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// 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.
+
+filegroup {
+    name: "metalava-config-files",
+    srcs: ["*-config.xml"],
+}
diff --git a/java/metalava/OWNERS b/java/metalava/OWNERS
new file mode 100644
index 0000000..e8c438e
--- /dev/null
+++ b/java/metalava/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 463936
+
+file:platform/tools/metalava:/OWNERS
diff --git a/java/metalava/main-config.xml b/java/metalava/main-config.xml
new file mode 100644
index 0000000..c61196f
--- /dev/null
+++ b/java/metalava/main-config.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ 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.
+  -->
+
+<config xmlns="http://www.google.com/tools/metalava/config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.google.com/tools/metalava/config ../../../../tools/metalava/metalava/src/main/resources/schemas/config.xsd"/>
diff --git a/java/metalava/source-model-selection-config.xml b/java/metalava/source-model-selection-config.xml
new file mode 100644
index 0000000..c61196f
--- /dev/null
+++ b/java/metalava/source-model-selection-config.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ 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.
+  -->
+
+<config xmlns="http://www.google.com/tools/metalava/config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.google.com/tools/metalava/config ../../../../tools/metalava/metalava/src/main/resources/schemas/config.xsd"/>
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 1eb7ab8..3931456 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1516,6 +1516,13 @@
 
 // Add other dependencies as normal.
 func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// If the module does not create an implementation library or defaults to stubs,
+	// mark the top level sdk library as stubs module as the module will provide stubs via
+	// "magic" when listed as a dependency in the Android.bp files.
+	notCreateImplLib := proptools.Bool(module.sdkLibraryProperties.Api_only)
+	preferStubs := proptools.Bool(module.sdkLibraryProperties.Default_to_stubs)
+	module.properties.Is_stubs_module = proptools.BoolPtr(notCreateImplLib || preferStubs)
+
 	var missingApiModules []string
 	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
 		if apiScope.unstable {
diff --git a/java/testing.go b/java/testing.go
index 5ae326d..7a42e4c 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -52,6 +52,8 @@
 	android.MockFS{
 		// Needed for linter used by java_library.
 		"build/soong/java/lint_defaults.txt": nil,
+		// Needed for java components that invoke Metalava.
+		"build/soong/java/metalava/Android.bp": []byte(`filegroup {name: "metalava-config-files"}`),
 		// Needed for apps that do not provide their own.
 		"build/make/target/product/security": nil,
 		// Required to generate Java used-by API coverage
diff --git a/rust/bindgen.go b/rust/bindgen.go
index dbc3697..f1579cc 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
 	defaultBindgenFlags = []string{""}
 
 	// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
-	bindgenClangVersion = "clang-r522817"
+	bindgenClangVersion = "clang-r530567"
 
 	_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
 		if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 5d76930..25839b8 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -2205,6 +2205,7 @@
             "3",
             "current",
         ],
+        symbol_file: "stubslib.map.txt",
     },
     arch: {
         arm64: {
@@ -2268,6 +2269,7 @@
             "3",
             "current",
         ],
+        symbol_file: "stubslib.map.txt",
     },
     target: {
         host: {