Merge "Speed up build_test"
diff --git a/Android.bp b/Android.bp
index 5faefe6..1b93c0d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -77,6 +77,7 @@
         "android/neverallow_test.go",
         "android/paths_test.go",
         "android/prebuilt_test.go",
+        "android/prebuilt_etc_test.go",
         "android/util_test.go",
         "android/variable_test.go",
     ],
diff --git a/OWNERS b/OWNERS
index edd2557..780a35b 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
 per-file * = ccross@android.com,dwillemsen@google.com,nanzhang@google.com
 per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
 per-file clang.go,global.go,tidy.go = srhines@google.com, chh@google.com
+per-file apex.go = jiyong@google.com
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index fbc9de2..cc1f846 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -37,6 +37,9 @@
 	// optional subdirectory under which this file is installed into
 	Sub_dir *string `android:"arch_variant"`
 
+	// optional name for the installed file. If unspecified, name of the module is used as the file name
+	Filename *string `android:"arch_variant"`
+
 	// Make this module available when building for recovery.
 	Recovery_available *bool
 
@@ -95,7 +98,11 @@
 
 func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
 	p.sourceFilePath = ctx.ExpandSource(String(p.properties.Src), "src")
-	p.outputFilePath = PathForModuleOut(ctx, ctx.ModuleName()).OutputPath
+	filename := String(p.properties.Filename)
+	if filename == "" {
+		filename = ctx.ModuleName()
+	}
+	p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
 	p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir))
 
 	// This ensures that outputFilePath has the same name as this module.
@@ -120,7 +127,7 @@
 			fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
 			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.outputFilePath.String())
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
-			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name)
+			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", p.outputFilePath.Base())
 			if p.additionalDependencies != nil {
 				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
 				for _, path := range *p.additionalDependencies {
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
index 9244647..1ecdf79 100644
--- a/android/prebuilt_etc_test.go
+++ b/android/prebuilt_etc_test.go
@@ -91,3 +91,18 @@
 		t.Errorf("expected 1, got %#v", bar_variants)
 	}
 }
+
+func TestPrebuiltEtcOutputPath(t *testing.T) {
+	ctx := testPrebuiltEtc(t, `
+		prebuilt_etc {
+			name: "foo.conf",
+			src: "foo.conf",
+			filename: "foo.installed.conf",
+		}
+	`)
+
+	p := ctx.ModuleForTests("foo.conf", "android_common_core").Module().(*PrebuiltEtc)
+	if p.outputFilePath.Base() != "foo.installed.conf" {
+		t.Errorf("expected foo.installed.conf, got %q", p.outputFilePath.Base())
+	}
+}
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index b3d5aec..99b3523 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -161,24 +161,25 @@
 	addStandardProperties(bpparser.BoolType,
 		map[string]string{
 			// Bool properties
-			"LOCAL_IS_HOST_MODULE":           "host",
-			"LOCAL_CLANG":                    "clang",
-			"LOCAL_FORCE_STATIC_EXECUTABLE":  "static_executable",
-			"LOCAL_NATIVE_COVERAGE":          "native_coverage",
-			"LOCAL_NO_CRT":                   "nocrt",
-			"LOCAL_ALLOW_UNDEFINED_SYMBOLS":  "allow_undefined_symbols",
-			"LOCAL_RTTI_FLAG":                "rtti",
-			"LOCAL_NO_STANDARD_LIBRARIES":    "no_standard_libs",
-			"LOCAL_PACK_MODULE_RELOCATIONS":  "pack_relocations",
-			"LOCAL_TIDY":                     "tidy",
-			"LOCAL_USE_CLANG_LLD":            "use_clang_lld",
-			"LOCAL_PROPRIETARY_MODULE":       "proprietary",
-			"LOCAL_VENDOR_MODULE":            "vendor",
-			"LOCAL_ODM_MODULE":               "device_specific",
-			"LOCAL_PRODUCT_MODULE":           "product_specific",
-			"LOCAL_PRODUCT_SERVICES_MODULE":  "product_services_specific",
-			"LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources",
-			"LOCAL_PRIVILEGED_MODULE":        "privileged",
+			"LOCAL_IS_HOST_MODULE":             "host",
+			"LOCAL_CLANG":                      "clang",
+			"LOCAL_FORCE_STATIC_EXECUTABLE":    "static_executable",
+			"LOCAL_NATIVE_COVERAGE":            "native_coverage",
+			"LOCAL_NO_CRT":                     "nocrt",
+			"LOCAL_ALLOW_UNDEFINED_SYMBOLS":    "allow_undefined_symbols",
+			"LOCAL_RTTI_FLAG":                  "rtti",
+			"LOCAL_NO_STANDARD_LIBRARIES":      "no_standard_libs",
+			"LOCAL_PACK_MODULE_RELOCATIONS":    "pack_relocations",
+			"LOCAL_TIDY":                       "tidy",
+			"LOCAL_USE_CLANG_LLD":              "use_clang_lld",
+			"LOCAL_PROPRIETARY_MODULE":         "proprietary",
+			"LOCAL_VENDOR_MODULE":              "vendor",
+			"LOCAL_ODM_MODULE":                 "device_specific",
+			"LOCAL_PRODUCT_MODULE":             "product_specific",
+			"LOCAL_PRODUCT_SERVICES_MODULE":    "product_services_specific",
+			"LOCAL_EXPORT_PACKAGE_RESOURCES":   "export_package_resources",
+			"LOCAL_PRIVILEGED_MODULE":          "privileged",
+			"LOCAL_AAPT_INCLUDE_ALL_RESOURCES": "aapt_include_all_resources",
 
 			"LOCAL_DEX_PREOPT":                  "dex_preopt.enabled",
 			"LOCAL_DEX_PREOPT_APP_IMAGE":        "dex_preopt.app_image",
diff --git a/apex/apex.go b/apex/apex.go
index 5390114..41c7a97 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -81,7 +81,18 @@
 func init() {
 	pctx.Import("android/soong/common")
 	pctx.HostBinToolVariable("apexer", "apexer")
-	pctx.HostBinToolVariable("aapt2", "aapt2")
+	// ART minimal builds (using the master-art manifest) do not have the "frameworks/base"
+	// projects, and hence cannot built 'aapt2'. Use the SDK prebuilt instead.
+	hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) {
+		pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
+			if !android.ExistentPathForSource(ctx, "frameworks/base").Valid() {
+				return filepath.Join(prebuiltDir, runtime.GOOS, "bin", tool)
+			} else {
+				return pctx.HostBinToolPath(ctx, tool).String()
+			}
+		})
+	}
+	hostBinToolVariableWithPrebuilt("aapt2", "prebuilts/sdk/tools", "aapt2")
 	pctx.HostBinToolVariable("avbtool", "avbtool")
 	pctx.HostBinToolVariable("e2fsdroid", "e2fsdroid")
 	pctx.HostBinToolVariable("merge_zips", "merge_zips")
@@ -176,6 +187,39 @@
 
 	// Name of the apex_key module that provides the private key to sign APEX
 	Key *string
+
+	Multilib struct {
+		First struct {
+			// List of native libraries whose compile_multilib is "first"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "first"
+			Binaries []string
+		}
+		Both struct {
+			// List of native libraries whose compile_multilib is "both"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "both"
+			Binaries []string
+		}
+		Prefer32 struct {
+			// List of native libraries whose compile_multilib is "prefer32"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "prefer32"
+			Binaries []string
+		}
+		Lib32 struct {
+			// List of native libraries whose compile_multilib is "32"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "32"
+			Binaries []string
+		}
+		Lib64 struct {
+			// List of native libraries whose compile_multilib is "64"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "64"
+			Binaries []string
+		}
+	}
 }
 
 type apexBundle struct {
@@ -188,22 +232,83 @@
 	installDir android.OutputPath
 }
 
+func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
+	native_shared_libs []string, binaries []string, arch string) {
+	// Use *FarVariation* to be able to depend on modules having
+	// conflicting variations with this module. This is required since
+	// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
+	// for native shared libs.
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: arch},
+		{Mutator: "image", Variation: "core"},
+		{Mutator: "link", Variation: "shared"},
+	}, sharedLibTag, native_shared_libs...)
+
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: arch},
+		{Mutator: "image", Variation: "core"},
+	}, executableTag, binaries...)
+}
+
 func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
-	for _, arch := range ctx.MultiTargets() {
-		// Use *FarVariation* to be able to depend on modules having
-		// conflicting variations with this module. This is required since
-		// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
-		// for native shared libs.
+	targets := ctx.MultiTargets()
+	has32BitTarget := false
+	for _, target := range targets {
+		if target.Arch.ArchType.Multilib == "lib32" {
+			has32BitTarget = true
+		}
+	}
+	for i, target := range targets {
+		// When multilib.* is omitted for native_shared_libs, it implies
+		// multilib.both.
 		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: arch.String()},
+			{Mutator: "arch", Variation: target.String()},
 			{Mutator: "image", Variation: "core"},
 			{Mutator: "link", Variation: "shared"},
 		}, sharedLibTag, a.properties.Native_shared_libs...)
 
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: arch.String()},
-			{Mutator: "image", Variation: "core"},
-		}, executableTag, a.properties.Binaries...)
+		// Add native modules targetting both ABIs
+		addDependenciesForNativeModules(ctx,
+			a.properties.Multilib.Both.Native_shared_libs,
+			a.properties.Multilib.Both.Binaries, target.String())
+
+		if i == 0 {
+			// When multilib.* is omitted for binaries, it implies
+			// multilib.first.
+			ctx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "arch", Variation: target.String()},
+				{Mutator: "image", Variation: "core"},
+			}, executableTag, a.properties.Binaries...)
+
+			// Add native modules targetting the first ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.First.Native_shared_libs,
+				a.properties.Multilib.First.Binaries, target.String())
+		}
+
+		switch target.Arch.ArchType.Multilib {
+		case "lib32":
+			// Add native modules targetting 32-bit ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Lib32.Native_shared_libs,
+				a.properties.Multilib.Lib32.Binaries, target.String())
+
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Prefer32.Native_shared_libs,
+				a.properties.Multilib.Prefer32.Binaries, target.String())
+		case "lib64":
+			// Add native modules targetting 64-bit ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Lib64.Native_shared_libs,
+				a.properties.Multilib.Lib64.Binaries, target.String())
+
+			if !has32BitTarget {
+				addDependenciesForNativeModules(ctx,
+					a.properties.Multilib.Prefer32.Native_shared_libs,
+					a.properties.Multilib.Prefer32.Binaries, target.String())
+			}
+		}
+
 	}
 
 	ctx.AddFarVariationDependencies([]blueprint.Variation{
@@ -407,6 +512,10 @@
 func apexBundleFactory() android.Module {
 	module := &apexBundle{}
 	module.AddProperties(&module.properties)
+	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase,
+		class android.OsClass) bool {
+		return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
+	})
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	return module
diff --git a/cc/cc.go b/cc/cc.go
index 8b68489..0569563 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -39,6 +39,7 @@
 		ctx.BottomUp("vndk", vndkMutator).Parallel()
 		ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
+		ctx.BottomUp("version", versionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
 
@@ -945,6 +946,16 @@
 	c.begin(ctx)
 }
 
+// Split name#version into name and version
+func stubsLibNameAndVersion(name string) (string, string) {
+	if sharp := strings.LastIndex(name, "#"); sharp != -1 && sharp != len(name)-1 {
+		version := name[sharp+1:]
+		libname := name[:sharp]
+		return libname, version
+	}
+	return name, ""
+}
+
 func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
 	ctx := &depsContext{
 		BottomUpMutatorContext: actx,
@@ -979,25 +990,28 @@
 			variantLibs = []string{}
 			nonvariantLibs = []string{}
 			for _, entry := range list {
-				if ctx.useSdk() && inList(entry, ndkPrebuiltSharedLibraries) {
-					if !inList(entry, ndkMigratedLibs) {
-						nonvariantLibs = append(nonvariantLibs, entry+".ndk."+version)
+				// strip #version suffix out
+				name, _ := stubsLibNameAndVersion(entry)
+				if ctx.useSdk() && inList(name, ndkPrebuiltSharedLibraries) {
+					if !inList(name, ndkMigratedLibs) {
+						nonvariantLibs = append(nonvariantLibs, name+".ndk."+version)
 					} else {
-						variantLibs = append(variantLibs, entry+ndkLibrarySuffix)
+						variantLibs = append(variantLibs, name+ndkLibrarySuffix)
 					}
-				} else if ctx.useVndk() && inList(entry, llndkLibraries) {
-					nonvariantLibs = append(nonvariantLibs, entry+llndkLibrarySuffix)
-				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(entry, vendorPublicLibraries) {
-					vendorPublicLib := entry + vendorPublicLibrarySuffix
+				} else if ctx.useVndk() && inList(name, llndkLibraries) {
+					nonvariantLibs = append(nonvariantLibs, name+llndkLibrarySuffix)
+				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, vendorPublicLibraries) {
+					vendorPublicLib := name + vendorPublicLibrarySuffix
 					if actx.OtherModuleExists(vendorPublicLib) {
 						nonvariantLibs = append(nonvariantLibs, vendorPublicLib)
 					} else {
 						// This can happen if vendor_public_library module is defined in a
 						// namespace that isn't visible to the current module. In that case,
 						// link to the original library.
-						nonvariantLibs = append(nonvariantLibs, entry)
+						nonvariantLibs = append(nonvariantLibs, name)
 					}
 				} else {
+					// put name#version back
 					nonvariantLibs = append(nonvariantLibs, entry)
 				}
 			}
@@ -1009,6 +1023,15 @@
 		deps.ReexportSharedLibHeaders, _ = rewriteNdkLibs(deps.ReexportSharedLibHeaders)
 	}
 
+	if c.linker != nil {
+		if library, ok := c.linker.(*libraryDecorator); ok {
+			if library.buildStubs() {
+				// Stubs lib does not have dependency to other libraries. Don't proceed.
+				return
+			}
+		}
+	}
+
 	for _, lib := range deps.HeaderLibs {
 		depTag := headerDepTag
 		if inList(lib, deps.ReexportHeaderLibHeaders) {
@@ -1035,19 +1058,40 @@
 		{Mutator: "link", Variation: "static"},
 	}, lateStaticDepTag, deps.LateStaticLibs...)
 
+	// shared lib names without the #version suffix
+	var sharedLibNames []string
+
 	for _, lib := range deps.SharedLibs {
+		name, version := stubsLibNameAndVersion(lib)
+		sharedLibNames = append(sharedLibNames, name)
 		depTag := sharedDepTag
 		if inList(lib, deps.ReexportSharedLibHeaders) {
 			depTag = sharedExportDepTag
 		}
-		actx.AddVariationDependencies([]blueprint.Variation{
-			{Mutator: "link", Variation: "shared"},
-		}, depTag, lib)
+		var variations []blueprint.Variation
+		variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
+		if version != "" && ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery() {
+			variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
+		}
+		actx.AddVariationDependencies(variations, depTag, name)
 	}
 
-	actx.AddVariationDependencies([]blueprint.Variation{
-		{Mutator: "link", Variation: "shared"},
-	}, lateSharedDepTag, deps.LateSharedLibs...)
+	for _, lib := range deps.LateSharedLibs {
+		name, version := stubsLibNameAndVersion(lib)
+		if inList(name, sharedLibNames) {
+			// This is to handle the case that some of the late shared libs (libc, libdl, libm, ...)
+			// are added also to SharedLibs with version (e.g., libc#10). If not skipped, we will be
+			// linking against both the stubs lib and the non-stubs lib at the same time.
+			continue
+		}
+		depTag := lateSharedDepTag
+		var variations []blueprint.Variation
+		variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
+		if version != "" && ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery() {
+			variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
+		}
+		actx.AddVariationDependencies(variations, depTag, name)
+	}
 
 	actx.AddVariationDependencies([]blueprint.Variation{
 		{Mutator: "link", Variation: "shared"},
@@ -1629,8 +1673,8 @@
 		return
 	}
 
-	if genrule, ok := mctx.Module().(*genrule.Module); ok {
-		if props, ok := genrule.Extra.(*GenruleExtraProperties); ok {
+	if g, ok := mctx.Module().(*genrule.Module); ok {
+		if props, ok := g.Extra.(*GenruleExtraProperties); ok {
 			var coreVariantNeeded bool = false
 			var vendorVariantNeeded bool = false
 			var recoveryVariantNeeded bool = false
@@ -1650,7 +1694,7 @@
 
 			if recoveryVariantNeeded {
 				primaryArch := mctx.Config().DevicePrimaryArchType()
-				moduleArch := genrule.Target().Arch.ArchType
+				moduleArch := g.Target().Arch.ArchType
 				if moduleArch != primaryArch {
 					recoveryVariantNeeded = false
 				}
@@ -1666,7 +1710,13 @@
 			if recoveryVariantNeeded {
 				variants = append(variants, recoveryMode)
 			}
-			mctx.CreateVariations(variants...)
+			mod := mctx.CreateVariations(variants...)
+			for i, v := range variants {
+				if v == recoveryMode {
+					m := mod[i].(*genrule.Module)
+					m.Extra.(*GenruleExtraProperties).InRecovery = true
+				}
+			}
 		}
 	}
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index ead89f6..fba38a2 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -66,6 +66,7 @@
 		ctx.BottomUp("image", imageMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
 		ctx.BottomUp("vndk", vndkMutator).Parallel()
+		ctx.BottomUp("version", versionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
 	ctx.Register()
@@ -205,12 +206,13 @@
 `
 
 	ctx.MockFileSystem(map[string][]byte{
-		"Android.bp": []byte(bp),
-		"foo.c":      nil,
-		"bar.c":      nil,
-		"a.proto":    nil,
-		"b.aidl":     nil,
-		"my_include": nil,
+		"Android.bp":  []byte(bp),
+		"foo.c":       nil,
+		"bar.c":       nil,
+		"a.proto":     nil,
+		"b.aidl":      nil,
+		"my_include":  nil,
+		"foo.map.txt": nil,
 	})
 
 	return ctx
@@ -1730,5 +1732,58 @@
 	if !recoveryModule.Platform() {
 		t.Errorf("recovery variant of libHalInRecovery must not specific to device, soc, or product")
 	}
+}
 
+func TestVersionedStubs(t *testing.T) {
+	ctx := testCc(t, `
+		cc_library_shared {
+			name: "libFoo",
+			stubs: {
+				symbol_file: "foo.map.txt",
+				versions: ["1", "2", "3"],
+			},
+		}
+		cc_library_shared {
+			name: "libBar",
+			shared_libs: ["libFoo#1"],
+		}`)
+
+	variants := ctx.ModuleVariantsForTests("libFoo")
+	expectedVariants := []string{
+		"android_arm64_armv8-a_core_shared",
+		"android_arm64_armv8-a_core_shared_1",
+		"android_arm64_armv8-a_core_shared_2",
+		"android_arm64_armv8-a_core_shared_3",
+		"android_arm_armv7-a-neon_core_shared",
+		"android_arm_armv7-a-neon_core_shared_1",
+		"android_arm_armv7-a-neon_core_shared_2",
+		"android_arm_armv7-a-neon_core_shared_3",
+	}
+	variantsMismatch := false
+	if len(variants) != len(expectedVariants) {
+		variantsMismatch = true
+	} else {
+		for _, v := range expectedVariants {
+			if !inList(v, variants) {
+				variantsMismatch = false
+			}
+		}
+	}
+	if variantsMismatch {
+		t.Errorf("variants of libFoo expected:\n")
+		for _, v := range expectedVariants {
+			t.Errorf("%q\n", v)
+		}
+		t.Errorf(", but got:\n")
+		for _, v := range variants {
+			t.Errorf("%q\n", v)
+		}
+	}
+
+	libBarLinkRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_core_shared").Rule("ld")
+	libFlags := libBarLinkRule.Args["libFlags"]
+	libFoo1StubPath := "libFoo/android_arm64_armv8-a_core_shared_1/libFoo.so"
+	if !strings.Contains(libFlags, libFoo1StubPath) {
+		t.Errorf("%q is not found in %q", libFoo1StubPath, libFlags)
+	}
 }
diff --git a/cc/genrule.go b/cc/genrule.go
index a672992..decf6ea 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -26,6 +26,9 @@
 type GenruleExtraProperties struct {
 	Vendor_available   *bool
 	Recovery_available *bool
+
+	// This genrule is for recovery variant
+	InRecovery bool `blueprint:"mutated"`
 }
 
 // cc_genrule is a genrule that can depend on other cc_* objects.
diff --git a/cc/library.go b/cc/library.go
index 920292d..aafe365 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -22,6 +22,7 @@
 
 	"android/soong/android"
 	"android/soong/cc/config"
+	"android/soong/genrule"
 )
 
 type LibraryProperties struct {
@@ -65,6 +66,15 @@
 	}
 
 	Static_ndk_lib *bool
+
+	Stubs struct {
+		// Relative path to the symbol map. The symbol map provides the list of
+		// symbols that are exported for stubs variant of this library.
+		Symbol_file *string
+
+		// List versions to generate stubs libs for.
+		Versions []string
+	}
 }
 
 type LibraryMutatedProperties struct {
@@ -78,6 +88,11 @@
 	VariantIsShared bool `blueprint:"mutated"`
 	// This variant is static
 	VariantIsStatic bool `blueprint:"mutated"`
+
+	// This variant is a stubs lib
+	BuildStubs bool `blueprint:"mutated"`
+	// Version of the stubs lib
+	StubsVersion string `blueprint:"mutated"`
 }
 
 type FlagExporterProperties struct {
@@ -240,6 +255,8 @@
 	// Location of the linked, unstripped library for shared libraries
 	unstrippedOutputFile android.Path
 
+	versionScriptPath android.ModuleGenPath
+
 	// Decorated interafaces
 	*baseCompiler
 	*baseLinker
@@ -313,7 +330,11 @@
 		flags.YasmFlags = append(flags.YasmFlags, f)
 	}
 
-	return library.baseCompiler.compilerFlags(ctx, flags, deps)
+	flags = library.baseCompiler.compilerFlags(ctx, flags, deps)
+	if library.buildStubs() {
+		flags = addStubLibraryCompilerFlags(flags)
+	}
+	return flags
 }
 
 func extractExportIncludesFromFlags(flags []string) []string {
@@ -336,6 +357,12 @@
 }
 
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
+	if library.buildStubs() {
+		objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "")
+		library.versionScriptPath = versionScript
+		return objs
+	}
+
 	if !library.buildShared() && !library.buildStatic() {
 		if len(library.baseCompiler.Properties.Srcs) > 0 {
 			ctx.PropertyErrorf("srcs", "cc_library_headers must not have any srcs")
@@ -422,8 +449,10 @@
 		location = InstallInSanitizerDir
 	}
 	library.baseInstaller.location = location
-
 	library.baseLinker.linkerInit(ctx)
+	// Let baseLinker know whether this variant is for stubs or not, so that
+	// it can omit things that are not required for linking stubs.
+	library.baseLinker.dynamicProperties.BuildStubs = library.buildStubs()
 }
 
 func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
@@ -735,7 +764,8 @@
 
 	if Bool(library.Properties.Static_ndk_lib) && library.static() &&
 		!ctx.useVndk() && !ctx.inRecovery() && ctx.Device() &&
-		library.baseLinker.sanitize.isUnsanitizedVariant() {
+		library.baseLinker.sanitize.isUnsanitizedVariant() &&
+		!library.buildStubs() {
 		installPath := getNdkSysrootBase(ctx).Join(
 			ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base())
 
@@ -785,6 +815,14 @@
 	library.MutatedProperties.BuildStatic = false
 }
 
+func (library *libraryDecorator) buildStubs() bool {
+	return library.MutatedProperties.BuildStubs
+}
+
+func (library *libraryDecorator) stubsVersion() string {
+	return library.MutatedProperties.StubsVersion
+}
+
 func NewLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
 	module := newModule(hod, android.MultilibBoth)
 
@@ -847,3 +885,41 @@
 		}
 	}
 }
+
+// Version mutator splits a module into the mandatory non-stubs variant
+// (which is named "impl") and zero or more stubs variants.
+func versionMutator(mctx android.BottomUpMutatorContext) {
+	if mctx.Os() != android.Android {
+		return
+	}
+
+	if m, ok := mctx.Module().(*Module); ok && !m.inRecovery() && m.linker != nil {
+		if library, ok := m.linker.(*libraryDecorator); ok && library.buildShared() {
+			versions := []string{""}
+			for _, v := range library.Properties.Stubs.Versions {
+				versions = append(versions, v)
+			}
+			modules := mctx.CreateVariations(versions...)
+			for i, m := range modules {
+				l := m.(*Module).linker.(*libraryDecorator)
+				if i == 0 {
+					l.MutatedProperties.BuildStubs = false
+					continue
+				}
+				// Mark that this variant is for stubs.
+				l.MutatedProperties.BuildStubs = true
+				l.MutatedProperties.StubsVersion = versions[i]
+				m.(*Module).Properties.HideFromMake = true
+			}
+		} else {
+			mctx.CreateVariations("")
+		}
+		return
+	}
+	if genrule, ok := mctx.Module().(*genrule.Module); ok {
+		if props, ok := genrule.Extra.(*GenruleExtraProperties); ok && !props.InRecovery {
+			mctx.CreateVariations("")
+			return
+		}
+	}
+}
diff --git a/cc/linker.go b/cc/linker.go
index 28f4747..e96bfcb 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -160,7 +160,8 @@
 	Properties        BaseLinkerProperties
 	MoreProperties    MoreBaseLinkerProperties
 	dynamicProperties struct {
-		RunPaths []string `blueprint:"mutated"`
+		RunPaths   []string `blueprint:"mutated"`
+		BuildStubs bool     `blueprint:"mutated"`
 	}
 
 	sanitize *sanitize
@@ -269,9 +270,13 @@
 		deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread")
 	}
 
-	android.ExtractSourceDeps(ctx, linker.MoreProperties.Version_script)
-	android.ExtractSourceDeps(ctx,
-		linker.MoreProperties.Target.Vendor.Version_script)
+	// Version_script is not needed when linking stubs lib where the version
+	// script is created from the symbol map file.
+	if !linker.dynamicProperties.BuildStubs {
+		android.ExtractSourceDeps(ctx, linker.MoreProperties.Version_script)
+		android.ExtractSourceDeps(ctx,
+			linker.MoreProperties.Target.Vendor.Version_script)
+	}
 
 	return deps
 }
@@ -375,28 +380,32 @@
 		flags.GroupStaticLibs = true
 	}
 
-	versionScript := ctx.ExpandOptionalSource(
-		linker.MoreProperties.Version_script, "version_script")
+	// Version_script is not needed when linking stubs lib where the version
+	// script is created from the symbol map file.
+	if !linker.dynamicProperties.BuildStubs {
+		versionScript := ctx.ExpandOptionalSource(
+			linker.MoreProperties.Version_script, "version_script")
 
-	if ctx.useVndk() && linker.MoreProperties.Target.Vendor.Version_script != nil {
-		versionScript = ctx.ExpandOptionalSource(
-			linker.MoreProperties.Target.Vendor.Version_script,
-			"target.vendor.version_script")
-	}
+		if ctx.useVndk() && linker.MoreProperties.Target.Vendor.Version_script != nil {
+			versionScript = ctx.ExpandOptionalSource(
+				linker.MoreProperties.Target.Vendor.Version_script,
+				"target.vendor.version_script")
+		}
 
-	if versionScript.Valid() {
-		if ctx.Darwin() {
-			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
-		} else {
-			flags.LdFlags = append(flags.LdFlags,
-				"-Wl,--version-script,"+versionScript.String())
-			flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
-
-			if linker.sanitize.isSanitizerEnabled(cfi) {
-				cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+		if versionScript.Valid() {
+			if ctx.Darwin() {
+				ctx.PropertyErrorf("version_script", "Not supported on Darwin")
+			} else {
 				flags.LdFlags = append(flags.LdFlags,
-					"-Wl,--version-script,"+cfiExportsMap.String())
-				flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
+					"-Wl,--version-script,"+versionScript.String())
+				flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
+
+				if linker.sanitize.isSanitizerEnabled(cfi) {
+					cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+					flags.LdFlags = append(flags.LdFlags,
+						"-Wl,--version-script,"+cfiExportsMap.String())
+					flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
+				}
 			}
 		}
 	}
diff --git a/java/aar.go b/java/aar.go
index a06d191..3ab07cc 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -47,6 +47,10 @@
 	// flags passed to aapt when creating the apk
 	Aaptflags []string
 
+	// include all resource configurations, not just the product-configured
+	// ones.
+	Aapt_include_all_resources *bool
+
 	// list of directories relative to the Blueprints file containing assets.
 	// Defaults to "assets"
 	Asset_dirs []string
diff --git a/java/app.go b/java/app.go
index d1b04c3..db6c15c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -154,7 +154,6 @@
 	strip = ctx.Config().DefaultStripDex()
 	// TODO(ccross): don't strip dex installed on partitions that may be updated separately (like vendor)
 	// TODO(ccross): don't strip dex on modules with LOCAL_APK_LIBRARIES equivalent
-	// TODO(ccross): don't strip dex on modules that are preopted to system_other
 
 	// Uncompress dex in APKs of privileged apps, and modules used by privileged apps.
 	if ctx.Config().UncompressPrivAppDex() &&
@@ -174,6 +173,9 @@
 		strip = false
 	}
 
+	// TODO(ccross): strip dexpropted modules that are not propted to system_other
+	strip = false
+
 	return uncompress, strip
 }
 
@@ -192,14 +194,16 @@
 		linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
 	}
 
-	// Product AAPT config
-	for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
-		linkFlags = append(linkFlags, "-c", aaptConfig)
-	}
+	if !Bool(a.aaptProperties.Aapt_include_all_resources) {
+		// Product AAPT config
+		for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
+			linkFlags = append(linkFlags, "-c", aaptConfig)
+		}
 
-	// Product AAPT preferred config
-	if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
-		linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+		// Product AAPT preferred config
+		if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
+			linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+		}
 	}
 
 	// TODO: LOCAL_PACKAGE_OVERRIDES
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index c4fcc20..e846b03 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -122,7 +122,6 @@
 	"rm":        Allowed,
 	"rmdir":     Allowed,
 	"rsync":     Allowed,
-	"runalarm":  Allowed,
 	"sed":       Allowed,
 	"setsid":    Allowed,
 	"sh":        Allowed,
@@ -135,6 +134,7 @@
 	"tar":       Allowed,
 	"tail":      Allowed,
 	"tee":       Allowed,
+	"timeout":   Allowed,
 	"todos":     Allowed,
 	"touch":     Allowed,
 	"tr":        Allowed,