Merge "Bp2build Sanitizer Blocklist"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index f826f5c..64e9958 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -1486,6 +1486,17 @@
 		"ICU4CTestRunner",
 
 		"HelloWorldHostTest", // TODO(b/280452825): Convert HelloWorldHostTest to b test
+
+		"libprotobuf-full-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
+		"libprotobuf-lite-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
+
+		"expresscatalogvalidator", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
+
+		// depends on other //art modules
+		"libart-for-test",
+		"libart_generated_headers",
+		"libart-runtime-gtest",
+		"libartd-runtime-gtest",
 	}
 
 	MixedBuildsDisabledList = []string{
diff --git a/bp2build/testing.go b/bp2build/testing.go
index fd99ff0..f3263a1 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -76,10 +76,19 @@
 	Description                string
 	ModuleTypeUnderTest        string
 	ModuleTypeUnderTestFactory android.ModuleFactory
-	Blueprint                  string
-	ExpectedBazelTargets       []string
-	Filesystem                 map[string]string
-	Dir                        string
+	// Text to add to the toplevel, root Android.bp file. If Dir is not set, all
+	// ExpectedBazelTargets are assumed to be generated by this file.
+	Blueprint            string
+	// ExpectedBazelTargets compares the BazelTargets generated in `Dir` (if not empty).
+	// Otherwise, it checks the BazelTargets generated by `Blueprint` in the root directory.
+	ExpectedBazelTargets []string
+	Filesystem           map[string]string
+	// Dir sets the directory which will be compared against the targets in ExpectedBazelTargets.
+	// This should used in conjunction with the Filesystem property to check for targets
+	// generated from a directory that is not the root.
+	// If not set, all ExpectedBazelTargets are assumed to be generated by the text in the
+	// Blueprint property.
+	Dir string
 	// An error with a string contained within the string of the expected error
 	ExpectedErr         error
 	UnconvertedDepsMode unconvertedDepsMode
diff --git a/cc/cc.go b/cc/cc.go
index fe85cae..3484000 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1077,6 +1077,10 @@
 	return false
 }
 
+func (c *Module) RustLibraryInterface() bool {
+	return false
+}
+
 func (c *Module) IsFuzzModule() bool {
 	if _, ok := c.compiler.(*fuzzBinary); ok {
 		return true
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index d66697c..77ee977 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -29,14 +29,14 @@
 		// A temporary fix for SExtWRemoval miscompilation bug.
 		"-mllvm",
 		"-riscv-disable-sextw-removal=true",
-		"-march=rv64gc_zbb",
+		"-march=rv64gc_zba_zbb",
 	}
 
 	riscv64ArchVariantCflags = map[string][]string{}
 
 	riscv64Ldflags = []string{
 		"-Wl,--hash-style=gnu",
-		"-march=rv64gc_zbb",
+		"-march=rv64gc_zba_zbb",
 	}
 
 	riscv64Lldflags = append(riscv64Ldflags,
diff --git a/cc/fuzz.go b/cc/fuzz.go
index c897501..636ad85 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -535,6 +535,17 @@
 	})
 
 	ctx.WalkDeps(func(child, parent android.Module) bool {
+
+		// If this is a Rust module which is not rust_ffi_shared, we still want to bundle any transitive
+		// shared dependencies (even for rust_ffi_static)
+		if rustmod, ok := child.(LinkableInterface); ok && rustmod.RustLibraryInterface() && !rustmod.Shared() {
+			if recursed[ctx.OtherModuleName(child)] {
+				return false
+			}
+			recursed[ctx.OtherModuleName(child)] = true
+			return true
+		}
+
 		if !IsValidSharedDependency(child) {
 			return false
 		}
diff --git a/cc/linkable.go b/cc/linkable.go
index 557f5d2..976a382 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -100,6 +100,9 @@
 	CcLibrary() bool
 	CcLibraryInterface() bool
 
+	// RustLibraryInterface returns true if this is a Rust library module
+	RustLibraryInterface() bool
+
 	// BaseModuleName returns the android.ModuleBase.BaseModuleName() value for this module.
 	BaseModuleName() string
 
diff --git a/cc/lto_test.go b/cc/lto_test.go
index 4220f32..e0afd4a 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -23,6 +23,12 @@
 	"github.com/google/blueprint"
 )
 
+var NoGlobalThinLTOPreparer = android.GroupFixturePreparers(
+	prepareForCcTest,
+	android.FixtureModifyEnv(func(env map[string]string) {
+		env["GLOBAL_THINLTO"] = "false"
+	}))
+
 func TestThinLtoDeps(t *testing.T) {
 	t.Parallel()
 	bp := `
@@ -57,9 +63,7 @@
 	}
 `
 
-	result := android.GroupFixturePreparers(
-		prepareForCcTest,
-	).RunTestWithBp(t, bp)
+	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
 
 	libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
 
@@ -137,9 +141,7 @@
 	}
 `
 
-	result := android.GroupFixturePreparers(
-		prepareForCcTest,
-	).RunTestWithBp(t, bp)
+	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
 
 	libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
 	libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()
@@ -197,9 +199,7 @@
 			},
 		},
 	}`
-	result := android.GroupFixturePreparers(
-		prepareForCcTest,
-	).RunTestWithBp(t, bp)
+	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
 
 	libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
 	libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
@@ -227,9 +227,7 @@
 		},
 	}`
 
-	result := android.GroupFixturePreparers(
-		prepareForCcTest,
-	).RunTestWithBp(t, bp)
+	result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
 
 	libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
 	libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index e903c0a..d2eadba 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -817,6 +817,9 @@
 		ctx.SetNameInterface(newNameResolver(ctx.Config()))
 		ctx.RegisterForBazelConversion()
 		ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
+		// Skip cloning modules during bp2build's blueprint run. Some mutators set
+		// bp2build-related module values which should be preserved during codegen.
+		ctx.SkipCloneModulesAfterMutators = true
 
 		var ninjaDeps []string
 		ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
diff --git a/cmd/zipsync/zipsync.go b/cmd/zipsync/zipsync.go
index aecdc3d..b3e78d0 100644
--- a/cmd/zipsync/zipsync.go
+++ b/cmd/zipsync/zipsync.go
@@ -29,10 +29,14 @@
 var (
 	outputDir  = flag.String("d", "", "output dir")
 	outputFile = flag.String("l", "", "output list file")
-	filter     = flag.String("f", "", "optional filter pattern")
 	zipPrefix  = flag.String("zip-prefix", "", "optional prefix within the zip file to extract, stripping the prefix")
+	filter     multiFlag
 )
 
+func init() {
+	flag.Var(&filter, "f", "optional filter pattern")
+}
+
 func must(err error) {
 	if err != nil {
 		log.Fatal(err)
@@ -107,13 +111,15 @@
 				}
 				name = strings.TrimPrefix(name, *zipPrefix)
 			}
-			if *filter != "" {
-				if match, err := filepath.Match(*filter, filepath.Base(name)); err != nil {
+
+			if filter != nil {
+				if match, err := filter.Match(filepath.Base(name)); err != nil {
 					log.Fatal(err)
 				} else if !match {
 					continue
 				}
 			}
+
 			if filepath.IsAbs(name) {
 				log.Fatalf("%q in %q is an absolute path", name, input)
 			}
@@ -151,3 +157,28 @@
 		must(ioutil.WriteFile(*outputFile, []byte(data), 0666))
 	}
 }
+
+type multiFlag []string
+
+func (m *multiFlag) String() string {
+	return strings.Join(*m, " ")
+}
+
+func (m *multiFlag) Set(s string) error {
+	*m = append(*m, s)
+	return nil
+}
+
+func (m *multiFlag) Match(s string) (bool, error) {
+	if m == nil {
+		return false, nil
+	}
+	for _, f := range *m {
+		if match, err := filepath.Match(f, s); err != nil {
+			return false, err
+		} else if match {
+			return true, nil
+		}
+	}
+	return false, nil
+}
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index b0508cb..1fe30db 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -86,7 +86,6 @@
 		"ltp_config_x86_64",
 		"vm-tests-tf-lib",
 		"hidl_cpp_impl_test_gen-headers",
-		"pandora_experimental-python-gen-src",
 		"Refocus-rscript",
 		"RSTest_v11-rscript",
 		"RSTest_v16-rscript",
@@ -122,7 +121,6 @@
 		"nos_app_weaver_service_genc++_headers",
 		"nos_app_weaver_service_genc++_mock",
 		"nos_generator_test_service_genc++",
-		"pandora-python-gen-src",
 	}
 
 	SandboxingDenyPathList = []string{
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 889bccd..a7264cc 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -24,7 +24,6 @@
 	"path/filepath"
 	"strconv"
 	"strings"
-	"sync"
 
 	"android/soong/bazel/cquery"
 
@@ -61,12 +60,6 @@
 	PrepareForTestWithGenRuleBuildComponents,
 )
 
-var DepfileAllowSet map[string]bool
-var SandboxingDenyModuleSet map[string]bool
-var SandboxingDenyPathSet map[string]bool
-var SandboxingDenyModuleSetLock sync.Mutex
-var DepfileAllowSetLock sync.Mutex
-
 func RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
 
@@ -618,15 +611,10 @@
 	// Allowlist genrule to use depfile until we have a solution to remove it.
 	// TODO(b/235582219): Remove allowlist for genrule
 	if Bool(g.properties.Depfile) {
-		if DepfileAllowSet == nil {
-			DepfileAllowSetLock.Lock()
-			defer DepfileAllowSetLock.Unlock()
-			DepfileAllowSet = map[string]bool{}
-			android.AddToStringSet(DepfileAllowSet, DepfileAllowList)
-		}
+		sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx)
 		// TODO(b/283852474): Checking the GenruleSandboxing flag is temporary in
 		// order to pass the presubmit before internal master is updated.
-		if ctx.DeviceConfig().GenruleSandboxing() && !DepfileAllowSet[g.Name()] {
+		if ctx.DeviceConfig().GenruleSandboxing() && !sandboxingAllowlistSets.depfileAllowSet[g.Name()] {
 			ctx.PropertyErrorf(
 				"depfile",
 				"Deprecated to ensure the module type is convertible to Bazel. "+
@@ -1067,20 +1055,37 @@
 	return module
 }
 
+var sandboxingAllowlistKey = android.NewOnceKey("genruleSandboxingAllowlistKey")
+
+type sandboxingAllowlistSets struct {
+	sandboxingDenyModuleSet map[string]bool
+	sandboxingDenyPathSet   map[string]bool
+	depfileAllowSet         map[string]bool
+}
+
+func getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSets {
+	return ctx.Config().Once(sandboxingAllowlistKey, func() interface{} {
+		sandboxingDenyModuleSet := map[string]bool{}
+		sandboxingDenyPathSet := map[string]bool{}
+		depfileAllowSet := map[string]bool{}
+
+		android.AddToStringSet(sandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...))
+		android.AddToStringSet(sandboxingDenyPathSet, SandboxingDenyPathList)
+		android.AddToStringSet(depfileAllowSet, DepfileAllowList)
+		return &sandboxingAllowlistSets{
+			sandboxingDenyModuleSet: sandboxingDenyModuleSet,
+			sandboxingDenyPathSet:   sandboxingDenyPathSet,
+			depfileAllowSet:         depfileAllowSet,
+		}
+	}).(*sandboxingAllowlistSets)
+}
 func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
 	if !ctx.DeviceConfig().GenruleSandboxing() {
 		return r.SandboxTools()
 	}
-	if SandboxingDenyModuleSet == nil {
-		SandboxingDenyModuleSetLock.Lock()
-		defer SandboxingDenyModuleSetLock.Unlock()
-		SandboxingDenyModuleSet = map[string]bool{}
-		SandboxingDenyPathSet = map[string]bool{}
-		android.AddToStringSet(SandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...))
-		android.AddToStringSet(SandboxingDenyPathSet, SandboxingDenyPathList)
-	}
-
-	if SandboxingDenyPathSet[ctx.ModuleDir()] || SandboxingDenyModuleSet[ctx.ModuleName()] {
+	sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx)
+	if sandboxingAllowlistSets.sandboxingDenyPathSet[ctx.ModuleDir()] ||
+		sandboxingAllowlistSets.sandboxingDenyModuleSet[ctx.ModuleName()] {
 		return r.SandboxTools()
 	}
 	return r.SandboxInputs()
diff --git a/java/kotlin.go b/java/kotlin.go
index 9bff5ea..f28d6c7 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -30,7 +30,7 @@
 	blueprint.RuleParams{
 		Command: `rm -rf "$classesDir" "$headerClassesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
 			`mkdir -p "$classesDir" "$headerClassesDir" "$srcJarDir" "$emptyDir" && ` +
-			`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
+			`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" -f "*.kt" $srcJars && ` +
 			`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
 			` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
 			` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
diff --git a/rust/builder.go b/rust/builder.go
index 0dfaef4..bf009a5 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -324,6 +324,7 @@
 			envVars = append(envVars, "CARGO_BIN_NAME="+strings.TrimSuffix(outputFile.Base(), outputFile.Ext()))
 		}
 		envVars = append(envVars, "CARGO_CRATE_NAME="+ctx.RustModule().CrateName())
+		envVars = append(envVars, "CARGO_PKG_NAME="+ctx.RustModule().CrateName())
 		pkgVersion := ctx.RustModule().compiler.CargoPkgVersion()
 		if pkgVersion != "" {
 			envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index 7fa9f5c..0aecf61 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -19,6 +19,7 @@
 	"testing"
 
 	"android/soong/android"
+	"android/soong/cc"
 )
 
 func TestRustFuzz(t *testing.T) {
@@ -59,3 +60,68 @@
 		t.Errorf("rust_fuzz dependent library does not contain the expected flags (sancov-module, cfg fuzzing).")
 	}
 }
+
+func TestRustFuzzDepBundling(t *testing.T) {
+	ctx := testRust(t, `
+			cc_library {
+				name: "libcc_transitive_dep",
+			}
+			cc_library {
+				name: "libcc_direct_dep",
+			}
+			rust_library {
+				name: "libtest_fuzzing",
+				crate_name: "test_fuzzing",
+				srcs: ["foo.rs"],
+				shared_libs: ["libcc_transitive_dep"],
+			}
+			rust_fuzz {
+				name: "fuzz_libtest",
+				srcs: ["foo.rs"],
+				rustlibs: ["libtest_fuzzing"],
+				shared_libs: ["libcc_direct_dep"],
+			}
+	`)
+
+	fuzz_libtest := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Module().(*Module)
+
+	if !strings.Contains(fuzz_libtest.FuzzSharedLibraries().String(), ":libcc_direct_dep.so") {
+		t.Errorf("rust_fuzz does not contain the expected bundled direct shared libs ('libcc_direct_dep'): %#v", fuzz_libtest.FuzzSharedLibraries().String())
+	}
+	if !strings.Contains(fuzz_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
+		t.Errorf("rust_fuzz does not contain the expected bundled transitive shared libs ('libcc_transitive_dep'): %#v", fuzz_libtest.FuzzSharedLibraries().String())
+	}
+}
+
+func TestCCFuzzDepBundling(t *testing.T) {
+	ctx := testRust(t, `
+			cc_library {
+				name: "libcc_transitive_dep",
+			}
+			rust_ffi {
+				name: "libtest_fuzzing",
+				crate_name: "test_fuzzing",
+				srcs: ["foo.rs"],
+				shared_libs: ["libcc_transitive_dep"],
+			}
+			cc_fuzz {
+				name: "fuzz_shared_libtest",
+				shared_libs: ["libtest_fuzzing"],
+			}
+			cc_fuzz {
+				name: "fuzz_static_libtest",
+				static_libs: ["libtest_fuzzing"],
+			}
+
+	`)
+
+	fuzz_shared_libtest := ctx.ModuleForTests("fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
+	fuzz_static_libtest := ctx.ModuleForTests("fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
+
+	if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String())
+	}
+	if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String())
+	}
+}
diff --git a/rust/rust.go b/rust/rust.go
index 4324ecb..e524c9f 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -631,6 +631,15 @@
 	return false
 }
 
+func (mod *Module) RustLibraryInterface() bool {
+	if mod.compiler != nil {
+		if _, ok := mod.compiler.(libraryInterface); ok {
+			return true
+		}
+	}
+	return false
+}
+
 func (mod *Module) IsFuzzModule() bool {
 	if _, ok := mod.compiler.(*fuzzDecorator); ok {
 		return true
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 83cf055..0f7cf6e 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -62,8 +62,7 @@
 	"-C llvm-args=-sanitizer-coverage-level=3",
 	"-C llvm-args=-sanitizer-coverage-trace-compares",
 	"-C llvm-args=-sanitizer-coverage-inline-8bit-counters",
-	"-C llvm-args=-sanitizer-coverage-trace-geps",
-	"-C llvm-args=-sanitizer-coverage-prune-blocks=0",
+	"-C llvm-args=-sanitizer-coverage-pc-table",
 
 	// See https://github.com/rust-fuzz/cargo-fuzz/pull/193
 	"-C link-dead-code",