Adding support for building AFLpp
Test: Build AFL fuzzers locally and ran them

Change-Id: Ie07ec336892649192a844a4d0d231196673e34a0
diff --git a/cc/cc.go b/cc/cc.go
index f04b6f0..bc95813 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -61,6 +61,9 @@
 		ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator).Parallel()
 		ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel()
 
+		ctx.TopDown("fuzz_deps", fuzzMutatorDeps)
+		ctx.BottomUp("fuzz", fuzzMutator)
+
 		ctx.BottomUp("coverage", coverageMutator).Parallel()
 
 		ctx.TopDown("afdo_deps", afdoDepsMutator)
@@ -838,6 +841,7 @@
 	stl      *stl
 	sanitize *sanitize
 	coverage *coverage
+	fuzzer   *fuzzer
 	sabi     *sabi
 	vndkdep  *vndkdep
 	lto      *lto
@@ -1163,6 +1167,9 @@
 	if c.coverage != nil {
 		c.AddProperties(c.coverage.props()...)
 	}
+	if c.fuzzer != nil {
+		c.AddProperties(c.fuzzer.props()...)
+	}
 	if c.sabi != nil {
 		c.AddProperties(c.sabi.props()...)
 	}
@@ -1680,6 +1687,7 @@
 	module.stl = &stl{}
 	module.sanitize = &sanitize{}
 	module.coverage = &coverage{}
+	module.fuzzer = &fuzzer{}
 	module.sabi = &sabi{}
 	module.vndkdep = &vndkdep{}
 	module.lto = &lto{}
@@ -1901,6 +1909,9 @@
 	if c.coverage != nil {
 		flags, deps = c.coverage.flags(ctx, flags, deps)
 	}
+	if c.fuzzer != nil {
+		flags = c.fuzzer.flags(ctx, flags)
+	}
 	if c.lto != nil {
 		flags = c.lto.flags(ctx, flags)
 	}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index b6d196c..24732bf 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3342,6 +3342,125 @@
 	`)
 }
 
+func TestAFLFuzzTarget(t *testing.T) {
+	ctx := testCc(t, `
+		cc_afl_fuzz {
+			name: "test_afl_fuzz_target",
+			srcs: ["foo.c"],
+			host_supported: true,
+			static_libs: [
+				"afl_fuzz_static_lib",
+			],
+			shared_libs: [
+				"afl_fuzz_shared_lib",
+			],
+		}
+		cc_fuzz {
+			name: "test_fuzz_target",
+			srcs: ["foo.c"],
+			static_libs: [
+				"afl_fuzz_static_lib",
+				"libfuzzer_only_static_lib",
+			],
+			shared_libs: [
+				"afl_fuzz_shared_lib",
+			],
+		}
+		cc_library {
+			name: "afl_fuzz_static_lib",
+			host_supported: true,
+			srcs: ["static_file.c"],
+		}
+		cc_library {
+			name: "libfuzzer_only_static_lib",
+			host_supported: true,
+			srcs: ["static_file.c"],
+		}
+		cc_library {
+			name: "afl_fuzz_shared_lib",
+			host_supported: true,
+			srcs: ["shared_file.c"],
+			static_libs: [
+				"second_static_lib",
+			],
+		}
+		cc_library_headers {
+			name: "libafl_headers",
+			vendor_available: true,
+			host_supported: true,
+			export_include_dirs: [
+				"include",
+				"instrumentation",
+			],
+		}
+		cc_object {
+			name: "afl-compiler-rt",
+			vendor_available: true,
+			host_supported: true,
+			cflags: [
+				"-fPIC",
+			],
+			srcs: [
+				"instrumentation/afl-compiler-rt.o.c",
+			],
+		}
+		cc_library {
+			name: "second_static_lib",
+			host_supported: true,
+			srcs: ["second_file.c"],
+		}
+		filegroup {
+			name: "aflpp_driver",
+			srcs: [
+				"aflpp_driver.c",
+			],
+		}`)
+
+	checkPcGuardFlag := func(
+		modName string, variantName string, shouldHave bool) {
+		cc := ctx.ModuleForTests(modName, variantName).Rule("cc")
+
+		cFlags, ok := cc.Args["cFlags"]
+		if !ok {
+			t.Errorf("Could not find cFlags for module %s and variant %s",
+				modName, variantName)
+		}
+
+		if strings.Contains(
+			cFlags, "-fsanitize-coverage=trace-pc-guard") != shouldHave {
+			t.Errorf("Flag was found: %t. Expected to find flag:  %t. "+
+				"Test failed for module %s and variant %s",
+				!shouldHave, shouldHave, modName, variantName)
+		}
+	}
+
+	for _, vnt := range ctx.ModuleVariantsForTests("libfuzzer_only_static_lib") {
+		if strings.Contains(vnt, "fuzzer_afl") {
+			t.Errorf("libfuzzer_only_static_lib has afl variant and should not")
+		}
+	}
+
+	moduleName := "test_afl_fuzz_target"
+	variantName := "android_arm64_armv8-a_fuzzer_afl"
+	checkPcGuardFlag(moduleName, variantName, true)
+
+	moduleName = "afl_fuzz_static_lib"
+	variantName = "android_arm64_armv8-a_static"
+	checkPcGuardFlag(moduleName, variantName, false)
+	checkPcGuardFlag(moduleName, variantName+"_fuzzer", false)
+	checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true)
+
+	moduleName = "second_static_lib"
+	checkPcGuardFlag(moduleName, variantName, false)
+	checkPcGuardFlag(moduleName, variantName+"_fuzzer", false)
+	checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true)
+
+	ctx.ModuleForTests("afl_fuzz_shared_lib",
+		"android_arm64_armv8-a_shared").Rule("cc")
+	ctx.ModuleForTests("afl_fuzz_shared_lib",
+		"android_arm64_armv8-a_shared_fuzzer_afl").Rule("cc")
+}
+
 // Simple smoke test for the cc_fuzz target that ensures the rule compiles
 // correctly.
 func TestFuzzTarget(t *testing.T) {
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 23d81d6..5bb832a 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -27,29 +27,117 @@
 )
 
 func init() {
-	android.RegisterModuleType("cc_fuzz", FuzzFactory)
+	android.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory)
+	android.RegisterModuleType("cc_fuzz", LibFuzzFactory)
 	android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
+	android.RegisterSingletonType("cc_afl_fuzz_packaging", fuzzAFLPackagingFactory)
+}
+
+var (
+	neededAFLTools = map[string]bool{"afl-fuzz": true, "afl-showmap": true}
+)
+
+type FuzzProperties struct {
+	AFLEnabled  bool `blueprint:"mutated"`
+	AFLAddFlags bool `blueprint:"mutated"`
+}
+
+type fuzzer struct {
+	Properties FuzzProperties
+}
+
+func (fuzzer *fuzzer) flags(ctx ModuleContext, flags Flags) Flags {
+	if fuzzer.Properties.AFLAddFlags {
+		flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-coverage=trace-pc-guard")
+	}
+
+	return flags
+}
+
+func (fuzzer *fuzzer) props() []interface{} {
+	return []interface{}{&fuzzer.Properties}
+}
+
+func fuzzMutatorDeps(mctx android.TopDownMutatorContext) {
+	currentModule, ok := mctx.Module().(*Module)
+	if !ok {
+		return
+	}
+
+	if currentModule.fuzzer == nil || !currentModule.fuzzer.Properties.AFLEnabled {
+		return
+	}
+
+	mctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+		c, ok := child.(*Module)
+		if !ok {
+			return false
+		}
+
+		if c.sanitize == nil {
+			return false
+		}
+
+		isFuzzerPointer := c.sanitize.getSanitizerBoolPtr(Fuzzer)
+		if isFuzzerPointer == nil || !*isFuzzerPointer {
+			return false
+		}
+
+		if c.fuzzer == nil {
+			return false
+		}
+
+		c.fuzzer.Properties.AFLEnabled = true
+		c.fuzzer.Properties.AFLAddFlags = true
+		return true
+	})
+}
+
+func fuzzMutator(mctx android.BottomUpMutatorContext) {
+	if c, ok := mctx.Module().(*Module); ok && c.fuzzer != nil {
+		if !c.fuzzer.Properties.AFLEnabled {
+			return
+		}
+
+		if c.Binary() {
+			m := mctx.CreateVariations("afl")
+			m[0].(*Module).fuzzer.Properties.AFLEnabled = true
+			m[0].(*Module).fuzzer.Properties.AFLAddFlags = true
+		} else {
+			m := mctx.CreateVariations("", "afl")
+			m[0].(*Module).fuzzer.Properties.AFLEnabled = false
+			m[0].(*Module).fuzzer.Properties.AFLAddFlags = false
+
+			m[1].(*Module).fuzzer.Properties.AFLEnabled = true
+			m[1].(*Module).fuzzer.Properties.AFLAddFlags = true
+		}
+	}
 }
 
 // cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
 // $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on
 // your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
-func FuzzFactory() android.Module {
-	module := NewFuzz(android.HostAndDeviceSupported)
+func LibFuzzFactory() android.Module {
+	module := NewFuzzer(android.HostAndDeviceSupported, fuzz.Cc)
 	return module.Init()
 }
 
-func NewFuzzInstaller() *baseInstaller {
-	return NewBaseInstaller("fuzz", "fuzz", InstallInData)
+// cc_afl_fuzz creates a host/device AFL++ fuzzer binary.
+// AFL++ is an open source framework used to fuzz libraries
+// Host binaries can be found at $ANDROID_HOST_OUT/afl_fuzz/ and device
+// binaries can be found at $ANDROID_PRODUCT_OUT/data/afl_fuzz in your
+// build tree
+func AFLFuzzFactory() android.Module {
+	module := NewFuzzer(android.HostAndDeviceSupported, fuzz.AFL)
+	return module.Init()
 }
 
 type fuzzBinary struct {
 	*binaryDecorator
 	*baseCompiler
-
-	fuzzPackagedModule fuzz.FuzzPackagedModule
-
+	fuzzPackagedModule  fuzz.FuzzPackagedModule
 	installedSharedDeps []string
+	fuzzType            fuzz.FuzzType
 }
 
 func (fuzz *fuzzBinary) fuzzBinary() bool {
@@ -66,11 +154,17 @@
 	fuzz.binaryDecorator.linkerInit(ctx)
 }
 
-func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	deps.StaticLibs = append(deps.StaticLibs,
-		config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
-	deps = fuzz.binaryDecorator.linkerDeps(ctx, deps)
-	return deps
+func (fuzzBin *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
+	if fuzzBin.fuzzType == fuzz.AFL {
+		deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers")
+		deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps)
+		return deps
+
+	} else {
+		deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
+		deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps)
+		return deps
+	}
 }
 
 func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -80,6 +174,7 @@
 	// target packages.
 	flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
 	flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+
 	return flags
 }
 
@@ -149,63 +244,68 @@
 }
 
 func sharedLibraryInstallLocation(
-	libraryPath android.Path, isHost bool, archString string) string {
+	libraryPath android.Path, isHost bool, fuzzDir string, archString string) string {
 	installLocation := "$(PRODUCT_OUT)/data"
 	if isHost {
 		installLocation = "$(HOST_OUT)"
 	}
 	installLocation = filepath.Join(
-		installLocation, "fuzz", archString, "lib", libraryPath.Base())
+		installLocation, fuzzDir, archString, "lib", libraryPath.Base())
 	return installLocation
 }
 
 // Get the device-only shared library symbols install directory.
-func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, archString string) string {
-	return filepath.Join("$(PRODUCT_OUT)/symbols/data/fuzz/", archString, "/lib/", libraryPath.Base())
+func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir string, archString string) string {
+	return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, "/lib/", libraryPath.Base())
 }
 
-func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
-	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)
+func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
+	installBase := "fuzz"
+	if fuzzBin.fuzzType == fuzz.AFL {
+		installBase = "afl_fuzz"
+	}
 
-	fuzz.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Corpus)
+	fuzzBin.binaryDecorator.baseInstaller.dir = filepath.Join(
+		installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+	fuzzBin.binaryDecorator.baseInstaller.dir64 = filepath.Join(
+		installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+	fuzzBin.binaryDecorator.baseInstaller.install(ctx, file)
+
+	fuzzBin.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Corpus)
 	builder := android.NewRuleBuilder(pctx, ctx)
 	intermediateDir := android.PathForModuleOut(ctx, "corpus")
-	for _, entry := range fuzz.fuzzPackagedModule.Corpus {
+	for _, entry := range fuzzBin.fuzzPackagedModule.Corpus {
 		builder.Command().Text("cp").
 			Input(entry).
 			Output(intermediateDir.Join(ctx, entry.Base()))
 	}
 	builder.Build("copy_corpus", "copy corpus")
-	fuzz.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
+	fuzzBin.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
 
-	fuzz.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Data)
+	fuzzBin.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Data)
 	builder = android.NewRuleBuilder(pctx, ctx)
 	intermediateDir = android.PathForModuleOut(ctx, "data")
-	for _, entry := range fuzz.fuzzPackagedModule.Data {
+	for _, entry := range fuzzBin.fuzzPackagedModule.Data {
 		builder.Command().Text("cp").
 			Input(entry).
 			Output(intermediateDir.Join(ctx, entry.Rel()))
 	}
 	builder.Build("copy_data", "copy data")
-	fuzz.fuzzPackagedModule.DataIntermediateDir = intermediateDir
+	fuzzBin.fuzzPackagedModule.DataIntermediateDir = intermediateDir
 
-	if fuzz.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
-		fuzz.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzz.fuzzPackagedModule.FuzzProperties.Dictionary)
-		if fuzz.fuzzPackagedModule.Dictionary.Ext() != ".dict" {
+	if fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
+		fuzzBin.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary)
+		if fuzzBin.fuzzPackagedModule.Dictionary.Ext() != ".dict" {
 			ctx.PropertyErrorf("dictionary",
 				"Fuzzer dictionary %q does not have '.dict' extension",
-				fuzz.fuzzPackagedModule.Dictionary.String())
+				fuzzBin.fuzzPackagedModule.Dictionary.String())
 		}
 	}
 
-	if fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
+	if fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
 		configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
-		android.WriteFileRule(ctx, configPath, fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
-		fuzz.fuzzPackagedModule.Config = configPath
+		android.WriteFileRule(ctx, configPath, fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
+		fuzzBin.fuzzPackagedModule.Config = configPath
 	}
 
 	// Grab the list of required shared libraries.
@@ -225,31 +325,36 @@
 	})
 
 	for _, lib := range sharedLibraries {
-		fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+		fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
 			sharedLibraryInstallLocation(
-				lib, ctx.Host(), ctx.Arch().ArchType.String()))
+				lib, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
 
 		// Also add the dependency on the shared library symbols dir.
 		if !ctx.Host() {
-			fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
-				sharedLibrarySymbolsInstallLocation(lib, ctx.Arch().ArchType.String()))
+			fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
+				sharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
 		}
 	}
 }
 
-func NewFuzz(hod android.HostOrDeviceSupported) *Module {
+func NewFuzzer(hod android.HostOrDeviceSupported, fuzzType fuzz.FuzzType) *Module {
 	module, binary := newBinary(hod, false)
+	baseInstallerPath := "fuzz"
+	if fuzzType == fuzz.AFL {
+		baseInstallerPath = "afl_fuzz"
+	}
 
-	binary.baseInstaller = NewFuzzInstaller()
+	binary.baseInstaller = NewBaseInstaller(baseInstallerPath, baseInstallerPath, InstallInData)
 	module.sanitize.SetSanitizer(Fuzzer, true)
 
-	fuzz := &fuzzBinary{
+	fuzzBin := &fuzzBinary{
 		binaryDecorator: binary,
 		baseCompiler:    NewBaseCompiler(),
+		fuzzType:        fuzzType,
 	}
-	module.compiler = fuzz
-	module.linker = fuzz
-	module.installer = fuzz
+	module.compiler = fuzzBin
+	module.linker = fuzzBin
+	module.installer = fuzzBin
 
 	// The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
 	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
@@ -268,6 +373,17 @@
 		ctx.AppendProperties(&disableDarwinAndLinuxBionic)
 	})
 
+	if fuzzType == fuzz.AFL {
+		// Add cc_objects to Srcs
+		fuzzBin.baseCompiler.Properties.Srcs = append(fuzzBin.baseCompiler.Properties.Srcs, ":aflpp_driver", ":afl-compiler-rt")
+		module.fuzzer.Properties.AFLEnabled = true
+		module.compiler.appendCflags([]string{
+			"-Wno-unused-result",
+			"-Wno-unused-parameter",
+			"-Wno-unused-function",
+		})
+	}
+
 	return module
 }
 
@@ -275,10 +391,30 @@
 // their architecture & target/host specific zip file.
 type ccFuzzPackager struct {
 	fuzz.FuzzPackager
+	fuzzPackagingArchModules         string
+	fuzzTargetSharedDepsInstallPairs string
+	allFuzzTargetsName               string
 }
 
 func fuzzPackagingFactory() android.Singleton {
-	return &ccFuzzPackager{}
+
+	fuzzPackager := &ccFuzzPackager{
+		fuzzPackagingArchModules:         "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
+		fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+		allFuzzTargetsName:               "ALL_FUZZ_TARGETS",
+	}
+	fuzzPackager.FuzzType = fuzz.Cc
+	return fuzzPackager
+}
+
+func fuzzAFLPackagingFactory() android.Singleton {
+	fuzzPackager := &ccFuzzPackager{
+		fuzzPackagingArchModules:         "SOONG_AFL_FUZZ_PACKAGING_ARCH_MODULES",
+		fuzzTargetSharedDepsInstallPairs: "AFL_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+		allFuzzTargetsName:               "ALL_AFL_FUZZ_TARGETS",
+	}
+	fuzzPackager.FuzzType = fuzz.AFL
+	return fuzzPackager
 }
 
 func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
@@ -306,9 +442,15 @@
 			return
 		}
 
+		sharedLibsInstallDirPrefix := "lib"
 		fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
-		if !ok {
-			return
+		if !ok || fuzzModule.fuzzType != s.FuzzType {
+			// check is module is a tool needed to be zipped for AFL
+			if _, aflTool := neededAFLTools[ccModule.Name()]; aflTool && s.FuzzType == fuzz.AFL {
+				sharedLibsInstallDirPrefix = "lib64"
+			} else {
+				return
+			}
 		}
 
 		hostOrTargetString := "target"
@@ -316,8 +458,18 @@
 			hostOrTargetString = "host"
 		}
 
+		fpm := fuzz.FuzzPackagedModule{}
+		if ok {
+			fpm = fuzzModule.fuzzPackagedModule
+		}
+
+		intermediatePath := "fuzz"
+		if s.FuzzType == fuzz.AFL {
+			intermediatePath = "afl_fuzz"
+		}
+
 		archString := ccModule.Arch().ArchType.String()
-		archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+		archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString)
 		archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
 
 		// Grab the list of required shared libraries.
@@ -327,22 +479,21 @@
 		builder := android.NewRuleBuilder(pctx, ctx)
 
 		// Package the corpus, data, dict and config into a zipfile.
-		files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder)
+		files = s.PackageArtifacts(ctx, module, fpm, archDir, builder)
 
 		// Package shared libraries
-		files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...)
+		files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
 
 		// The executable.
 		files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""})
 
-		archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
+		archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
 		if !ok {
 			return
 		}
 	})
 
-	s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx)
-
+	s.CreateFuzzPackage(ctx, archDirs, s.FuzzType, pctx)
 }
 
 func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
@@ -353,27 +504,38 @@
 	// ready to handle phony targets created in Soong. In the meantime, this
 	// exports the phony 'fuzz' target and dependencies on packages to
 	// core/main.mk so that we can use dist-for-goals.
-	ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
-	ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+	if s.FuzzType == fuzz.AFL {
+		s.FuzzTargets["afl-fuzz"] = true
+		s.FuzzTargets["afl-showmap"] = true
+	}
+
+	ctx.Strict(s.fuzzPackagingArchModules, strings.Join(packages, " "))
+
+	ctx.Strict(s.fuzzTargetSharedDepsInstallPairs,
 		strings.Join(s.FuzzPackager.SharedLibInstallStrings, " "))
 
 	// Preallocate the slice of fuzz targets to minimise memory allocations.
-	s.PreallocateSlice(ctx, "ALL_FUZZ_TARGETS")
+	s.PreallocateSlice(ctx, s.allFuzzTargetsName)
 }
 
 // GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for
 // packaging.
-func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
+func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
 	var files []fuzz.FileToZip
 
+	fuzzDir := "fuzz"
+	if s.FuzzType == fuzz.AFL {
+		fuzzDir = "afl_fuzz"
+	}
+
 	for _, library := range sharedLibraries {
-		files = append(files, fuzz.FileToZip{library, "lib"})
+		files = append(files, fuzz.FileToZip{library, destinationPathPrefix})
 
 		// For each architecture-specific shared library dependency, we need to
 		// install it to the output directory. Setup the install destination here,
 		// which will be used by $(copy-many-files) in the Make backend.
 		installDestination := sharedLibraryInstallLocation(
-			library, module.Host(), archString)
+			library, module.Host(), fuzzDir, archString)
 		if (*sharedLibraryInstalled)[installDestination] {
 			continue
 		}
@@ -391,7 +553,7 @@
 		// we want symbolization tools (like `stack`) to be able to find the symbols
 		// in $ANDROID_PRODUCT_OUT/symbols automagically.
 		if !module.Host() {
-			symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString)
+			symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, fuzzDir, archString)
 			symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
 			s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
 				library.String()+":"+symbolsInstallDestination)
diff --git a/cc/testing.go b/cc/testing.go
index 077fcda..6b858d5 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -534,7 +534,8 @@
 	android.PrepareForTestWithAndroidBuildComponents,
 	android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
 	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
-		ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
+		ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
+		ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory)
 		ctx.RegisterModuleType("cc_test", TestFactory)
 		ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
 		ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
@@ -648,7 +649,8 @@
 func CreateTestContext(config android.Config) *android.TestContext {
 	ctx := android.NewTestArchContext(config)
 	genrule.RegisterGenruleBuildComponents(ctx)
-	ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
+	ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
+	ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory)
 	ctx.RegisterModuleType("cc_test", TestFactory)
 	ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 700cdf0..66d5aba 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -26,12 +26,13 @@
 	"android/soong/android"
 )
 
-type Lang string
+type FuzzType string
 
 const (
-	Cc   Lang = ""
-	Rust Lang = "rust"
-	Java Lang = "java"
+	Cc   FuzzType = ""
+	Rust FuzzType = "rust"
+	Java FuzzType = "java"
+	AFL  FuzzType = "AFL"
 )
 
 var BoolDefault = proptools.BoolDefault
@@ -46,6 +47,7 @@
 	Packages                android.Paths
 	FuzzTargets             map[string]bool
 	SharedLibInstallStrings []string
+	FuzzType                FuzzType
 }
 
 type FileToZip struct {
@@ -208,7 +210,7 @@
 	return string(b)
 }
 
-func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, lang Lang, pctx android.PackageContext) {
+func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType FuzzType, pctx android.PackageContext) {
 	var archOsList []ArchOs
 	for archOs := range archDirs {
 		archOsList = append(archOsList, archOs)
@@ -221,12 +223,15 @@
 		hostOrTarget := archOs.HostOrTarget
 		builder := android.NewRuleBuilder(pctx, ctx)
 		zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
-		if lang == Rust {
+		if fuzzType == Rust {
 			zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
 		}
-		if lang == Java {
+		if fuzzType == Java {
 			zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip"
 		}
+		if fuzzType == AFL {
+			zipFileName = "fuzz-afl-" + hostOrTarget + "-" + arch + ".zip"
+		}
 		outputFile := android.PathForOutput(ctx, zipFileName)
 
 		s.Packages = append(s.Packages, outputFile)
@@ -237,7 +242,6 @@
 			Flag("-L 0") // No need to try and re-compress the zipfiles.
 
 		for _, fileToZip := range filesToZip {
-
 			if fileToZip.DestinationPathPrefix != "" {
 				command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
 			} else {
@@ -256,6 +260,7 @@
 	for target, _ := range s.FuzzTargets {
 		fuzzTargets = append(fuzzTargets, target)
 	}
+
 	sort.Strings(fuzzTargets)
 	ctx.Strict(targets, strings.Join(fuzzTargets, " "))
 }
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 55921ba..586095c 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -153,7 +153,7 @@
 		sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, cc.UnstrippedOutputFile, cc.IsValidSharedDependency)
 
 		// Package shared libraries
-		files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...)
+		files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, "lib", &sharedLibraryInstalled)...)
 
 		archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
 		if !ok {