Merge "genrule: add $(location) for inputs and outputs"
diff --git a/Android.bp b/Android.bp
index aeabb13..eefa149 100644
--- a/Android.bp
+++ b/Android.bp
@@ -219,6 +219,7 @@
         "blueprint-pathtools",
         "soong",
         "soong-android",
+        "soong-cc",
         "soong-genrule",
         "soong-java-config",
         "soong-tradefed",
diff --git a/android/arch.go b/android/arch.go
index 95f8803..6516558 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -288,6 +288,30 @@
 	return target.Os.String() + "_" + target.Arch.String()
 }
 
+// archMutator splits a module into a variant for each Target requested by the module.  Target selection
+// for a module is in three levels, OsClass, mulitlib, and then Target.
+// OsClass selection is determined by:
+//    - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
+//      whether the module type can compile for host, device or both.
+//    - The host_supported and device_supported properties on the module.
+// If host is supported for the module, the Host and HostCross OsClasses are  are selected.  If device is supported
+// for the module, the Device OsClass is selected.
+// Within each selected OsClass, the multilib selection is determined by:
+//    - The compile_multilib property if it set (which may be overriden by target.android.compile_multlib or
+//      target.host.compile_multilib).
+//    - The default multilib passed to InitAndroidArchModule if compile_multilib was not set.
+// Valid multilib values include:
+//    "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm).
+//    "first": compile for only a single preferred Target supported by the OsClass.  This is generally x86_64 or arm64,
+//        but may be arm for a 32-bit only build or a build with TARGET_PREFER_32_BIT=true set.
+//    "32": compile for only a single 32-bit Target supported by the OsClass.
+//    "64": compile for only a single 64-bit Target supported by the OsClass.
+//    "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java).
+//
+// Once the list of Targets is determined, the module is split into a variant for each Target.
+//
+// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
+// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
 func archMutator(mctx BottomUpMutatorContext) {
 	var module Module
 	var ok bool
@@ -304,6 +328,7 @@
 	osClasses := base.OsClassSupported()
 
 	var moduleTargets []Target
+	moduleMultiTargets := make(map[int][]Target)
 	primaryModules := make(map[int]bool)
 
 	for _, class := range osClasses {
@@ -311,36 +336,34 @@
 		if len(classTargets) == 0 {
 			continue
 		}
+
 		// only the primary arch in the recovery partition
 		if module.InstallInRecovery() {
 			classTargets = []Target{mctx.Config().Targets[Device][0]}
 		}
 
-		var multilib string
-		switch class {
-		case Device:
-			multilib = String(base.commonProperties.Target.Android.Compile_multilib)
-		case Host, HostCross:
-			multilib = String(base.commonProperties.Target.Host.Compile_multilib)
-		}
-		if multilib == "" {
-			multilib = String(base.commonProperties.Compile_multilib)
-		}
-		if multilib == "" {
-			multilib = base.commonProperties.Default_multilib
-		}
-
 		prefer32 := false
 		if base.prefer32 != nil {
 			prefer32 = base.prefer32(mctx, base, class)
 		}
 
-		targets, err := decodeMultilib(multilib, classTargets, prefer32)
+		multilib, extraMultilib := decodeMultilib(base, class)
+		targets, err := decodeMultilibTargets(multilib, classTargets, prefer32)
 		if err != nil {
 			mctx.ModuleErrorf("%s", err.Error())
 		}
+
+		var multiTargets []Target
+		if extraMultilib != "" {
+			multiTargets, err = decodeMultilibTargets(extraMultilib, classTargets, prefer32)
+			if err != nil {
+				mctx.ModuleErrorf("%s", err.Error())
+			}
+		}
+
 		if len(targets) > 0 {
 			primaryModules[len(moduleTargets)] = true
+			moduleMultiTargets[len(moduleTargets)] = multiTargets
 			moduleTargets = append(moduleTargets, targets...)
 		}
 	}
@@ -358,11 +381,37 @@
 
 	modules := mctx.CreateVariations(targetNames...)
 	for i, m := range modules {
-		m.(Module).base().SetTarget(moduleTargets[i], primaryModules[i])
+		m.(Module).base().SetTarget(moduleTargets[i], moduleMultiTargets[i], primaryModules[i])
 		m.(Module).base().setArchProperties(mctx)
 	}
 }
 
+func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
+	switch class {
+	case Device:
+		multilib = String(base.commonProperties.Target.Android.Compile_multilib)
+	case Host, HostCross:
+		multilib = String(base.commonProperties.Target.Host.Compile_multilib)
+	}
+	if multilib == "" {
+		multilib = String(base.commonProperties.Compile_multilib)
+	}
+	if multilib == "" {
+		multilib = base.commonProperties.Default_multilib
+	}
+
+	if base.commonProperties.UseTargetVariants {
+		return multilib, ""
+	} else {
+		// For app modules a single arch variant will be created per OS class which is expected to handle all the
+		// selected arches.  Return the common-type as multilib and any Android.bp provided multilib as extraMultilib
+		if multilib == base.commonProperties.Default_multilib {
+			multilib = "first"
+		}
+		return base.commonProperties.Default_multilib, multilib
+	}
+}
+
 func filterArchStruct(prop reflect.Type) (reflect.Type, bool) {
 	var fields []reflect.StructField
 
@@ -1114,7 +1163,7 @@
 }
 
 // Use the module multilib setting to select one or more targets from a target list
-func decodeMultilib(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
+func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
 	buildTargets := []Target{}
 
 	switch multilib {
diff --git a/android/config.go b/android/config.go
index 4b10552..5da1e0b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -232,8 +232,8 @@
 
 	config.Targets = map[OsClass][]Target{
 		Device: []Target{
-			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true}},
-			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true}},
+			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}},
+			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}},
 		},
 		Host: []Target{
 			{BuildOs, Arch{ArchType: X86_64}},
diff --git a/android/module.go b/android/module.go
index 01766b4..9d9d9a9 100644
--- a/android/module.go
+++ b/android/module.go
@@ -58,6 +58,7 @@
 type androidBaseContext interface {
 	Target() Target
 	TargetPrimary() bool
+	MultiTargets() []Target
 	Arch() Arch
 	Os() OsType
 	Host() bool
@@ -215,7 +216,8 @@
 		}
 	}
 
-	Default_multilib string `blueprint:"mutated"`
+	UseTargetVariants bool   `blueprint:"mutated"`
+	Default_multilib  string `blueprint:"mutated"`
 
 	// whether this is a proprietary vendor module, and should be installed into /vendor
 	Proprietary *bool
@@ -264,8 +266,9 @@
 	Notice *string
 
 	// Set by TargetMutator
-	CompileTarget  Target `blueprint:"mutated"`
-	CompilePrimary bool   `blueprint:"mutated"`
+	CompileTarget       Target   `blueprint:"mutated"`
+	CompileMultiTargets []Target `blueprint:"mutated"`
+	CompilePrimary      bool     `blueprint:"mutated"`
 
 	// Set by InitAndroidModule
 	HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
@@ -362,6 +365,7 @@
 	base.commonProperties.HostOrDeviceSupported = hod
 	base.commonProperties.Default_multilib = string(defaultMultilib)
 	base.commonProperties.ArchSpecific = true
+	base.commonProperties.UseTargetVariants = true
 
 	switch hod {
 	case HostAndDeviceSupported, HostAndDeviceDefault:
@@ -371,6 +375,11 @@
 	InitArchModule(m)
 }
 
+func InitAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
+	InitAndroidArchModule(m, hod, defaultMultilib)
+	m.base().commonProperties.UseTargetVariants = false
+}
+
 // A ModuleBase object contains the properties that are common to all Android
 // modules.  It should be included as an anonymous field in every module
 // struct definition.  InitAndroidModule should then be called from the module's
@@ -477,8 +486,9 @@
 	return a
 }
 
-func (a *ModuleBase) SetTarget(target Target, primary bool) {
+func (a *ModuleBase) SetTarget(target Target, multiTargets []Target, primary bool) {
 	a.commonProperties.CompileTarget = target
+	a.commonProperties.CompileMultiTargets = multiTargets
 	a.commonProperties.CompilePrimary = primary
 }
 
@@ -490,6 +500,10 @@
 	return a.commonProperties.CompilePrimary
 }
 
+func (a *ModuleBase) MultiTargets() []Target {
+	return a.commonProperties.CompileMultiTargets
+}
+
 func (a *ModuleBase) Os() OsType {
 	return a.Target().Os
 }
@@ -731,6 +745,7 @@
 	return androidBaseContextImpl{
 		target:        a.commonProperties.CompileTarget,
 		targetPrimary: a.commonProperties.CompilePrimary,
+		multiTargets:  a.commonProperties.CompileMultiTargets,
 		kind:          determineModuleKind(a, ctx),
 		config:        ctx.Config().(Config),
 	}
@@ -785,6 +800,7 @@
 
 type androidBaseContextImpl struct {
 	target        Target
+	multiTargets  []Target
 	targetPrimary bool
 	debug         bool
 	kind          moduleKind
@@ -1022,6 +1038,10 @@
 	return a.targetPrimary
 }
 
+func (a *androidBaseContextImpl) MultiTargets() []Target {
+	return a.multiTargets
+}
+
 func (a *androidBaseContextImpl) Arch() Arch {
 	return a.target.Arch
 }
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 1d50980..10e5b0a 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -140,6 +140,7 @@
 			"LOCAL_DX_FLAGS":              "dxflags",
 			"LOCAL_JAVA_LIBRARIES":        "libs",
 			"LOCAL_STATIC_JAVA_LIBRARIES": "static_libs",
+			"LOCAL_JNI_SHARED_LIBRARIES":  "jni_libs",
 			"LOCAL_AAPT_FLAGS":            "aaptflags",
 			"LOCAL_PACKAGE_SPLITS":        "package_splits",
 			"LOCAL_COMPATIBILITY_SUITE":   "test_suites",
@@ -154,6 +155,7 @@
 			// java_library_static to android_library.
 			"LOCAL_SHARED_ANDROID_LIBRARIES": "android_libs",
 			"LOCAL_STATIC_ANDROID_LIBRARIES": "android_static_libs",
+			"LOCAL_ADDITIONAL_CERTIFICATES":  "additional_certificates",
 		})
 
 	addStandardProperties(bpparser.BoolType,
diff --git a/cc/binary.go b/cc/binary.go
index 07d503b..5fa501e 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -302,8 +302,7 @@
 	if binary.stripper.needsStrip(ctx) {
 		// b/80093681, GNU strip/objcopy bug.
 		// Use llvm-{strip,objcopy} when clang lld is used.
-		builderFlags.stripUseLlvmStrip =
-			flags.Clang && binary.baseLinker.useClangLld(ctx)
+		builderFlags.stripUseLlvmStrip = binary.baseLinker.useClangLld(ctx)
 		strippedOutputFile := outputFile
 		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
 		binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
diff --git a/cc/builder.go b/cc/builder.go
index d1bc23f..d16efd0 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -242,7 +242,6 @@
 	aidlFlags       string
 	rsFlags         string
 	toolchain       config.Toolchain
-	clang           bool
 	tidy            bool
 	coverage        bool
 	sAbiDump        bool
@@ -290,7 +289,7 @@
 
 	objFiles := make(android.Paths, len(srcFiles))
 	var tidyFiles android.Paths
-	if flags.tidy && flags.clang {
+	if flags.tidy {
 		tidyFiles = make(android.Paths, 0, len(srcFiles))
 	}
 	var coverageFiles android.Paths
@@ -333,19 +332,14 @@
 	}, " ")
 
 	var sAbiDumpFiles android.Paths
-	if flags.sAbiDump && flags.clang {
+	if flags.sAbiDump {
 		sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
 	}
 
-	if flags.clang {
-		cflags += " ${config.NoOverrideClangGlobalCflags}"
-		toolingCflags += " ${config.NoOverrideClangGlobalCflags}"
-		cppflags += " ${config.NoOverrideClangGlobalCflags}"
-		toolingCppflags += " ${config.NoOverrideClangGlobalCflags}"
-	} else {
-		cflags += " ${config.NoOverrideGlobalCflags}"
-		cppflags += " ${config.NoOverrideGlobalCflags}"
-	}
+	cflags += " ${config.NoOverrideClangGlobalCflags}"
+	toolingCflags += " ${config.NoOverrideClangGlobalCflags}"
+	cppflags += " ${config.NoOverrideClangGlobalCflags}"
+	toolingCppflags += " ${config.NoOverrideClangGlobalCflags}"
 
 	for i, srcFile := range srcFiles {
 		objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
@@ -385,23 +379,23 @@
 		var moduleCflags string
 		var moduleToolingCflags string
 		var ccCmd string
-		tidy := flags.tidy && flags.clang
+		tidy := flags.tidy
 		coverage := flags.coverage
-		dump := flags.sAbiDump && flags.clang
+		dump := flags.sAbiDump
 
 		switch srcFile.Ext() {
 		case ".S", ".s":
-			ccCmd = "gcc"
+			ccCmd = "clang"
 			moduleCflags = asflags
 			tidy = false
 			coverage = false
 			dump = false
 		case ".c":
-			ccCmd = "gcc"
+			ccCmd = "clang"
 			moduleCflags = cflags
 			moduleToolingCflags = toolingCflags
 		case ".cpp", ".cc", ".mm":
-			ccCmd = "g++"
+			ccCmd = "clang++"
 			moduleCflags = cppflags
 			moduleToolingCflags = toolingCppflags
 		default:
@@ -409,24 +403,9 @@
 			continue
 		}
 
-		if flags.clang {
-			switch ccCmd {
-			case "gcc":
-				ccCmd = "clang"
-			case "g++":
-				ccCmd = "clang++"
-			default:
-				panic("unrecoginzied ccCmd")
-			}
-		}
-
 		ccDesc := ccCmd
 
-		if flags.clang {
-			ccCmd = "${config.ClangBin}/" + ccCmd
-		} else {
-			ccCmd = gccCmd(flags.toolchain, ccCmd)
-		}
+		ccCmd = "${config.ClangBin}/" + ccCmd
 
 		var implicitOutputs android.WritablePaths
 		if coverage {
@@ -611,12 +590,7 @@
 	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
 	crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath) {
 
-	var ldCmd string
-	if flags.clang {
-		ldCmd = "${config.ClangBin}/clang++"
-	} else {
-		ldCmd = gccCmd(flags.toolchain, "g++")
-	}
+	ldCmd := "${config.ClangBin}/clang++"
 
 	var libFlagsList []string
 
@@ -777,12 +751,7 @@
 func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
 	flags builderFlags, outputFile android.WritablePath) {
 
-	var ldCmd string
-	if flags.clang {
-		ldCmd = "${config.ClangBin}/clang++"
-	} else {
-		ldCmd = gccCmd(flags.toolchain, "g++")
-	}
+	ldCmd := "${config.ClangBin}/clang++"
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        partialLd,
diff --git a/cc/cc.go b/cc/cc.go
index d04485d..5f3baea 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -35,11 +35,11 @@
 
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("image", imageMutator).Parallel()
-		ctx.BottomUp("link", linkageMutator).Parallel()
+		ctx.BottomUp("link", LinkageMutator).Parallel()
 		ctx.BottomUp("vndk", vndkMutator).Parallel()
 		ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
-		ctx.BottomUp("begin", beginMutator).Parallel()
+		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
 
 	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -136,7 +136,6 @@
 	SystemIncludeFlags []string
 
 	Toolchain config.Toolchain
-	Clang     bool
 	Tidy      bool
 	Coverage  bool
 	SAbiDump  bool
@@ -165,9 +164,6 @@
 	// Deprecated. true is the default, false is invalid.
 	Clang *bool `android:"arch_variant"`
 
-	// Some internals still need GCC (toolchain_library)
-	Gcc bool `blueprint:"mutated"`
-
 	// Minimum sdk version supported when compiling against the ndk
 	Sdk_version *string
 
@@ -220,7 +216,6 @@
 type ModuleContextIntf interface {
 	static() bool
 	staticBinary() bool
-	clang() bool
 	toolchain() config.Toolchain
 	useSdk() bool
 	sdkVersion() string
@@ -513,10 +508,6 @@
 	ctx BaseModuleContext
 }
 
-func (ctx *moduleContextImpl) clang() bool {
-	return ctx.mod.clang(ctx.ctx)
-}
-
 func (ctx *moduleContextImpl) toolchain() config.Toolchain {
 	return ctx.mod.toolchain(ctx.ctx)
 }
@@ -733,9 +724,12 @@
 		return
 	}
 
+	if c.Properties.Clang != nil && *c.Properties.Clang == false {
+		ctx.PropertyErrorf("clang", "false (GCC) is no longer supported")
+	}
+
 	flags := Flags{
 		Toolchain: c.toolchain(ctx),
-		Clang:     c.clang(ctx),
 	}
 	if c.compiler != nil {
 		flags = c.compiler.compilerFlags(ctx, flags, deps)
@@ -1093,20 +1087,12 @@
 	}
 }
 
-func beginMutator(ctx android.BottomUpMutatorContext) {
+func BeginMutator(ctx android.BottomUpMutatorContext) {
 	if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
 		c.beginMutator(ctx)
 	}
 }
 
-func (c *Module) clang(ctx BaseModuleContext) bool {
-	if c.Properties.Clang != nil && *c.Properties.Clang == false {
-		ctx.PropertyErrorf("clang", "false (GCC) is no longer supported")
-	}
-
-	return !c.Properties.Gcc
-}
-
 // Whether a module can link to another module, taking into
 // account NDK linking.
 func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag dependencyTag) {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 01beb66..bca26ea 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -56,17 +56,17 @@
 	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
 	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
 	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(LibraryHeaderFactory))
-	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
+	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(ToolchainLibraryFactory))
 	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
 	ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
 	ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
-	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
+	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
 	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("image", imageMutator).Parallel()
-		ctx.BottomUp("link", linkageMutator).Parallel()
+		ctx.BottomUp("link", LinkageMutator).Parallel()
 		ctx.BottomUp("vndk", vndkMutator).Parallel()
-		ctx.BottomUp("begin", beginMutator).Parallel()
+		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
 	ctx.Register()
 
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index 699f5c0..7b4f89b 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -18,7 +18,6 @@
 	"fmt"
 
 	"android/soong/android"
-	"android/soong/cc/config"
 	"os"
 	"path"
 	"path/filepath"
@@ -150,18 +149,10 @@
 	f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name()))
 	f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", getAndroidSrcRootDirectory(ctx)))
 
-	if ccModule.flags.Clang {
-		pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
-		f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
-		f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang++"))
-	} else {
-		toolchain := config.FindToolchain(ccModule.Os(), ccModule.Arch())
-		root, _ := evalVariable(ctx, toolchain.GccRoot())
-		triple, _ := evalVariable(ctx, toolchain.GccTriple())
-		pathToCC := filepath.Join(root, "bin", triple+"-")
-		f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "gcc"))
-		f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "g++"))
-	}
+	pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
+	f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
+	f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang++"))
+
 	// Add all sources to the project.
 	f.WriteString("list(APPEND\n")
 	f.WriteString("     SOURCE_FILES\n")
diff --git a/cc/compiler.go b/cc/compiler.go
index 5ef9e4e..68d8593 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -340,10 +340,7 @@
 	if flags.RequiredInstructionSet != "" {
 		instructionSet = flags.RequiredInstructionSet
 	}
-	instructionSetFlags, err := tc.InstructionSetFlags(instructionSet)
-	if flags.Clang {
-		instructionSetFlags, err = tc.ClangInstructionSetFlags(instructionSet)
-	}
+	instructionSetFlags, err := tc.ClangInstructionSetFlags(instructionSet)
 	if err != nil {
 		ctx.ModuleErrorf("%s", err)
 	}
@@ -353,24 +350,22 @@
 	// TODO: debug
 	flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Release.Cflags)...)
 
-	if flags.Clang {
-		CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
-		CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+	CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
+	CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
 
-		flags.CFlags = config.ClangFilterUnknownCflags(flags.CFlags)
-		flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Clang_cflags)...)
-		flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Clang_asflags)...)
-		flags.CppFlags = config.ClangFilterUnknownCflags(flags.CppFlags)
-		flags.ConlyFlags = config.ClangFilterUnknownCflags(flags.ConlyFlags)
-		flags.LdFlags = config.ClangFilterUnknownCflags(flags.LdFlags)
+	flags.CFlags = config.ClangFilterUnknownCflags(flags.CFlags)
+	flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Clang_cflags)...)
+	flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Clang_asflags)...)
+	flags.CppFlags = config.ClangFilterUnknownCflags(flags.CppFlags)
+	flags.ConlyFlags = config.ClangFilterUnknownCflags(flags.ConlyFlags)
+	flags.LdFlags = config.ClangFilterUnknownCflags(flags.LdFlags)
 
-		target := "-target " + tc.ClangTriple()
-		gccPrefix := "-B" + config.ToolPath(tc)
+	target := "-target " + tc.ClangTriple()
+	gccPrefix := "-B" + config.ToolPath(tc)
 
-		flags.CFlags = append(flags.CFlags, target, gccPrefix)
-		flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
-		flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
-	}
+	flags.CFlags = append(flags.CFlags, target, gccPrefix)
+	flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
+	flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
 
 	hod := "Host"
 	if ctx.Os().Class == android.Device {
@@ -381,25 +376,15 @@
 	flags.ConlyFlags = append([]string{"${config.CommonGlobalConlyflags}"}, flags.ConlyFlags...)
 	flags.CppFlags = append([]string{fmt.Sprintf("${config.%sGlobalCppflags}", hod)}, flags.CppFlags...)
 
-	if flags.Clang {
-		flags.AsFlags = append(flags.AsFlags, tc.ClangAsflags())
-		flags.CppFlags = append([]string{"${config.CommonClangGlobalCppflags}"}, flags.CppFlags...)
-		flags.GlobalFlags = append(flags.GlobalFlags,
-			tc.ClangCflags(),
-			"${config.CommonClangGlobalCflags}",
-			fmt.Sprintf("${config.%sClangGlobalCflags}", hod))
-	} else {
-		flags.CppFlags = append([]string{"${config.CommonGlobalCppflags}"}, flags.CppFlags...)
-		flags.GlobalFlags = append(flags.GlobalFlags,
-			tc.Cflags(),
-			"${config.CommonGlobalCflags}",
-			fmt.Sprintf("${config.%sGlobalCflags}", hod))
-	}
+	flags.AsFlags = append(flags.AsFlags, tc.ClangAsflags())
+	flags.CppFlags = append([]string{"${config.CommonClangGlobalCppflags}"}, flags.CppFlags...)
+	flags.GlobalFlags = append(flags.GlobalFlags,
+		tc.ClangCflags(),
+		"${config.CommonClangGlobalCflags}",
+		fmt.Sprintf("${config.%sClangGlobalCflags}", hod))
 
-	if flags.Clang {
-		if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
-			flags.GlobalFlags = append([]string{"${config.ClangExternalCflags}"}, flags.GlobalFlags...)
-		}
+	if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
+		flags.GlobalFlags = append([]string{"${config.ClangExternalCflags}"}, flags.GlobalFlags...)
 	}
 
 	if ctx.Device() {
@@ -412,19 +397,11 @@
 
 	flags.AsFlags = append(flags.AsFlags, "-D__ASSEMBLY__")
 
-	if flags.Clang {
-		flags.CppFlags = append(flags.CppFlags, tc.ClangCppflags())
-	} else {
-		flags.CppFlags = append(flags.CppFlags, tc.Cppflags())
-	}
+	flags.CppFlags = append(flags.CppFlags, tc.ClangCppflags())
 
 	flags.YasmFlags = append(flags.YasmFlags, tc.YasmFlags())
 
-	if flags.Clang {
-		flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainClangCflags())
-	} else {
-		flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainCflags())
-	}
+	flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainClangCflags())
 
 	cStd := config.CStdVersion
 	if String(compiler.Properties.C_std) == "experimental" {
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index c1c2c7b..8dee2c8 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -348,17 +348,6 @@
 	return "${config.ArmIncludeFlags}"
 }
 
-func (t *toolchainArm) InstructionSetFlags(isa string) (string, error) {
-	switch isa {
-	case "arm":
-		return "${config.ArmArmCflags}", nil
-	case "thumb", "":
-		return "${config.ArmThumbCflags}", nil
-	default:
-		return t.toolchainBase.InstructionSetFlags(isa)
-	}
-}
-
 func (t *toolchainArm) ClangTriple() string {
 	// http://b/72619014 work around llvm LTO bug.
 	return "armv7a-linux-androideabi"
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 5e22d6a..5cf2421 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -103,6 +103,10 @@
 	pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
 		"-D__compiler_offsetof=__builtin_offsetof",
 
+		// Make implicit fallthrough an error in the future.
+		"-Wimplicit-fallthrough",
+		"-Wno-error=implicit-fallthrough",
+
 		// Help catch common 32/64-bit errors.
 		"-Werror=int-conversion",
 
diff --git a/cc/config/global.go b/cc/config/global.go
index ad63c97..8a3d545 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -146,19 +146,13 @@
 		commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
 	}
 
-	pctx.StaticVariable("CommonGlobalCflags", strings.Join(commonGlobalCflags, " "))
 	pctx.StaticVariable("CommonGlobalConlyflags", strings.Join(commonGlobalConlyflags, " "))
-	pctx.StaticVariable("DeviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
 	pctx.StaticVariable("DeviceGlobalCppflags", strings.Join(deviceGlobalCppflags, " "))
 	pctx.StaticVariable("DeviceGlobalLdflags", strings.Join(deviceGlobalLdflags, " "))
 	pctx.StaticVariable("DeviceGlobalLldflags", strings.Join(deviceGlobalLldflags, " "))
-	pctx.StaticVariable("HostGlobalCflags", strings.Join(hostGlobalCflags, " "))
 	pctx.StaticVariable("HostGlobalCppflags", strings.Join(hostGlobalCppflags, " "))
 	pctx.StaticVariable("HostGlobalLdflags", strings.Join(hostGlobalLdflags, " "))
 	pctx.StaticVariable("HostGlobalLldflags", strings.Join(hostGlobalLldflags, " "))
-	pctx.StaticVariable("NoOverrideGlobalCflags", strings.Join(noOverrideGlobalCflags, " "))
-
-	pctx.StaticVariable("CommonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
 
 	pctx.StaticVariable("CommonClangGlobalCflags",
 		strings.Join(append(ClangFilterUnknownCflags(commonGlobalCflags), "${ClangExtraCflags}"), " "))
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 930b18f..0b9f4ed 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -49,13 +49,7 @@
 	GccVersion() string
 	ToolPath() string
 
-	ToolchainCflags() string
-	ToolchainLdflags() string
-	Cflags() string
-	Cppflags() string
-	Ldflags() string
 	IncludeFlags() string
-	InstructionSetFlags(string) (string, error)
 
 	ClangTriple() string
 	ToolchainClangCflags() string
@@ -101,13 +95,6 @@
 	return triple
 }
 
-func (toolchainBase) InstructionSetFlags(s string) (string, error) {
-	if s != "" {
-		return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s)
-	}
-	return "", nil
-}
-
 func (toolchainBase) ClangInstructionSetFlags(s string) (string, error) {
 	if s != "" {
 		return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s)
@@ -115,14 +102,6 @@
 	return "", nil
 }
 
-func (toolchainBase) ToolchainCflags() string {
-	return ""
-}
-
-func (toolchainBase) ToolchainLdflags() string {
-	return ""
-}
-
 func (toolchainBase) ToolchainClangCflags() string {
 	return ""
 }
diff --git a/cc/library.go b/cc/library.go
index 0e45af9..9eb3f47 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -274,11 +274,6 @@
 
 	if library.shared() {
 		libName := library.getLibName(ctx)
-		// GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
-		sharedFlag := "-Wl,-shared"
-		if flags.Clang || ctx.Host() {
-			sharedFlag = "-shared"
-		}
 		var f []string
 		if ctx.toolchain().Bionic() {
 			f = append(f,
@@ -300,7 +295,7 @@
 			}
 		} else {
 			f = append(f,
-				sharedFlag,
+				"-shared",
 				"-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
 		}
 
@@ -558,8 +553,7 @@
 	if library.stripper.needsStrip(ctx) {
 		// b/80093681, GNU strip/objcopy bug.
 		// Use llvm-{strip,objcopy} when clang lld is used.
-		builderFlags.stripUseLlvmStrip =
-			flags.Clang && library.baseLinker.useClangLld(ctx)
+		builderFlags.stripUseLlvmStrip = library.baseLinker.useClangLld(ctx)
 		strippedOutputFile := outputFile
 		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
 		library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
@@ -821,7 +815,7 @@
 	}
 }
 
-func linkageMutator(mctx android.BottomUpMutatorContext) {
+func LinkageMutator(mctx android.BottomUpMutatorContext) {
 	if m, ok := mctx.Module().(*Module); ok && m.linker != nil {
 		if library, ok := m.linker.(libraryInterface); ok {
 			var modules []blueprint.Module
diff --git a/cc/linker.go b/cc/linker.go
index 9911b16..e3f1ff1 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -293,7 +293,7 @@
 		hod = "Device"
 	}
 
-	if flags.Clang && linker.useClangLld(ctx) {
+	if linker.useClangLld(ctx) {
 		flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
 		if !BoolDefault(linker.MoreProperties.Pack_relocations, true) {
 			flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=none")
@@ -310,12 +310,10 @@
 		flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
 	}
 
-	if flags.Clang && linker.useClangLld(ctx) {
+	if linker.useClangLld(ctx) {
 		flags.LdFlags = append(flags.LdFlags, toolchain.ClangLldflags())
-	} else if flags.Clang {
-		flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
 	} else {
-		flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
+		flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
 	}
 
 	if !ctx.toolchain().Bionic() {
@@ -362,11 +360,7 @@
 		flags.LdFlags = append(flags.LdFlags, "-Wl,--hash-style=both")
 	}
 
-	if flags.Clang {
-		flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
-	} else {
-		flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
-	}
+	flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
 
 	if Bool(linker.Properties.Group_static_libs) {
 		flags.GroupStaticLibs = true
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 2709a89..63d9f29 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -61,7 +61,7 @@
 	// These libraries have migrated over to the new ndk_library, which is added
 	// as a variation dependency via depsMutator.
 	ndkMigratedLibs     = []string{}
-	ndkMigratedLibsLock sync.Mutex // protects ndkMigratedLibs writes during parallel beginMutator
+	ndkMigratedLibsLock sync.Mutex // protects ndkMigratedLibs writes during parallel BeginMutator
 )
 
 // Creates a stub shared library based on the provided version file.
diff --git a/cc/object.go b/cc/object.go
index 7c134ac..0010621 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -25,7 +25,7 @@
 //
 
 func init() {
-	android.RegisterModuleType("cc_object", objectFactory)
+	android.RegisterModuleType("cc_object", ObjectFactory)
 }
 
 type objectLinker struct {
@@ -33,7 +33,7 @@
 	Properties ObjectLinkerProperties
 }
 
-func objectFactory() android.Module {
+func ObjectFactory() android.Module {
 	module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth)
 	module.linker = &objectLinker{
 		baseLinker: NewBaseLinker(nil),
@@ -64,11 +64,7 @@
 }
 
 func (*objectLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
-	if flags.Clang {
-		flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
-	} else {
-		flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainLdflags())
-	}
+	flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
 
 	return flags
 }
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b2fc63f..8262a68 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -50,7 +50,8 @@
 	hwasanStaticLibsMutex sync.Mutex
 
 	intOverflowCflags   = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
-	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer", "-fno-sanitize-recover=integer"}
+	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
+		"-fno-sanitize-recover=integer,undefined"}
 )
 
 type sanitizerType int
@@ -164,17 +165,15 @@
 	var globalSanitizers []string
 	var globalSanitizersDiag []string
 
-	if ctx.clang() {
-		if ctx.Host() {
-			if !ctx.Windows() {
-				globalSanitizers = ctx.Config().SanitizeHost()
-			}
-		} else {
-			arches := ctx.Config().SanitizeDeviceArch()
-			if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
-				globalSanitizers = ctx.Config().SanitizeDevice()
-				globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
-			}
+	if ctx.Host() {
+		if !ctx.Windows() {
+			globalSanitizers = ctx.Config().SanitizeHost()
+		}
+	} else {
+		arches := ctx.Config().SanitizeDeviceArch()
+		if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
+			globalSanitizers = ctx.Config().SanitizeDevice()
+			globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
 		}
 	}
 
@@ -369,10 +368,6 @@
 		return flags
 	}
 
-	if !ctx.clang() {
-		ctx.ModuleErrorf("Use of sanitizers requires clang")
-	}
-
 	var sanitizers []string
 	var diagSanitizers []string
 
diff --git a/cc/tidy.go b/cc/tidy.go
index 0a6b413..ddb445a 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -62,11 +62,6 @@
 		return flags
 	}
 
-	// Clang-tidy requires clang
-	if !flags.Clang {
-		return flags
-	}
-
 	flags.Tidy = true
 
 	// Add global WITH_TIDY_FLAGS and local tidy_flags.
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 20b0f85..5811b01 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -23,7 +23,7 @@
 //
 
 func init() {
-	android.RegisterModuleType("toolchain_library", toolchainLibraryFactory)
+	android.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
 }
 
 type toolchainLibraryProperties struct {
@@ -48,7 +48,7 @@
 	return append(props, &library.Properties)
 }
 
-func toolchainLibraryFactory() android.Module {
+func ToolchainLibraryFactory() android.Module {
 	module, library := NewLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyStatic()
 	toolchainLibrary := &toolchainLibraryDecorator{
@@ -56,7 +56,6 @@
 	}
 	module.compiler = toolchainLibrary
 	module.linker = toolchainLibrary
-	module.Properties.Gcc = true
 	module.stl = nil
 	module.sanitize = nil
 	module.installer = nil
diff --git a/cc/util.go b/cc/util.go
index bab4d32..1412d54 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -78,7 +78,6 @@
 		sAbiFlags:       strings.Join(in.SAbiFlags, " "),
 		yasmFlags:       strings.Join(in.YasmFlags, " "),
 		toolchain:       in.Toolchain,
-		clang:           in.Clang,
 		coverage:        in.Coverage,
 		tidy:            in.Tidy,
 		sAbiDump:        in.SAbiDump,
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index e8ea9b9..d3b349c 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -17,6 +17,7 @@
 import (
 	"flag"
 	"fmt"
+	"io"
 	"log"
 	"os"
 	"path/filepath"
@@ -39,11 +40,13 @@
 
 	staticTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
 
-	excludes excludeArgs
+	excludes   multiFlag
+	uncompress multiFlag
 )
 
 func init() {
 	flag.Var(&excludes, "x", "exclude a filespec from the output")
+	flag.Var(&uncompress, "0", "convert a filespec to uncompressed in the output")
 }
 
 func main() {
@@ -93,7 +96,7 @@
 	}()
 
 	if err := zip2zip(&reader.Reader, writer, *sortGlobs, *sortJava, *setTime,
-		flag.Args(), excludes); err != nil {
+		flag.Args(), excludes, uncompress); err != nil {
 
 		log.Fatal(err)
 	}
@@ -101,11 +104,12 @@
 
 type pair struct {
 	*zip.File
-	newName string
+	newName    string
+	uncompress bool
 }
 
 func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTime bool,
-	includes []string, excludes []string) error {
+	includes, excludes, uncompresses []string) error {
 
 	matches := []pair{}
 
@@ -149,7 +153,7 @@
 						newName = output
 					}
 				}
-				includeMatches = append(includeMatches, pair{file, newName})
+				includeMatches = append(includeMatches, pair{file, newName, false})
 			}
 		}
 
@@ -160,7 +164,7 @@
 	if len(includes) == 0 {
 		// implicitly match everything
 		for _, file := range reader.File {
-			matches = append(matches, pair{file, file.Name})
+			matches = append(matches, pair{file, file.Name, false})
 		}
 		sortMatches(matches)
 	}
@@ -193,6 +197,15 @@
 		}
 		seen[match.newName] = match.File
 
+		for _, u := range uncompresses {
+			if uncompressMatch, err := pathtools.Match(u, match.newName); err != nil {
+				return err
+			} else if uncompressMatch {
+				match.uncompress = true
+				break
+			}
+		}
+
 		matchesAfterExcludes = append(matchesAfterExcludes, match)
 	}
 
@@ -200,8 +213,32 @@
 		if setTime {
 			match.File.SetModTime(staticTime)
 		}
-		if err := writer.CopyFrom(match.File, match.newName); err != nil {
-			return err
+		if match.uncompress && match.File.FileHeader.Method != zip.Store {
+			fh := match.File.FileHeader
+			fh.Name = match.newName
+			fh.Method = zip.Store
+			fh.CompressedSize64 = fh.UncompressedSize64
+
+			zw, err := writer.CreateHeaderAndroid(&fh)
+			if err != nil {
+				return err
+			}
+
+			zr, err := match.File.Open()
+			if err != nil {
+				return err
+			}
+
+			_, err = io.Copy(zw, zr)
+			zr.Close()
+			if err != nil {
+				return err
+			}
+		} else {
+			err := writer.CopyFrom(match.File, match.newName)
+			if err != nil {
+				return err
+			}
 		}
 	}
 
@@ -217,13 +254,13 @@
 	}
 }
 
-type excludeArgs []string
+type multiFlag []string
 
-func (e *excludeArgs) String() string {
+func (e *multiFlag) String() string {
 	return strings.Join(*e, " ")
 }
 
-func (e *excludeArgs) Set(s string) error {
+func (e *multiFlag) Set(s string) error {
 	*e = append(*e, s)
 	return nil
 }
diff --git a/cmd/zip2zip/zip2zip_test.go b/cmd/zip2zip/zip2zip_test.go
index 212ab28..e032fe6 100644
--- a/cmd/zip2zip/zip2zip_test.go
+++ b/cmd/zip2zip/zip2zip_test.go
@@ -26,13 +26,15 @@
 var testCases = []struct {
 	name string
 
-	inputFiles []string
-	sortGlobs  bool
-	sortJava   bool
-	args       []string
-	excludes   []string
+	inputFiles   []string
+	sortGlobs    bool
+	sortJava     bool
+	args         []string
+	excludes     []string
+	uncompresses []string
 
 	outputFiles []string
+	storedFiles []string
 	err         error
 }{
 	{
@@ -251,6 +253,79 @@
 
 		outputFiles: nil,
 	},
+	{
+		name: "uncompress one",
+
+		inputFiles: []string{
+			"a/a",
+			"a/b",
+		},
+		uncompresses: []string{"a/a"},
+
+		outputFiles: []string{
+			"a/a",
+			"a/b",
+		},
+		storedFiles: []string{
+			"a/a",
+		},
+	},
+	{
+		name: "uncompress two",
+
+		inputFiles: []string{
+			"a/a",
+			"a/b",
+		},
+		uncompresses: []string{"a/a", "a/b"},
+
+		outputFiles: []string{
+			"a/a",
+			"a/b",
+		},
+		storedFiles: []string{
+			"a/a",
+			"a/b",
+		},
+	},
+	{
+		name: "uncompress glob",
+
+		inputFiles: []string{
+			"a/a",
+			"a/b",
+			"a/c.so",
+			"a/d.so",
+		},
+		uncompresses: []string{"a/*.so"},
+
+		outputFiles: []string{
+			"a/a",
+			"a/b",
+			"a/c.so",
+			"a/d.so",
+		},
+		storedFiles: []string{
+			"a/c.so",
+			"a/d.so",
+		},
+	},
+	{
+		name: "uncompress rename",
+
+		inputFiles: []string{
+			"a/a",
+		},
+		args:         []string{"a/a:a/b"},
+		uncompresses: []string{"a/b"},
+
+		outputFiles: []string{
+			"a/b",
+		},
+		storedFiles: []string{
+			"a/b",
+		},
+	},
 }
 
 func errorString(e error) string {
@@ -282,7 +357,8 @@
 			}
 
 			outputWriter := zip.NewWriter(outputBuf)
-			err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false, testCase.args, testCase.excludes)
+			err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false,
+				testCase.args, testCase.excludes, testCase.uncompresses)
 			if errorString(testCase.err) != errorString(err) {
 				t.Fatalf("Unexpected error:\n got: %q\nwant: %q", errorString(err), errorString(testCase.err))
 			}
@@ -294,15 +370,22 @@
 				t.Fatal(err)
 			}
 			var outputFiles []string
+			var storedFiles []string
 			if len(outputReader.File) > 0 {
 				outputFiles = make([]string, len(outputReader.File))
 				for i, file := range outputReader.File {
 					outputFiles[i] = file.Name
+					if file.Method == zip.Store {
+						storedFiles = append(storedFiles, file.Name)
+					}
 				}
 			}
 
 			if !reflect.DeepEqual(testCase.outputFiles, outputFiles) {
-				t.Fatalf("Output file list does not match:\n got: %v\nwant: %v", outputFiles, testCase.outputFiles)
+				t.Fatalf("Output file list does not match:\nwant: %v\n got: %v", testCase.outputFiles, outputFiles)
+			}
+			if !reflect.DeepEqual(testCase.storedFiles, storedFiles) {
+				t.Fatalf("Stored file list does not match:\nwant: %v\n got: %v", testCase.storedFiles, storedFiles)
 			}
 		})
 	}
diff --git a/java/androidmk.go b/java/androidmk.go
index 313a144..359594c 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -243,6 +243,10 @@
 				if len(app.appProperties.Overrides) > 0 {
 					fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES := "+strings.Join(app.appProperties.Overrides, " "))
 				}
+
+				for _, jniLib := range app.installJniLibs {
+					fmt.Fprintln(w, "LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), "+=", jniLib.name)
+				}
 			},
 		},
 	}
@@ -267,6 +271,21 @@
 	return data
 }
 
+func (a *AndroidTestHelperApp) AndroidMk() android.AndroidMkData {
+	data := a.AndroidApp.AndroidMk()
+	data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
+		fmt.Fprintln(w, "LOCAL_MODULE_TAGS := tests")
+		if len(a.appTestHelperAppProperties.Test_suites) > 0 {
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+				strings.Join(a.appTestHelperAppProperties.Test_suites, " "))
+		} else {
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := null-suite")
+		}
+	})
+
+	return data
+}
+
 func (a *AndroidLibrary) AndroidMk() android.AndroidMkData {
 	data := a.Library.AndroidMk()
 
diff --git a/java/app.go b/java/app.go
index dc5296d..d21b62a 100644
--- a/java/app.go
+++ b/java/app.go
@@ -19,26 +19,30 @@
 import (
 	"strings"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/cc"
 	"android/soong/tradefed"
 )
 
 func init() {
 	android.RegisterModuleType("android_app", AndroidAppFactory)
 	android.RegisterModuleType("android_test", AndroidTestFactory)
+	android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
+	android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
 }
 
 // AndroidManifest.xml merging
 // package splits
 
 type appProperties struct {
-	// path to a certificate, or the name of a certificate in the default
-	// certificate directory, or blank to use the default product certificate
+	// The name of a certificate in the default certificate directory, blank to use the default product certificate,
+	// or an android_app_certificate module name in the form ":module".
 	Certificate *string
 
-	// paths to extra certificates to sign the apk with
+	// Names of extra android_app_certificate modules to sign the apk with in the form ":module".
 	Additional_certificates []string
 
 	// If set, create package-export.apk, which other packages can
@@ -59,6 +63,11 @@
 	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
 	// from PRODUCT_PACKAGES.
 	Overrides []string
+
+	// list of native libraries that will be provided in or alongside the resulting jar
+	Jni_libs []string `android:"arch_variant"`
+
+	EmbedJNI bool `blueprint:"mutated"`
 }
 
 type AndroidApp struct {
@@ -70,6 +79,8 @@
 	appProperties appProperties
 
 	extraLinkFlags []string
+
+	installJniLibs []jniLib
 }
 
 func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
@@ -92,9 +103,36 @@
 
 func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
 	a.Module.deps(ctx)
+
 	if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
 		a.aapt.deps(ctx, sdkContext(a))
 	}
+
+	for _, jniTarget := range ctx.MultiTargets() {
+		variation := []blueprint.Variation{
+			{Mutator: "arch", Variation: jniTarget.String()},
+			{Mutator: "link", Variation: "shared"},
+		}
+		tag := &jniDependencyTag{
+			target: jniTarget,
+		}
+		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+	}
+
+	cert := android.SrcIsModule(String(a.appProperties.Certificate))
+	if cert != "" {
+		ctx.AddDependency(ctx.Module(), certificateTag, cert)
+	}
+
+	for _, cert := range a.appProperties.Additional_certificates {
+		cert = android.SrcIsModule(cert)
+		if cert != "" {
+			ctx.AddDependency(ctx.Module(), certificateTag, cert)
+		} else {
+			ctx.PropertyErrorf("additional_certificates",
+				`must be names of android_app_certificate modules in the form ":module"`)
+		}
+	}
 }
 
 func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -150,35 +188,45 @@
 		a.Module.compile(ctx, a.aaptSrcJar)
 	}
 
-	c := String(a.appProperties.Certificate)
-	switch {
-	case c == "":
-		pem, key := ctx.Config().DefaultAppCertificate(ctx)
-		a.certificate = certificate{pem, key}
-	case strings.ContainsRune(c, '/'):
-		a.certificate = certificate{
-			android.PathForSource(ctx, c+".x509.pem"),
-			android.PathForSource(ctx, c+".pk8"),
-		}
-	default:
-		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
-		a.certificate = certificate{
-			defaultDir.Join(ctx, c+".x509.pem"),
-			defaultDir.Join(ctx, c+".pk8"),
-		}
-	}
-
-	certificates := []certificate{a.certificate}
-	for _, c := range a.appProperties.Additional_certificates {
-		certificates = append(certificates, certificate{
-			android.PathForSource(ctx, c+".x509.pem"),
-			android.PathForSource(ctx, c+".pk8"),
-		})
-	}
-
 	packageFile := android.PathForModuleOut(ctx, "package.apk")
 
-	CreateAppPackage(ctx, packageFile, a.exportPackage, a.outputFile, certificates)
+	var certificates []certificate
+
+	var jniJarFile android.WritablePath
+	jniLibs, certificateDeps := a.collectAppDeps(ctx)
+	if len(jniLibs) > 0 {
+		embedJni := ctx.Config().UnbundledBuild() || a.appProperties.EmbedJNI
+		if embedJni {
+			jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
+			TransformJniLibsToJar(ctx, jniJarFile, jniLibs)
+		} else {
+			a.installJniLibs = jniLibs
+		}
+	}
+
+	if ctx.Failed() {
+		return
+	}
+
+	cert := String(a.appProperties.Certificate)
+	certModule := android.SrcIsModule(cert)
+	if certModule != "" {
+		a.certificate = certificateDeps[0]
+		certificateDeps = certificateDeps[1:]
+	} else if cert != "" {
+		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
+		a.certificate = certificate{
+			defaultDir.Join(ctx, cert+".x509.pem"),
+			defaultDir.Join(ctx, cert+".pk8"),
+		}
+	} else {
+		pem, key := ctx.Config().DefaultAppCertificate(ctx)
+		a.certificate = certificate{pem, key}
+	}
+
+	certificates = append([]certificate{a.certificate}, certificateDeps...)
+
+	CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, a.outputFile, certificates)
 
 	a.outputFile = packageFile
 
@@ -192,6 +240,42 @@
 	}
 }
 
+func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []certificate) {
+	var jniLibs []jniLib
+	var certificates []certificate
+
+	ctx.VisitDirectDeps(func(module android.Module) {
+		otherName := ctx.OtherModuleName(module)
+		tag := ctx.OtherModuleDependencyTag(module)
+
+		if jniTag, ok := tag.(*jniDependencyTag); ok {
+			if dep, ok := module.(*cc.Module); ok {
+				lib := dep.OutputFile()
+				if lib.Valid() {
+					jniLibs = append(jniLibs, jniLib{
+						name:   ctx.OtherModuleName(module),
+						path:   lib.Path(),
+						target: jniTag.target,
+					})
+				} else {
+					ctx.ModuleErrorf("dependency %q missing output file", otherName)
+				}
+			} else {
+				ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName)
+
+			}
+		} else if tag == certificateTag {
+			if dep, ok := module.(*AndroidAppCertificate); ok {
+				certificates = append(certificates, dep.certificate)
+			} else {
+				ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
+			}
+		}
+	})
+
+	return jniLibs, certificates
+}
+
 func AndroidAppFactory() android.Module {
 	module := &AndroidApp{}
 
@@ -212,7 +296,9 @@
 		return class == android.Device && ctx.Config().DevicePrefer32BitApps()
 	})
 
-	InitJavaModule(module, android.DeviceSupported)
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
+
 	return module
 }
 
@@ -258,6 +344,7 @@
 
 	module.Module.properties.Instrument = true
 	module.Module.properties.Installable = proptools.BoolPtr(true)
+	module.appProperties.EmbedJNI = true
 
 	module.AddProperties(
 		&module.Module.properties,
@@ -268,6 +355,69 @@
 		&module.appTestProperties,
 		&module.testProperties)
 
-	InitJavaModule(module, android.DeviceSupported)
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 	return module
 }
+
+type appTestHelperAppProperties struct {
+	// list of compatibility suites (for example "cts", "vts") that the module should be
+	// installed into.
+	Test_suites []string `android:"arch_variant"`
+}
+
+type AndroidTestHelperApp struct {
+	AndroidApp
+
+	appTestHelperAppProperties appTestHelperAppProperties
+}
+
+func AndroidTestHelperAppFactory() android.Module {
+	module := &AndroidTestHelperApp{}
+
+	module.Module.deviceProperties.Optimize.Enabled = proptools.BoolPtr(true)
+
+	module.Module.properties.Installable = proptools.BoolPtr(true)
+	module.appProperties.EmbedJNI = true
+
+	module.AddProperties(
+		&module.Module.properties,
+		&module.Module.deviceProperties,
+		&module.Module.protoProperties,
+		&module.aaptProperties,
+		&module.appProperties,
+		&module.appTestHelperAppProperties)
+
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
+	return module
+}
+
+type AndroidAppCertificate struct {
+	android.ModuleBase
+	properties  AndroidAppCertificateProperties
+	certificate certificate
+}
+
+type AndroidAppCertificateProperties struct {
+	// Name of the certificate files.  Extensions .x509.pem and .pk8 will be added to the name.
+	Certificate *string
+}
+
+func AndroidAppCertificateFactory() android.Module {
+	module := &AndroidAppCertificate{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidModule(module)
+	return module
+}
+
+func (c *AndroidAppCertificate) DepsMutator(ctx android.BottomUpMutatorContext) {
+}
+
+func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	cert := String(c.properties.Certificate)
+	c.certificate = certificate{
+		android.PathForModuleSrc(ctx, cert+".x509.pem"),
+		android.PathForModuleSrc(ctx, cert+".pk8"),
+	}
+}
diff --git a/java/app_builder.go b/java/app_builder.go
index e27b1b7..b9b5f43 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -19,9 +19,11 @@
 // functions.
 
 import (
+	"path/filepath"
 	"strings"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 )
@@ -61,16 +63,18 @@
 	})
 
 func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
-	resJarFile, dexJarFile android.Path, certificates []certificate) {
-
-	// TODO(ccross): JNI libs
+	resJarFile, jniJarFile, dexJarFile android.Path, certificates []certificate) {
 
 	unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk")
 
-	inputs := android.Paths{resJarFile}
+	var inputs android.Paths
 	if dexJarFile != nil {
 		inputs = append(inputs, dexJarFile)
 	}
+	inputs = append(inputs, resJarFile)
+	if jniJarFile != nil {
+		inputs = append(inputs, jniJarFile)
+	}
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   combineApk,
@@ -132,3 +136,37 @@
 		},
 	})
 }
+
+func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.WritablePath,
+	jniLibs []jniLib) {
+
+	var deps android.Paths
+	jarArgs := []string{
+		"-j", // junk paths, they will be added back with -P arguments
+	}
+
+	if !ctx.Config().UnbundledBuild() {
+		jarArgs = append(jarArgs, "-L 0")
+	}
+
+	for _, j := range jniLibs {
+		deps = append(deps, j.path)
+		jarArgs = append(jarArgs,
+			"-P "+targetToJniDir(j.target),
+			"-f "+j.path.String())
+	}
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        zip,
+		Description: "zip jni libs",
+		Output:      outputFile,
+		Implicits:   deps,
+		Args: map[string]string{
+			"jarArgs": strings.Join(proptools.NinjaAndShellEscape(jarArgs), " "),
+		},
+	})
+}
+
+func targetToJniDir(target android.Target) string {
+	return filepath.Join("lib", target.Arch.Abi[0])
+}
diff --git a/java/app_test.go b/java/app_test.go
index c7c94ec..f6476dc 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -17,6 +17,7 @@
 import (
 	"android/soong/android"
 	"fmt"
+	"path/filepath"
 	"reflect"
 	"sort"
 	"strings"
@@ -338,3 +339,118 @@
 		}
 	}
 }
+
+func TestJNI(t *testing.T) {
+	ctx := testJava(t, `
+		toolchain_library {
+			name: "libcompiler_rt-extras",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libatomic",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libgcc",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-aarch64-android",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-arm-android",
+			src: "",
+		}
+
+		cc_object {
+			name: "crtbegin_so",
+			stl: "none",
+		}
+
+		cc_object {
+			name: "crtend_so",
+			stl: "none",
+		}
+
+		cc_library {
+			name: "libjni",
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		android_test {
+			name: "test",
+			no_framework_libs: true,
+			jni_libs: ["libjni"],
+		}
+
+		android_test {
+			name: "test_first",
+			no_framework_libs: true,
+			compile_multilib: "first",
+			jni_libs: ["libjni"],
+		}
+
+		android_test {
+			name: "test_both",
+			no_framework_libs: true,
+			compile_multilib: "both",
+			jni_libs: ["libjni"],
+		}
+
+		android_test {
+			name: "test_32",
+			no_framework_libs: true,
+			compile_multilib: "32",
+			jni_libs: ["libjni"],
+		}
+
+		android_test {
+			name: "test_64",
+			no_framework_libs: true,
+			compile_multilib: "64",
+			jni_libs: ["libjni"],
+		}
+		`)
+
+	// check the existence of the internal modules
+	ctx.ModuleForTests("test", "android_common")
+	ctx.ModuleForTests("test_first", "android_common")
+	ctx.ModuleForTests("test_both", "android_common")
+	ctx.ModuleForTests("test_32", "android_common")
+	ctx.ModuleForTests("test_64", "android_common")
+
+	testCases := []struct {
+		name string
+		abis []string
+	}{
+		{"test", []string{"arm64-v8a"}},
+		{"test_first", []string{"arm64-v8a"}},
+		{"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
+		{"test_32", []string{"armeabi-v7a"}},
+		{"test_64", []string{"arm64-v8a"}},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			app := ctx.ModuleForTests(test.name, "android_common")
+			jniLibZip := app.Output("jnilibs.zip")
+			var abis []string
+			args := strings.Fields(jniLibZip.Args["jarArgs"])
+			for i := 0; i < len(args); i++ {
+				if args[i] == "-P" {
+					abis = append(abis, filepath.Base(args[i+1]))
+					i++
+				}
+			}
+			if !reflect.DeepEqual(abis, test.abis) {
+				t.Errorf("want abis %v, got %v", test.abis, abis)
+			}
+		})
+	}
+}
diff --git a/java/builder.go b/java/builder.go
index 07af8eb..f55a7c7 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -109,6 +109,15 @@
 		},
 		"jarArgs")
 
+	zip = pctx.AndroidStaticRule("zip",
+		blueprint.RuleParams{
+			Command:        `${config.SoongZipCmd} -o $out @$out.rsp`,
+			CommandDeps:    []string{"${config.SoongZipCmd}"},
+			Rspfile:        "$out.rsp",
+			RspfileContent: "$jarArgs",
+		},
+		"jarArgs")
+
 	combineJar = pctx.AndroidStaticRule("combineJar",
 		blueprint.RuleParams{
 			Command:     `${config.MergeZipsCmd} --ignore-duplicates -j $jarArgs $out $in`,
diff --git a/java/java.go b/java/java.go
index b4b8feb..c5414f4 100644
--- a/java/java.go
+++ b/java/java.go
@@ -95,9 +95,6 @@
 	// list of java libraries that will be compiled into the resulting jar
 	Static_libs []string `android:"arch_variant"`
 
-	// list of native libraries that will be provided in or alongside the resulting jar
-	Jni_libs []string `android:"arch_variant"`
-
 	// manifest file to be included in resulting jar
 	Manifest *string
 
@@ -365,6 +362,11 @@
 	name string
 }
 
+type jniDependencyTag struct {
+	blueprint.BaseDependencyTag
+	target android.Target
+}
+
 var (
 	staticLibTag     = dependencyTag{name: "staticlib"}
 	libTag           = dependencyTag{name: "javalib"}
@@ -375,6 +377,7 @@
 	frameworkApkTag  = dependencyTag{name: "framework-apk"}
 	kotlinStdlibTag  = dependencyTag{name: "kotlin-stdlib"}
 	proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+	certificateTag   = dependencyTag{name: "certificate"}
 )
 
 type sdkDep struct {
@@ -389,6 +392,12 @@
 	aidl android.Path
 }
 
+type jniLib struct {
+	name   string
+	path   android.Path
+	target android.Target
+}
+
 func (j *Module) shouldInstrument(ctx android.BaseContext) bool {
 	return j.properties.Instrument && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
 }
@@ -597,6 +606,7 @@
 	ctx.AddFarVariationDependencies([]blueprint.Variation{
 		{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant},
 	}, annoTag, j.properties.Annotation_processors...)
+
 	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
 	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
 	android.ExtractSourcesDeps(ctx, j.properties.Java_resources)
@@ -787,6 +797,15 @@
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
+		if _, ok := tag.(*jniDependencyTag); ok {
+			// Handled by AndroidApp.collectAppDeps
+			return
+		}
+		if tag == certificateTag {
+			// Handled by AndroidApp.collectAppDeps
+			return
+		}
+
 		if to, ok := module.(*Library); ok {
 			switch tag {
 			case bootClasspathTag, libTag, staticLibTag:
diff --git a/java/java_test.go b/java/java_test.go
index 82accd5..1bfd24b 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -15,8 +15,6 @@
 package java
 
 import (
-	"android/soong/android"
-	"android/soong/genrule"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -27,6 +25,10 @@
 	"testing"
 
 	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+	"android/soong/cc"
+	"android/soong/genrule"
 )
 
 var buildDir string
@@ -73,6 +75,7 @@
 	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
 	ctx.RegisterModuleType("android_library", android.ModuleFactoryAdaptor(AndroidLibraryFactory))
+	ctx.RegisterModuleType("android_test", android.ModuleFactoryAdaptor(AndroidTestFactory))
 	ctx.RegisterModuleType("java_binary_host", android.ModuleFactoryAdaptor(BinaryHostFactory))
 	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
 	ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
@@ -95,6 +98,16 @@
 		ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
 	})
 	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
+
+	// Register module types and mutators from cc needed for JNI testing
+	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
+	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+	})
+
 	ctx.Register()
 
 	extraModules := []string{