Merge "Add option test_min_api_level and test_min_sdk_version for auto-generated test config"
diff --git a/Android.bp b/Android.bp
index 25038c6..89a1711 100644
--- a/Android.bp
+++ b/Android.bp
@@ -334,6 +334,7 @@
     srcs: [
         "rust/config/global.go",
         "rust/config/toolchain.go",
+        "rust/config/whitelist.go",
         "rust/config/x86_linux_host.go",
         "rust/config/x86_64_device.go",
     ],
diff --git a/OWNERS b/OWNERS
index 4ae045d..9f0fcf2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,4 @@
 per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
 per-file tidy.go = srhines@google.com, chh@google.com
 per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+per-file rust/config/whitelist.go = ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/cc/androidmk.go b/cc/androidmk.go
index c9d4dad..aab4edd 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -303,6 +303,33 @@
 	androidMkWriteTestData(test.data, ctx, ret)
 }
 
+func (fuzz *fuzzBinary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	ctx.subAndroidMk(ret, fuzz.binaryDecorator)
+
+	var fuzzFiles []string
+	for _, d := range fuzz.corpus {
+		rel := d.Rel()
+		path := d.String()
+		path = strings.TrimSuffix(path, rel)
+		fuzzFiles = append(fuzzFiles, path+":corpus/"+d.Base())
+	}
+
+	if fuzz.dictionary != nil {
+		path := strings.TrimSuffix(fuzz.dictionary.String(), fuzz.dictionary.Rel())
+		fuzzFiles = append(fuzzFiles, path+":"+fuzz.dictionary.Base())
+	}
+
+	if len(fuzzFiles) > 0 {
+		ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+			fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(fuzzFiles, " "))
+		})
+	}
+
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+		fmt.Fprintln(w, "LOCAL_IS_FUZZ_TARGET := true")
+	})
+}
+
 func (test *testLibrary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ctx.subAndroidMk(ret, test.libraryDecorator)
 }
diff --git a/cc/cc.go b/cc/cc.go
index cda37e8..b255a14 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2204,6 +2204,7 @@
 		&BinaryLinkerProperties{},
 		&TestProperties{},
 		&TestBinaryProperties{},
+		&FuzzProperties{},
 		&StlProperties{},
 		&SanitizeProperties{},
 		&StripProperties{},
diff --git a/cc/fuzz.go b/cc/fuzz.go
index b0fb262..325be63 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -23,6 +23,14 @@
 	"android/soong/cc/config"
 )
 
+type FuzzProperties struct {
+	// Optional list of seed files to be installed to the fuzz target's output
+	// directory.
+	Corpus []string `android:"path"`
+	// Optional dictionary to be installed to the fuzz target's output directory.
+	Dictionary *string `android:"path"`
+}
+
 func init() {
 	android.RegisterModuleType("cc_fuzz", FuzzFactory)
 }
@@ -42,10 +50,15 @@
 type fuzzBinary struct {
 	*binaryDecorator
 	*baseCompiler
+
+	Properties FuzzProperties
+	corpus     android.Paths
+	dictionary android.Path
 }
 
 func (fuzz *fuzzBinary) linkerProps() []interface{} {
 	props := fuzz.binaryDecorator.linkerProps()
+	props = append(props, &fuzz.Properties)
 	return props
 }
 
@@ -81,9 +94,21 @@
 }
 
 func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
-	fuzz.binaryDecorator.baseInstaller.dir = filepath.Join("fuzz", ctx.Target().Arch.ArchType.String())
-	fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join("fuzz", ctx.Target().Arch.ArchType.String())
+	fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
+		"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+	fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
+		"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
 	fuzz.binaryDecorator.baseInstaller.install(ctx, file)
+
+	fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
+	if fuzz.Properties.Dictionary != nil {
+		fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
+		if fuzz.dictionary.Ext() != ".dict" {
+			ctx.PropertyErrorf("dictionary",
+				"Fuzzer dictionary %q does not have '.dict' extension",
+				fuzz.dictionary.String())
+		}
+	}
 }
 
 func NewFuzz(hod android.HostOrDeviceSupported) *Module {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 5deac5e..1d5331e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -57,6 +57,10 @@
 	// filegroup or genrule can be included within this property.
 	Exclude_srcs []string `android:"path,arch_variant"`
 
+	// list of package names that should actually be used. If this property is left unspecified,
+	// all the sources from the srcs property is used.
+	Filter_packages []string
+
 	// list of java libraries that will be in the classpath.
 	Libs []string `android:"arch_variant"`
 
@@ -524,6 +528,34 @@
 	// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
 	// may contain filegroup or genrule.
 	srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+
+	filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path {
+		if filterPackages == nil {
+			return srcs
+		}
+		filtered := []android.Path{}
+		for _, src := range srcs {
+			if src.Ext() != ".java" {
+				// Don't filter-out non-Java (=generated sources) by package names. This is not ideal,
+				// but otherwise metalava emits stub sources having references to the generated AIDL classes
+				// in filtered-out pacages (e.g. com.android.internal.*).
+				// TODO(b/141149570) We need to fix this by introducing default private constructors or
+				// fixing metalava to not emit constructors having references to unknown classes.
+				filtered = append(filtered, src)
+				continue
+			}
+			packageName := strings.ReplaceAll(filepath.Dir(src.Rel()), "/", ".")
+			for _, pkg := range filterPackages {
+				if strings.HasPrefix(packageName, pkg) {
+					filtered = append(filtered, src)
+					break
+				}
+			}
+		}
+		return filtered
+	}
+	srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)
+
 	flags := j.collectAidlFlags(ctx, deps)
 	srcFiles = j.genSources(ctx, srcFiles, flags)
 
diff --git a/rust/config/whitelist.go b/rust/config/whitelist.go
new file mode 100644
index 0000000..4646264
--- /dev/null
+++ b/rust/config/whitelist.go
@@ -0,0 +1,21 @@
+package config
+
+var (
+	RustAllowedPaths = []string{
+		"external/rust/crates",
+		"external/crosvm",
+		"external/adhd",
+	}
+
+	RustModuleTypes = []string{
+		"rust_binary",
+		"rust_binary_host",
+		"rust_library",
+		"rust_library_dylib",
+		"rust_library_rlib",
+		"rust_library_host",
+		"rust_library_host_dylib",
+		"rust_library_host_rlib",
+		"rust_proc_macro",
+	}
+)
diff --git a/rust/rust.go b/rust/rust.go
index 7cc0b2c..2120916 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -29,28 +29,11 @@
 
 func init() {
 	// Only allow rust modules to be defined for certain projects
-	rustModuleTypes := []string{
-		"rust_binary",
-		"rust_binary_host",
-		"rust_library",
-		"rust_library_dylib",
-		"rust_library_rlib",
-		"rust_library_host",
-		"rust_library_host_dylib",
-		"rust_library_host_rlib",
-		"rust_proc_macro",
-	}
-
-	rustAllowedPaths := []string{
-		"external/rust/crates",
-		"external/crosvm",
-		"external/adhd",
-	}
 
 	android.AddNeverAllowRules(
 		android.NeverAllow().
-			NotIn(rustAllowedPaths...).
-			ModuleType(rustModuleTypes...))
+			NotIn(config.RustAllowedPaths...).
+			ModuleType(config.RustModuleTypes...))
 
 	android.RegisterModuleType("rust_defaults", defaultsFactory)
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {