Merge "export allowlist of environment variables to Bazel"
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 17d0124..9ff6b52 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -205,9 +205,11 @@
 // and their results after the requests have been made.
 type mixedBuildBazelContext struct {
 	bazelRunner
-	paths        *bazelPaths
-	requests     map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
-	requestMutex sync.Mutex         // requests can be written in parallel
+	paths *bazelPaths
+	// cquery requests that have not yet been issued to Bazel. This list is maintained
+	// in a sorted state, and is guaranteed to have no duplicates.
+	requests     []cqueryKey
+	requestMutex sync.Mutex // requests can be written in parallel
 
 	results map[cqueryKey]string // Results of cquery requests after Bazel invocations
 
@@ -318,7 +320,29 @@
 	key := makeCqueryKey(label, requestType, cfgKey)
 	bazelCtx.requestMutex.Lock()
 	defer bazelCtx.requestMutex.Unlock()
-	bazelCtx.requests[key] = true
+
+	// Insert key into requests, maintaining the sort, and only if it's not duplicate.
+	keyString := key.String()
+	foundEqual := false
+	notLessThanKeyString := func(i int) bool {
+		s := bazelCtx.requests[i].String()
+		v := strings.Compare(s, keyString)
+		if v == 0 {
+			foundEqual = true
+		}
+		return v >= 0
+	}
+	targetIndex := sort.Search(len(bazelCtx.requests), notLessThanKeyString)
+	if foundEqual {
+		return
+	}
+
+	if targetIndex == len(bazelCtx.requests) {
+		bazelCtx.requests = append(bazelCtx.requests, key)
+	} else {
+		bazelCtx.requests = append(bazelCtx.requests[:targetIndex+1], bazelCtx.requests[targetIndex:]...)
+		bazelCtx.requests[targetIndex] = key
+	}
 }
 
 func (bazelCtx *mixedBuildBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
@@ -509,7 +533,6 @@
 	return &mixedBuildBazelContext{
 		bazelRunner:           &builtinBazelRunner{},
 		paths:                 &paths,
-		requests:              make(map[cqueryKey]bool),
 		modulesDefaultToBazel: c.BuildMode == BazelDevMode,
 		bazelEnabledModules:   enabledModules,
 		bazelDisabledModules:  disabledModules,
@@ -756,14 +779,23 @@
 	configNodesSection := ""
 
 	labelsByConfig := map[string][]string{}
-	for val := range context.requests {
+
+	for _, val := range context.requests {
 		labelString := fmt.Sprintf("\"@%s\"", val.label)
 		configString := getConfigString(val)
 		labelsByConfig[configString] = append(labelsByConfig[configString], labelString)
 	}
 
+	// Configs need to be sorted to maintain determinism of the BUILD file.
+	sortedConfigs := make([]string, 0, len(labelsByConfig))
+	for val := range labelsByConfig {
+		sortedConfigs = append(sortedConfigs, val)
+	}
+	sort.Slice(sortedConfigs, func(i, j int) bool { return sortedConfigs[i] < sortedConfigs[j] })
+
 	allLabels := []string{}
-	for configString, labels := range labelsByConfig {
+	for _, configString := range sortedConfigs {
+		labels := labelsByConfig[configString]
 		configTokens := strings.Split(configString, "|")
 		if len(configTokens) != 2 {
 			panic(fmt.Errorf("Unexpected config string format: %s", configString))
@@ -794,7 +826,7 @@
 // request type.
 func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
 	requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
-	for val := range context.requests {
+	for _, val := range context.requests {
 		cqueryId := getCqueryId(val)
 		mapEntryString := fmt.Sprintf("%q : True", cqueryId)
 		requestTypeToCqueryIdEntries[val.requestType] =
@@ -973,7 +1005,7 @@
 	}
 
 	// Clear requests.
-	context.requests = map[cqueryKey]bool{}
+	context.requests = []cqueryKey{}
 	return nil
 }
 
@@ -990,17 +1022,17 @@
 			return err
 		}
 	}
-	if err := os.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
+	if err := writeFileBytesIfChanged(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
 		return err
 	}
-	if err := os.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
+	if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
 		return err
 	}
-	if err := os.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
+	if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
 		return err
 	}
 	cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
-	if err := os.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
+	if err := writeFileBytesIfChanged(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
 		return err
 	}
 
@@ -1021,7 +1053,7 @@
 			cqueryResults[splitLine[0]] = splitLine[1]
 		}
 	}
-	for val := range context.requests {
+	for _, val := range context.requests {
 		if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
 			context.results[val] = cqueryResult
 		} else {
@@ -1032,6 +1064,14 @@
 	return nil
 }
 
+func writeFileBytesIfChanged(path string, contents []byte, perm os.FileMode) error {
+	oldContents, err := os.ReadFile(path)
+	if err != nil || !bytes.Equal(contents, oldContents) {
+		err = os.WriteFile(path, contents, perm)
+	}
+	return nil
+}
+
 func (context *mixedBuildBazelContext) runAquery(config Config, ctx *Context) error {
 	if ctx != nil {
 		ctx.EventHandler.Begin("aquery")
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 013e19c..d971802 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -168,6 +168,32 @@
 	}
 }
 
+func TestBazelRequestsSorted(t *testing.T) {
+	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
+
+	bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+	bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, configKey{"arm64_armv8-a", Android})
+	bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+	bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+	bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Linux})
+	bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+	bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"otherarch", Android})
+	bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, configKey{"otherarch", Android})
+
+	if len(bazelContext.requests) != 7 {
+		t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
+	}
+
+	lastString := ""
+	for _, val := range bazelContext.requests {
+		thisString := val.String()
+		if thisString <= lastString {
+			t.Errorf("Requests are not ordered correctly. '%s' came before '%s'", lastString, thisString)
+		}
+		lastString = thisString
+	}
+}
+
 func verifyExtraFlags(t *testing.T, config Config, expected string) string {
 	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
 
@@ -204,7 +230,6 @@
 	return &mixedBuildBazelContext{
 		bazelRunner: runner,
 		paths:       &p,
-		requests:    map[cqueryKey]bool{},
 	}, p.soongOutDir
 }
 
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7babd45..12faf22 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -23,6 +23,7 @@
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/java"
+	"android/soong/rust"
 
 	"github.com/google/blueprint/proptools"
 )
@@ -256,6 +257,10 @@
 				if ccMod.CoverageOutputFile().Valid() {
 					fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
 				}
+			} else if rustMod, ok := fi.module.(*rust.Module); ok {
+				if rustMod.UnstrippedOutputFile() != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
+				}
 			}
 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk")
 		default:
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 31e848e..4f300e7 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4138,8 +4138,6 @@
 	module := ctx.ModuleForTests("myapex", "android_common_com.android.myapex_image")
 	apexManifestRule := module.Rule("apexManifestRule")
 	ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
-	apexRule := module.Rule("apexRule")
-	ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
 
 	apexBundle := module.Module().(*apexBundle)
 	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
diff --git a/apex/builder.go b/apex/builder.go
index 4331d3e..4aef3c1 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -706,12 +706,6 @@
 			optFlags = append(optFlags, "--unsigned_payload")
 		}
 
-		if a.properties.Apex_name != nil {
-			// If apex_name is set, apexer can skip checking if key name matches with
-			// apex name.  Note that apex_manifest is also mended.
-			optFlags = append(optFlags, "--do_not_check_keyname")
-		}
-
 		if moduleMinSdkVersion == android.SdkVersion_Android10 {
 			implicitInputs = append(implicitInputs, a.manifestJsonOut)
 			optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
diff --git a/cc/config/global.go b/cc/config/global.go
index d557c0b..1aec190 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -293,6 +293,9 @@
 
 		// http://b/239661264
 		"-Wno-deprecated-non-prototype",
+
+		// http://b/191699019
+		"-Wno-format-insufficient-args",
 	}
 
 	llvmNextExtraCommonGlobalCflags = []string{
diff --git a/cc/stl.go b/cc/stl.go
index 6353a4a..f1433ef 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -38,9 +38,9 @@
 func getNdkStlFamilyAndLinkType(m LinkableInterface) (string, string) {
 	stl := m.SelectedStl()
 	switch stl {
-	case "ndk_libc++_shared":
+	case "ndk_libc++_shared", "libc++":
 		return "libc++", "shared"
-	case "ndk_libc++_static":
+	case "ndk_libc++_static", "libc++_static":
 		return "libc++", "static"
 	case "ndk_system":
 		return "system", "shared"
@@ -80,7 +80,8 @@
 			return ""
 		}
 		s = deduplicateStlInput(s)
-		if ctx.useSdk() && ctx.Device() {
+		archHasNDKStl := ctx.Arch().ArchType != android.Riscv64
+		if ctx.useSdk() && ctx.Device() && archHasNDKStl {
 			switch s {
 			case "", "system":
 				return "ndk_system"
diff --git a/java/app.go b/java/app.go
index e7e52d4..5234808 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1524,7 +1524,6 @@
 		appAttrs.javaCommonAttributes = commonAttrs
 		appAttrs.bazelAapt = aapt
 		appAttrs.Deps = deps
-		ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, appAttrs)
 	} else {
 		ktName := a.Name() + "_kt"
 		commonAttrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, a.properties.Common_srcs))
@@ -1545,11 +1544,12 @@
 
 		appAttrs.bazelAapt = &bazelAapt{Manifest: aapt.Manifest}
 		appAttrs.Deps = bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + ktName})
-		ctx.CreateBazelTargetModule(
-			props,
-			android.CommonAttributes{Name: a.Name()},
-			appAttrs,
-		)
 	}
 
+	ctx.CreateBazelTargetModule(
+		props,
+		android.CommonAttributes{Name: a.Name()},
+		appAttrs,
+	)
+
 }
diff --git a/java/droidstubs.go b/java/droidstubs.go
index d9613e5..8a521aa 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -878,11 +878,13 @@
 		Name        *string
 		Api_surface *string
 		Api_file    *string
+		Visibility  []string
 	}{}
 
 	props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
 	props.Api_surface = api_surface
 	props.Api_file = api_file
+	props.Visibility = []string{"//visibility:override", "//visibility:public"}
 
 	ctx.CreateModule(ApiContributionFactory, &props)
 }
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 6c22937..7a04d73 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -370,3 +370,36 @@
 
 	ctx.ModuleForTests("foo.api.contribution", "")
 }
+
+func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
+	library_bp := `
+		java_api_library {
+			name: "bar",
+			api_surface: "public",
+			api_contributions: ["foo.api.contribution"],
+		}
+	`
+	ctx, _ := testJavaWithFS(t, `
+			droidstubs {
+				name: "foo",
+				srcs: ["A/a.java"],
+				api_surface: "public",
+				check_api: {
+					current: {
+						api_file: "A/current.txt",
+						removed_api_file: "A/removed.txt",
+					}
+				},
+				visibility: ["//a"],
+			}
+		`,
+		map[string][]byte{
+			"a/a.java":      nil,
+			"a/current.txt": nil,
+			"a/removed.txt": nil,
+			"b/Android.bp":  []byte(library_bp),
+		},
+	)
+
+	ctx.ModuleForTests("bar", "android_common")
+}
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index a02c195..08bd80c 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -75,6 +75,7 @@
 jdk\.internal\.ref
 jdk\.internal\.reflect
 jdk\.internal\.util
+jdk\.internal\.util\.jar
 jdk\.internal\.vm\.annotation
 jdk\.net
 org\.w3c\.dom