Merge "Allow overriding rro category in override_runtime_resource_overlay"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 4ab94c3..b09b923 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -284,6 +284,7 @@
 		"system/core/libvndksupport":                             Bp2BuildDefaultTrueRecursively,
 		"system/core/property_service/libpropertyinfoparser":     Bp2BuildDefaultTrueRecursively,
 		"system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
+		"system/extras/toolchain-extras":                         Bp2BuildDefaultTrue,
 		"system/incremental_delivery/incfs":                      Bp2BuildDefaultTrue,
 		"system/libartpalette":                                   Bp2BuildDefaultTrueRecursively,
 		"system/libbase":                                         Bp2BuildDefaultTrueRecursively,
diff --git a/apex/key.go b/apex/key.go
index d449589..2b09f1d 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -44,8 +44,6 @@
 
 	publicKeyFile  android.Path
 	privateKeyFile android.Path
-
-	keyName string
 }
 
 type apexKeyProperties struct {
@@ -102,7 +100,6 @@
 			m.publicKeyFile.String(), pubKeyName, m.privateKeyFile, privKeyName)
 		return
 	}
-	m.keyName = pubKeyName
 }
 
 // //////////////////////////////////////////////////////////////////////
@@ -203,8 +200,11 @@
 // For Bazel / bp2build
 
 type bazelApexKeyAttributes struct {
-	Public_key  bazel.LabelAttribute
-	Private_key bazel.LabelAttribute
+	Public_key      bazel.LabelAttribute
+	Public_key_name bazel.LabelAttribute
+
+	Private_key      bazel.LabelAttribute
+	Private_key_name bazel.LabelAttribute
 }
 
 // ConvertWithBp2build performs conversion apexKey for bp2build
@@ -214,18 +214,33 @@
 
 func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) {
 	var privateKeyLabelAttribute bazel.LabelAttribute
+	var privateKeyNameAttribute bazel.LabelAttribute
 	if module.properties.Private_key != nil {
-		privateKeyLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Private_key))
+		m := String(module.properties.Private_key)
+		if android.SrcIsModule(m) == "" {
+			privateKeyNameAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Private_key))
+		} else {
+			privateKeyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.properties.Private_key))
+		}
 	}
 
 	var publicKeyLabelAttribute bazel.LabelAttribute
+	var publicKeyNameAttribute bazel.LabelAttribute
 	if module.properties.Public_key != nil {
-		publicKeyLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Public_key))
+		m := String(module.properties.Public_key)
+		if android.SrcIsModule(m) == "" {
+			publicKeyNameAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Public_key))
+		} else {
+			publicKeyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.properties.Public_key))
+		}
 	}
 
 	attrs := &bazelApexKeyAttributes{
-		Private_key: privateKeyLabelAttribute,
-		Public_key:  publicKeyLabelAttribute,
+		Private_key:      privateKeyLabelAttribute,
+		Private_key_name: privateKeyNameAttribute,
+
+		Public_key:      publicKeyLabelAttribute,
+		Public_key_name: publicKeyNameAttribute,
 	}
 
 	props := bazel.BazelTargetModuleProperties{
diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go
index 15bccf7..79b1d89 100644
--- a/bp2build/apex_key_conversion_test.go
+++ b/bp2build/apex_key_conversion_test.go
@@ -27,11 +27,12 @@
 }
 
 func registerApexKeyModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 }
 
-func TestApexKeySimple(t *testing.T) {
+func TestApexKeySimple_KeysAreSrcFiles(t *testing.T) {
 	runApexKeyTestCase(t, Bp2buildTestCase{
-		Description:                "apex key - simple example",
+		Description:                "apex key - keys are src files, use key_name attributes",
 		ModuleTypeUnderTest:        "apex_key",
 		ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
 		Filesystem:                 map[string]string{},
@@ -43,8 +44,29 @@
 }
 `,
 		ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
-			"private_key": `"com.android.apogee.pem"`,
-			"public_key":  `"com.android.apogee.avbpubkey"`,
+			"private_key_name": `"com.android.apogee.pem"`,
+			"public_key_name":  `"com.android.apogee.avbpubkey"`,
+		}),
+		}})
+}
+
+func TestApexKey_KeysAreModules(t *testing.T) {
+	runApexKeyTestCase(t, Bp2buildTestCase{
+		Description:                "apex key - keys are modules, use key attributes",
+		ModuleTypeUnderTest:        "apex_key",
+		ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
+		Filesystem:                 map[string]string{},
+		Blueprint: `
+apex_key {
+        name: "com.android.apogee.key",
+        public_key: ":com.android.apogee.avbpubkey",
+        private_key: ":com.android.apogee.pem",
+}
+` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.avbpubkey") +
+			simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.pem"),
+		ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
+			"private_key": `":com.android.apogee.pem"`,
+			"public_key":  `":com.android.apogee.avbpubkey"`,
 		}),
 		}})
 }
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 72d3940..8aa2c3e 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -228,6 +228,38 @@
 	})
 }
 
+func TestCcBinaryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) {
+	runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+		description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
+		blueprint: `
+{rule_name} {
+    name: "foo",
+		ldflags: [
+			"--nospace_flag",
+			"-z spaceflag",
+		],
+		version_script: "version_script",
+		dynamic_list: "dynamic.list",
+    include_build_directory: false,
+}
+`,
+		targets: []testBazelTarget{
+			{"cc_binary", "foo", AttrNameToString{
+				"additional_linker_inputs": `[
+        "version_script",
+        "dynamic.list",
+    ]`,
+				"linkopts": `[
+        "--nospace_flag",
+        "-z",
+        "spaceflag",
+        "-Wl,--version-script,$(location version_script)",
+        "-Wl,--dynamic-list,$(location dynamic.list)",
+    ]`,
+			}}},
+	})
+}
+
 func TestCcBinarySplitSrcsByLang(t *testing.T) {
 	runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{
 		description: "split srcs by lang",
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 728a4dc..d4461b6 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -961,6 +961,46 @@
 	)
 }
 
+func TestCcLibraryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Filesystem: map[string]string{
+			"version_script": "",
+			"dynamic.list":   "",
+		},
+		Blueprint: `
+cc_library {
+    name: "foo",
+    ldflags: [
+        "--nospace_flag",
+        "-z spaceflag",
+    ],
+    version_script: "version_script",
+    dynamic_list: "dynamic.list",
+    include_build_directory: false,
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"additional_linker_inputs": `[
+        "version_script",
+        "dynamic.list",
+    ]`,
+				"linkopts": `[
+        "--nospace_flag",
+        "-z",
+        "spaceflag",
+        "-Wl,--version-script,$(location version_script)",
+        "-Wl,--dynamic-list,$(location dynamic.list)",
+    ]`,
+			}),
+		},
+	})
+}
+
 func TestCcLibrarySharedLibs(t *testing.T) {
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		Description:                "cc_library shared_libs",
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 6253de6..b86f607 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -367,6 +367,42 @@
 	})
 }
 
+func TestCcLibraryLdflagsSplitBySpaceSoongAdded(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
+		Filesystem: map[string]string{
+			"version_script": "",
+			"dynamic.list":   "",
+		},
+		Blueprint: `
+cc_library_shared {
+    name: "foo",
+    ldflags: [
+        "--nospace_flag",
+        "-z spaceflag",
+    ],
+    version_script: "version_script",
+    dynamic_list: "dynamic.list",
+    include_build_directory: false,
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"additional_linker_inputs": `[
+        "version_script",
+        "dynamic.list",
+    ]`,
+				"linkopts": `[
+        "--nospace_flag",
+        "-z",
+        "spaceflag",
+        "-Wl,--version-script,$(location version_script)",
+        "-Wl,--dynamic-list,$(location dynamic.list)",
+    ]`,
+			}),
+		},
+	})
+}
+
 func TestCcLibrarySharedNoCrtTrue(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
 		Description: "cc_library_shared - nocrt: true emits attribute",
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index 023ec96..7c39a11 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -285,6 +285,17 @@
 			// Neither is a directory. Merge them.
 			srcBuildFile := shared.JoinPath(topdir, srcChild)
 			generatedBuildFile := shared.JoinPath(topdir, buildFilesChild)
+			// Add the src and generated build files as dependencies so that bp2build
+			// is rerun when they change. Currently, this is only really necessary
+			// for srcBuildFile, because if we regenerate the generated build files
+			// we will always rerun the symlink forest generation as well. If that
+			// is later split up into separate, fully dependency-tracing steps, then
+			// we'll need srcBuildFile as well. Adding srcBuildFile here today
+			// technically makes it a dependency of bp2build_workspace_marker, which
+			// also implicitly outputs that file, but since bp2build_workspace_marker
+			// will always have a newer timestamp than the generatedBuildFile it
+			// shouldn't be a problem.
+			*acc = append(*acc, srcBuildFile, generatedBuildFile)
 			err = mergeBuildFiles(shared.JoinPath(topdir, forestChild), srcBuildFile, generatedBuildFile, cfg.IsEnvTrue("BP2BUILD_VERBOSE"))
 			if err != nil {
 				fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s",
diff --git a/bpf/bpf.go b/bpf/bpf.go
index dbbce50..60a410d 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -22,6 +22,7 @@
 
 	"android/soong/android"
 	"android/soong/bazel"
+	"android/soong/bazel/cquery"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -239,6 +240,35 @@
 	}
 }
 
+var _ android.MixedBuildBuildable = (*bpf)(nil)
+
+func (bpf *bpf) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
+	return true
+}
+
+func (bpf *bpf) QueueBazelCall(ctx android.BaseModuleContext) {
+	bazelCtx := ctx.Config().BazelContext
+	bazelCtx.QueueBazelRequest(
+		bpf.GetBazelLabel(ctx, bpf),
+		cquery.GetOutputFiles,
+		android.GetConfigKey(ctx))
+}
+
+func (bpf *bpf) ProcessBazelQueryResponse(ctx android.ModuleContext) {
+	bazelCtx := ctx.Config().BazelContext
+	objPaths, err := bazelCtx.GetOutputFiles(bpf.GetBazelLabel(ctx, bpf), android.GetConfigKey(ctx))
+	if err != nil {
+		ctx.ModuleErrorf(err.Error())
+		return
+	}
+
+	bazelOuts := android.Paths{}
+	for _, p := range objPaths {
+		bazelOuts = append(bazelOuts, android.PathForBazelOut(ctx, p))
+	}
+	bpf.objs = bazelOuts
+}
+
 // Implements OutputFileFileProducer interface so that the obj output can be used in the data property
 // of other modules.
 func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index 6e39096..a2010ff 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -71,3 +71,26 @@
 		`\QAndroid.bp:2:3: module "bpf_invalid_name.o" variant "android_common": invalid character '_' in source name\E`)).
 		RunTestWithBp(t, bp)
 }
+
+func TestBpfWithBazel(t *testing.T) {
+	bp := `
+		bpf {
+			name: "bpf.o",
+			srcs: ["bpf.c"],
+			bazel_module: { label: "//bpf" },
+		}
+	`
+
+	result := android.GroupFixturePreparers(
+		prepareForBpfTest, android.FixtureModifyConfig(func(config android.Config) {
+			config.BazelContext = android.MockBazelContext{
+				OutputBaseDir: "outputbase",
+				LabelToOutputFiles: map[string][]string{
+					"//bpf": []string{"bpf.o"}}}
+		})).RunTestWithBp(t, bp)
+
+	output := result.Module("bpf.o", "android_common").(*bpf)
+
+	expectedOutputFiles := []string{"outputbase/execroot/__main__/bpf.o"}
+	android.AssertDeepEquals(t, "output files", expectedOutputFiles, output.objs.Strings())
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 83368a3..868ff0d 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -174,7 +174,7 @@
 	attrs := staticOrSharedAttributes{}
 
 	setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
-		attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag))
+		attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag))
 		attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
 		attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
 
@@ -365,7 +365,7 @@
 	return false
 }
 
-func parseCommandLineFlags(soongFlags []string, noCoptsTokenization bool, filterOut ...filterOutFn) []string {
+func parseCommandLineFlags(soongFlags []string, filterOut ...filterOutFn) []string {
 	var result []string
 	for _, flag := range soongFlags {
 		skipFlag := false
@@ -380,15 +380,7 @@
 		// Soong's cflags can contain spaces, like `-include header.h`. For
 		// Bazel's copts, split them up to be compatible with the
 		// no_copts_tokenization feature.
-		if noCoptsTokenization {
-			result = append(result, strings.Split(flag, " ")...)
-		} else {
-			// Soong's Version Script and Dynamic List Properties are added as flags
-			// to Bazel's linkopts using "($location label)" syntax.
-			// Splitting on spaces would separate this into two different flags
-			// "($ location" and "label)"
-			result = append(result, flag)
-		}
+		result = append(result, strings.Split(flag, " ")...)
 	}
 	return result
 }
@@ -422,10 +414,10 @@
 	// overridden. In Bazel we always allow overriding, via flags; however, this can cause
 	// incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other
 	// cases.
-	ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag, filterOutClangUnknownCflags))
-	ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, true, nil))
-	ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, true, filterOutClangUnknownCflags))
-	ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, true, filterOutClangUnknownCflags))
+	ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutClangUnknownCflags))
+	ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, nil))
+	ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, filterOutClangUnknownCflags))
+	ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, filterOutClangUnknownCflags))
 	ca.rtti.SetSelectValue(axis, config, props.Rtti)
 }
 
@@ -1031,6 +1023,11 @@
 			axisFeatures = append(axisFeatures, "-static_flag")
 		}
 	}
+
+	// This must happen before the addition of flags for Version Script and
+	// Dynamic List, as these flags must be split on spaces and those must not
+	linkerFlags = parseCommandLineFlags(linkerFlags, filterOutClangUnknownCflags)
+
 	additionalLinkerInputs := bazel.LabelList{}
 	if props.Version_script != nil {
 		label := android.BazelLabelForModuleSrcSingle(ctx, *props.Version_script)
@@ -1045,7 +1042,7 @@
 	}
 
 	la.additionalLinkerInputs.SetSelectValue(axis, config, additionalLinkerInputs)
-	la.linkopts.SetSelectValue(axis, config, parseCommandLineFlags(linkerFlags, false, filterOutClangUnknownCflags))
+	la.linkopts.SetSelectValue(axis, config, linkerFlags)
 	la.useLibcrt.SetSelectValue(axis, config, props.libCrt())
 
 	// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
diff --git a/java/config/config.go b/java/config/config.go
index ea44aaa..a84c315 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -132,12 +132,7 @@
 		if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
 			return override
 		}
-		switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") {
-		case "true":
-			return "17"
-		default:
-			return "11"
-		}
+		return "17"
 	})
 
 	pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go
index e64cb48..b704d09 100644
--- a/java/dexpreopt_config_test.go
+++ b/java/dexpreopt_config_test.go
@@ -15,7 +15,6 @@
 package java
 
 import (
-	"log"
 	"runtime"
 	"testing"
 
@@ -24,8 +23,7 @@
 
 func TestBootImageConfig(t *testing.T) {
 	if runtime.GOOS != "linux" {
-		log.Printf("Skipping as boot image config test is only supported on linux not %s", runtime.GOOS)
-		return
+		t.Skipf("Skipping as boot image config test is only supported on linux not %s", runtime.GOOS)
 	}
 
 	result := android.GroupFixturePreparers(
diff --git a/ui/build/config.go b/ui/build/config.go
index 2060660..f6f5b46 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -388,13 +388,13 @@
 		if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
 			return override
 		}
-		if ret.environ.IsEnvTrue("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") {
-			return java17Home
-		}
 		if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
 			ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
 		}
-		return java11Home
+		if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
+			ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
+		}
+		return java17Home
 	}()
 	absJavaHome := absPath(ctx, javaHome)