Merge "Skip cloning modules in bp2build"
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/android/filegroup.go b/android/filegroup.go
index 3522f80..c042ff1 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -82,6 +82,7 @@
 type bazelAidlLibraryAttributes struct {
 	Srcs                bazel.LabelListAttribute
 	Strip_import_prefix *string
+	Deps                bazel.LabelListAttribute
 }
 
 // api srcs can be contained in filegroups.
@@ -120,9 +121,12 @@
 	// and then convert
 	if fg.ShouldConvertToAidlLibrary(ctx) {
 		tags := []string{"apex_available=//apex_available:anyapex"}
+		deps := bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, fg.properties.Aidl.Deps))
+
 		attrs := &bazelAidlLibraryAttributes{
 			Srcs:                srcs,
 			Strip_import_prefix: fg.properties.Path,
+			Deps:                deps,
 		}
 
 		props := bazel.BazelTargetModuleProperties{
@@ -199,6 +203,14 @@
 	// Create a make variable with the specified name that contains the list of files in the
 	// filegroup, relative to the root of the source tree.
 	Export_to_make_var *string
+
+	// aidl is explicitly provided for implicit aidl dependencies
+	// TODO(b/278298615): aidl prop is a no-op in Soong and is an escape hatch
+	// to include implicit aidl dependencies for bazel migration compatibility
+	Aidl struct {
+		// List of aidl files or filegroup depended on by srcs
+		Deps []string `android:"path"`
+	}
 }
 
 type fileGroup struct {
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index 7ce559d..273d556 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -105,6 +105,42 @@
 	}
 }
 
+func TestFilegroupWithAidlDeps(t *testing.T) {
+	bp := `
+	filegroup {
+		name: "bar",
+		srcs: ["bar.aidl"],
+	}
+	filegroup {
+		name: "foo",
+		srcs: ["aidl/foo.aidl"],
+		path: "aidl",
+		aidl: {
+			deps: [":bar"],
+		}
+	}`
+
+	t.Run("filegroup with aidl deps", func(t *testing.T) {
+		expectedBazelTargets := []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "bar", AttrNameToString{
+				"srcs": `["bar.aidl"]`,
+				"tags": `["apex_available=//apex_available:anyapex"]`,
+			}),
+			MakeBazelTargetNoRestrictions("aidl_library", "foo", AttrNameToString{
+				"srcs":                `["aidl/foo.aidl"]`,
+				"strip_import_prefix": `"aidl"`,
+				"deps":                `[":bar"]`,
+				"tags":                `["apex_available=//apex_available:anyapex"]`,
+			}),
+		}
+		runFilegroupTestCase(t, Bp2buildTestCase{
+			Description:          "filegroup with aidl deps",
+			Blueprint:            bp,
+			ExpectedBazelTargets: expectedBazelTargets,
+		})
+	})
+}
+
 func TestFilegroupWithAidlAndNonAidlSrcs(t *testing.T) {
 	runFilegroupTestCase(t, Bp2buildTestCase{
 		Description: "filegroup with aidl and non-aidl srcs",
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 f2c8525..a7d6ff5 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/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/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",