Merge "Remove libselinux from the apex_available whitelist"
diff --git a/Android.bp b/Android.bp
index 78ec9d8..9c2bb43 100644
--- a/Android.bp
+++ b/Android.bp
@@ -143,8 +143,6 @@
         "cc/config/arm_device.go",
         "cc/config/arm64_device.go",
         "cc/config/arm64_fuchsia_device.go",
-        "cc/config/mips_device.go",
-        "cc/config/mips64_device.go",
         "cc/config/x86_device.go",
         "cc/config/x86_64_device.go",
         "cc/config/x86_64_fuchsia_device.go",
diff --git a/android/apex.go b/android/apex.go
index a4de6dd..eabe059 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -21,13 +21,14 @@
 	"sync"
 )
 
+const (
+	SdkVersion_Android10 = 29
+)
+
 type ApexInfo struct {
 	// Name of the apex variant that this module is mutated into
 	ApexName string
 
-	// Whether this apex variant needs to target Android 10
-	LegacyAndroid10Support bool
-
 	MinSdkVersion int
 }
 
@@ -168,7 +169,7 @@
 
 const (
 	AvailableToPlatform = "//apex_available:platform"
-	availableToAnyApex  = "//apex_available:anyapex"
+	AvailableToAnyApex  = "//apex_available:anyapex"
 )
 
 func CheckAvailableForApex(what string, apex_available []string) bool {
@@ -178,7 +179,7 @@
 		return what == AvailableToPlatform
 	}
 	return InList(what, apex_available) ||
-		(what != AvailableToPlatform && InList(availableToAnyApex, apex_available))
+		(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available))
 }
 
 func (m *ApexModuleBase) AvailableFor(what string) bool {
@@ -207,12 +208,12 @@
 }
 
 func (m *ApexModuleBase) ShouldSupportAndroid10() bool {
-	return !m.IsForPlatform() && (m.ApexProperties.Info.MinSdkVersion <= 29 || m.ApexProperties.Info.LegacyAndroid10Support)
+	return !m.IsForPlatform() && (m.ApexProperties.Info.MinSdkVersion <= SdkVersion_Android10)
 }
 
 func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
 	for _, n := range m.ApexProperties.Apex_available {
-		if n == AvailableToPlatform || n == availableToAnyApex {
+		if n == AvailableToPlatform || n == AvailableToAnyApex {
 			continue
 		}
 		if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
diff --git a/android/arch.go b/android/arch.go
index e440486..08c0256 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -33,8 +33,6 @@
 
 	Arm    = newArch("arm", "lib32")
 	Arm64  = newArch("arm64", "lib64")
-	Mips   = newArch("mips", "lib32")
-	Mips64 = newArch("mips64", "lib64")
 	X86    = newArch("x86", "lib32")
 	X86_64 = newArch("x86_64", "lib64")
 
@@ -46,8 +44,6 @@
 var archTypeMap = map[string]ArchType{
 	"arm":    Arm,
 	"arm64":  Arm64,
-	"mips":   Mips,
-	"mips64": Mips64,
 	"x86":    X86,
 	"x86_64": X86_64,
 }
@@ -64,12 +60,6 @@
         arm64: {
             // Host or device variants with arm64 architecture
         },
-        mips: {
-            // Host or device variants with mips architecture
-        },
-        mips64: {
-            // Host or device variants with mips64 architecture
-        },
         x86: {
             // Host or device variants with x86 architecture
         },
@@ -145,18 +135,6 @@
 		"exynos-m1",
 		"exynos-m2",
 	},
-	Mips: {
-		"mips32_fp",
-		"mips32r2_fp",
-		"mips32r2_fp_xburst",
-		"mips32r2dsp_fp",
-		"mips32r2dspr2_fp",
-		"mips32r6",
-	},
-	Mips64: {
-		"mips64r2",
-		"mips64r6",
-	},
 	X86: {
 		"amberlake",
 		"atom",
@@ -193,15 +171,6 @@
 	Arm: {
 		"neon",
 	},
-	Mips: {
-		"dspr2",
-		"rev6",
-		"msa",
-	},
-	Mips64: {
-		"rev6",
-		"msa",
-	},
 	X86: {
 		"ssse3",
 		"sse4",
@@ -239,19 +208,6 @@
 			"neon",
 		},
 	},
-	Mips: {
-		"mips32r2dspr2_fp": {
-			"dspr2",
-		},
-		"mips32r6": {
-			"rev6",
-		},
-	},
-	Mips64: {
-		"mips64r6": {
-			"rev6",
-		},
-	},
 	X86: {
 		"amberlake": {
 			"ssse3",
@@ -616,7 +572,7 @@
 		LinuxBionic: []ArchType{X86_64},
 		Darwin:      []ArchType{X86_64},
 		Windows:     []ArchType{X86, X86_64},
-		Android:     []ArchType{Arm, Arm64, Mips, Mips64, X86, X86_64},
+		Android:     []ArchType{Arm, Arm64, X86, X86_64},
 		Fuchsia:     []ArchType{Arm64, X86_64},
 	}
 )
@@ -1656,15 +1612,6 @@
 		{"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
 		{"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
 		{"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}},
-		{"mips", "mips32-fp", "", []string{"mips"}},
-		{"mips", "mips32r2-fp", "", []string{"mips"}},
-		{"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
-		//{"mips", "mips32r6", "", []string{"mips"}},
-		{"mips", "mips32r2dsp-fp", "", []string{"mips"}},
-		{"mips", "mips32r2dspr2-fp", "", []string{"mips"}},
-		// mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc
-		//{"mips64", "mips64r2", "", []string{"mips64"}},
-		{"mips64", "mips64r6", "", []string{"mips64"}},
 		{"x86", "", "", []string{"x86"}},
 		{"x86", "atom", "", []string{"x86"}},
 		{"x86", "haswell", "", []string{"x86"}},
diff --git a/android/config.go b/android/config.go
index 9b1297c..bbbe3c8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -863,16 +863,7 @@
 }
 
 func (c *config) LibartImgDeviceBaseAddress() string {
-	archType := Common
-	if len(c.Targets[Android]) > 0 {
-		archType = c.Targets[Android][0].Arch.ArchType
-	}
-	switch archType {
-	default:
-		return "0x70000000"
-	case Mips, Mips64:
-		return "0x5C000000"
-	}
+	return "0x70000000"
 }
 
 func (c *config) ArtUseReadBarrier() bool {
diff --git a/android/sdk.go b/android/sdk.go
index 969e21a..5c7b329 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -186,9 +186,33 @@
 	// is correctly output for both versioned and unversioned prebuilts in the
 	// snapshot.
 	//
+	// "required: true" means that the property must only contain references
+	// to other members of the sdk. Passing a reference to a module that is not a
+	// member of the sdk will result in a build error.
+	//
+	// "required: false" means that the property can contain references to modules
+	// that are either members or not members of the sdk. If a reference is to a
+	// module that is a non member then the reference is left unchanged, i.e. it
+	// is not transformed as references to members are.
+	//
+	// The handling of the member names is dependent on whether it is an internal or
+	// exported member. An exported member is one whose name is specified in one of
+	// the member type specific properties. An internal member is one that is added
+	// due to being a part of an exported (or other internal) member and is not itself
+	// an exported member.
+	//
+	// Member names are handled as follows:
+	// * When creating the unversioned form of the module the name is left unchecked
+	//   unless the member is internal in which case it is transformed into an sdk
+	//   specific name, i.e. by prefixing with the sdk name.
+	//
+	// * When creating the versioned form of the module the name is transformed into
+	//   a versioned sdk specific name, i.e. by prefixing with the sdk name and
+	//   suffixing with the version.
+	//
 	// e.g.
-	// bpPropertySet.AddPropertyWithTag("libs", []string{"member1", "member2"}, builder.SdkMemberReferencePropertyTag())
-	SdkMemberReferencePropertyTag() BpPropertyTag
+	// bpPropertySet.AddPropertyWithTag("libs", []string{"member1", "member2"}, builder.SdkMemberReferencePropertyTag(true))
+	SdkMemberReferencePropertyTag(required bool) BpPropertyTag
 }
 
 type BpPropertyTag interface{}
@@ -325,21 +349,15 @@
 	//
 	// * The variant property structs are analysed to find exported (capitalized) fields which
 	//   have common values. Those fields are cleared and the common value added to the common
-	//   properties.
+	//   properties. A field annotated with a tag of `sdk:"keep"` will be treated as if it
+	//   was not capitalized, i.e. not optimized for common values.
 	//
 	// * The sdk module type populates the BpModule structure, creating the arch specific
 	//   structure and calls AddToPropertySet(...) on the properties struct to add the member
 	//   specific properties in the correct place in the structure.
 	//
-	// * Finally, the FinalizeModule(...) method is called to add any additional properties.
-	//   This was created to allow the property ordering in existing tests to be maintained so
-	//   as to avoid having to change tests while refactoring.
-	//
 	AddPrebuiltModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) BpModule
 
-	// Add any additional properties to the end of the module.
-	FinalizeModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember, bpModule BpModule)
-
 	// Create a structure into which variant specific properties can be added.
 	CreateVariantPropertiesStruct() SdkMemberProperties
 }
@@ -372,10 +390,6 @@
 	return nil
 }
 
-func (b *SdkMemberTypeBase) FinalizeModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember, module BpModule) {
-	// Do nothing by default
-}
-
 func (b *SdkMemberTypeBase) CreateVariantPropertiesStruct() SdkMemberProperties {
 	panic("override me")
 }
@@ -452,13 +466,13 @@
 // are not affected by the optimization to extract common values.
 type SdkMemberPropertiesBase struct {
 	// The setting to use for the compile_multilib property.
-	Compile_multilib string
+	Compile_multilib string `sdk:"keep"`
 
 	// The number of unique os types supported by the member variants.
-	Os_count int
+	Os_count int `sdk:"keep"`
 
 	// The os type for which these properties refer.
-	Os OsType
+	Os OsType `sdk:"keep"`
 }
 
 // The os prefix to use for any file paths in the sdk.
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index b7c54b1..f863f8d 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -829,8 +829,6 @@
 var propertyPrefixes = []struct{ mk, bp string }{
 	{"arm", "arch.arm"},
 	{"arm64", "arch.arm64"},
-	{"mips", "arch.mips"},
-	{"mips64", "arch.mips64"},
 	{"x86", "arch.x86"},
 	{"x86_64", "arch.x86_64"},
 	{"32", "multilib.lib32"},
diff --git a/apex/apex.go b/apex/apex.go
index 04d1bd1..46aaa8b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -63,8 +63,26 @@
 	usesTag        = dependencyTag{name: "uses"}
 	androidAppTag  = dependencyTag{name: "androidApp", payload: true}
 	apexAvailWl    = makeApexAvailableWhitelist()
+
+	inverseApexAvailWl = invertApexWhiteList(apexAvailWl)
 )
 
+// Transform the map of apex -> modules to module -> apexes.
+func invertApexWhiteList(m map[string][]string) map[string][]string {
+	r := make(map[string][]string)
+	for apex, modules := range m {
+		for _, module := range modules {
+			r[module] = append(r[module], apex)
+		}
+	}
+	return r
+}
+
+// Retrieve the while list of apexes to which the supplied module belongs.
+func WhitelistedApexAvailable(moduleName string) []string {
+	return inverseApexAvailWl[normalizeModuleName(moduleName)]
+}
+
 // This is a map from apex to modules, which overrides the
 // apex_available setting for that particular module to make
 // it available for the apex regardless of its setting.
@@ -962,7 +980,7 @@
 	//
 	// Module separator
 	//
-	m["//any"] = []string{
+	m[android.AvailableToAnyApex] = []string{
 		"crtbegin_dynamic",
 		"crtbegin_dynamic1",
 		"crtbegin_so",
@@ -1039,11 +1057,9 @@
 	var apexBundles []android.ApexInfo
 	var directDep bool
 	if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
-		minSdkVersion := a.minSdkVersion(mctx)
 		apexBundles = []android.ApexInfo{android.ApexInfo{
-			ApexName:               mctx.ModuleName(),
-			LegacyAndroid10Support: proptools.Bool(a.properties.Legacy_android10_support),
-			MinSdkVersion:          minSdkVersion,
+			ApexName:      mctx.ModuleName(),
+			MinSdkVersion: a.minSdkVersion(mctx),
 		}}
 		directDep = true
 	} else if am, ok := mctx.Module().(android.ApexModule); ok {
@@ -1287,10 +1303,6 @@
 	// Should be only used in tests#.
 	Test_only_no_hashtree *bool
 
-	// Whether this APEX should support Android10. Default is false. If this is set true, then apex_manifest.json is bundled as well
-	// because Android10 requires legacy apex_manifest.json instead of apex_manifest.pb
-	Legacy_android10_support *bool
-
 	IsCoverageVariant bool `blueprint:"mutated"`
 
 	// Whether this APEX is considered updatable or not. When set to true, this will enforce additional
@@ -1339,6 +1351,10 @@
 
 	// Logging Parent value
 	Logging_parent string
+
+	// Apex Container Package Name.
+	// Override value for attribute package:name in AndroidManifest.xml
+	Package_name string
 }
 
 type apexPackaging int
@@ -2393,6 +2409,21 @@
 
 func whitelistedApexAvailable(apex, moduleName string) bool {
 	key := apex
+	moduleName = normalizeModuleName(moduleName)
+
+	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+		return true
+	}
+
+	key = android.AvailableToAnyApex
+	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+		return true
+	}
+
+	return false
+}
+
+func normalizeModuleName(moduleName string) string {
 	// Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build
 	// system. Trim the prefix for the check since they are confusing
 	moduleName = strings.TrimPrefix(moduleName, "prebuilt_")
@@ -2401,17 +2432,7 @@
 		// We don't want to list them all
 		moduleName = "libclang_rt"
 	}
-
-	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
-		return true
-	}
-
-	key = "//any"
-	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
-		return true
-	}
-
-	return false
+	return moduleName
 }
 
 func newApexBundle() *apexBundle {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1f395b6..babc27b 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1763,6 +1763,7 @@
 			name: "otherapex",
 			key: "myapex.key",
 			native_shared_libs: ["mylib", "mylib2"],
+			min_sdk_version: "29",
 		}
 
 		apex_key {
@@ -1797,15 +1798,18 @@
 	// non-APEX variant does not have __ANDROID_APEX__ defined
 	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+	ensureContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=10000")
 
-	// APEX variant has __ANDROID_APEX__ defined
+	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
 	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+	ensureContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=10000")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
 
-	// APEX variant has __ANDROID_APEX__ defined
+	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
 	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+	ensureContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=29")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
 
 	// When cc_library sets use_apex_name_macro: true
@@ -3660,6 +3664,7 @@
 			apps: ["override_app"],
 			overrides: ["unknownapex"],
 			logging_parent: "com.foo.bar",
+			package_name: "test.overridden.package",
 		}
 
 		apex_key {
@@ -3711,7 +3716,7 @@
 	}
 
 	optFlags := apexRule.Args["opt_flags"]
-	ensureContains(t, optFlags, "--override_apk_package_name com.android.myapex")
+	ensureContains(t, optFlags, "--override_apk_package_name test.overridden.package")
 
 	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
 	var builder strings.Builder
@@ -3733,7 +3738,7 @@
 			name: "myapex",
 			key: "myapex.key",
 			native_shared_libs: ["mylib"],
-			legacy_android10_support: true,
+			min_sdk_version: "29",
 		}
 
 		apex_key {
diff --git a/apex/builder.go b/apex/builder.go
index 464d843..40adfca 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -20,6 +20,7 @@
 	"path/filepath"
 	"runtime"
 	"sort"
+	"strconv"
 	"strings"
 
 	"android/soong/android"
@@ -139,6 +140,7 @@
 	apexBundleRule = pctx.StaticRule("apexBundleRule", blueprint.RuleParams{
 		Command: `${zip2zip} -i $in -o $out.base ` +
 			`apex_payload.img:apex/${abi}.img ` +
+			`apex_build_info.pb:apex/${abi}.build_info.pb ` +
 			`apex_manifest.json:root/apex_manifest.json ` +
 			`apex_manifest.pb:root/apex_manifest.pb ` +
 			`AndroidManifest.xml:manifest/AndroidManifest.xml ` +
@@ -205,7 +207,7 @@
 		},
 	})
 
-	if proptools.Bool(a.properties.Legacy_android10_support) {
+	if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
 		// b/143654022 Q apexd can't understand newly added keys in apex_manifest.json
 		// prepare stripped-down version so that APEX modules built from R+ can be installed to Q
 		a.manifestJsonOut = android.PathForModuleOut(ctx, "apex_manifest.json")
@@ -354,7 +356,7 @@
 	var emitCommands []string
 	imageContentFile := android.PathForModuleOut(ctx, "content.txt")
 	emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String())
-	if proptools.Bool(a.properties.Legacy_android10_support) {
+	if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
 		emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String())
 	}
 	for _, fi := range a.filesInfo {
@@ -453,10 +455,9 @@
 		targetSdkVersion := ctx.Config().DefaultAppTargetSdk()
 		minSdkVersion := ctx.Config().DefaultAppTargetSdk()
 
-		// TODO: this should be based on min_sdk_version property of an APEX.
-		if proptools.Bool(a.properties.Legacy_android10_support) {
-			targetSdkVersion = "29"
-			minSdkVersion = "29"
+		if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
+			minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx))
+			targetSdkVersion = strconv.Itoa(a.minSdkVersion(ctx))
 		}
 
 		if java.UseApiFingerprint(ctx) {
@@ -485,7 +486,7 @@
 			ctx.PropertyErrorf("test_only_no_hashtree", "not available")
 			return
 		}
-		if !proptools.Bool(a.properties.Legacy_android10_support) || a.testOnlyShouldSkipHashtreeGeneration() {
+		if a.minSdkVersion(ctx) > android.SdkVersion_Android10 || a.testOnlyShouldSkipHashtreeGeneration() {
 			// Apexes which are supposed to be installed in builtin dirs(/system, etc)
 			// don't need hashtree for activation. Therefore, by removing hashtree from
 			// apex bundle (filesystem image in it, to be specific), we can save storage.
@@ -498,7 +499,7 @@
 			optFlags = append(optFlags, "--do_not_check_keyname")
 		}
 
-		if proptools.Bool(a.properties.Legacy_android10_support) {
+		if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
 			implicitInputs = append(implicitInputs, a.manifestJsonOut)
 			optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
 		}
@@ -657,6 +658,9 @@
 		}
 		return ""
 	}
+	if a.overridableProperties.Package_name != "" {
+		return a.overridableProperties.Package_name
+	}
 	manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
 	if overridden {
 		return manifestPackageName
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index fc9b89e..2778ebd 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -95,6 +95,16 @@
 
 	// outputFile is not exported as it is always arch specific.
 	outputFile android.Path
+
+	// The set of shared libraries
+	//
+	// This field is exported as its contents may not be arch specific.
+	SharedLibs []string
+
+	// The set of system shared libraries
+	//
+	// This field is exported as its contents may not be arch specific.
+	SystemSharedLibs []string
 }
 
 func (p *nativeBinaryInfoProperties) PopulateFromVariant(variant android.SdkAware) {
@@ -102,6 +112,14 @@
 
 	p.archType = ccModule.Target().Arch.ArchType.String()
 	p.outputFile = ccModule.OutputFile().Path()
+
+	if ccModule.linker != nil {
+		specifiedDeps := specifiedDeps{}
+		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
+
+		p.SharedLibs = specifiedDeps.sharedLibs
+		p.SystemSharedLibs = specifiedDeps.systemSharedLibs
+	}
 }
 
 func (p *nativeBinaryInfoProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) {
@@ -114,4 +132,12 @@
 
 		builder.CopyToSnapshot(p.outputFile, nativeBinaryPathFor(*p))
 	}
+
+	if len(p.SharedLibs) > 0 {
+		propertySet.AddPropertyWithTag("shared_libs", p.SharedLibs, builder.SdkMemberReferencePropertyTag(false))
+	}
+
+	if len(p.SystemSharedLibs) > 0 {
+		propertySet.AddPropertyWithTag("system_shared_libs", p.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
+	}
 }
diff --git a/cc/cc.go b/cc/cc.go
index 8b3c772..61ae10a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -250,6 +250,8 @@
 	// Used by vendor snapshot to record dependencies from snapshot modules.
 	SnapshotSharedLibs  []string `blueprint:"mutated"`
 	SnapshotRuntimeLibs []string `blueprint:"mutated"`
+
+	Installable *bool
 }
 
 type VendorProperties struct {
@@ -290,6 +292,7 @@
 	staticBinary() bool
 	header() bool
 	toolchain() config.Toolchain
+	canUseSdk() bool
 	useSdk() bool
 	sdkVersion() string
 	useVndk() bool
@@ -313,6 +316,7 @@
 	useClangLld(actx ModuleContext) bool
 	isForPlatform() bool
 	apexName() string
+	apexSdkVersion() int
 	hasStubsVariants() bool
 	isStubs() bool
 	bootstrap() bool
@@ -366,11 +370,21 @@
 
 	nativeCoverage() bool
 	coverageOutputFilePath() android.OptionalPath
+
+	// Get the deps that have been explicitly specified in the properties.
+	// Only updates the
+	linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps
+}
+
+type specifiedDeps struct {
+	sharedLibs       []string
+	systemSharedLibs []string
 }
 
 type installer interface {
 	installerProps() []interface{}
 	install(ctx ModuleContext, path android.Path)
+	everInstallable() bool
 	inData() bool
 	inSanitizerDir() bool
 	hostToolPath() android.OptionalPath
@@ -1045,8 +1059,12 @@
 	return ctx.mod.header()
 }
 
+func (ctx *moduleContextImpl) canUseSdk() bool {
+	return ctx.ctx.Device() && !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inRecovery() && !ctx.ctx.Fuchsia()
+}
+
 func (ctx *moduleContextImpl) useSdk() bool {
-	if ctx.ctx.Device() && !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inRecovery() && !ctx.ctx.Fuchsia() {
+	if ctx.canUseSdk() {
 		return String(ctx.mod.Properties.Sdk_version) != ""
 	}
 	return false
@@ -1179,6 +1197,10 @@
 	return ctx.mod.ApexName()
 }
 
+func (ctx *moduleContextImpl) apexSdkVersion() int {
+	return ctx.mod.ApexProperties.Info.MinSdkVersion
+}
+
 func (ctx *moduleContextImpl) hasStubsVariants() bool {
 	return ctx.mod.HasStubsVariants()
 }
@@ -1488,6 +1510,13 @@
 		if ctx.Failed() {
 			return
 		}
+	} else if !proptools.BoolDefault(c.Properties.Installable, true) {
+		// If the module has been specifically configure to not be installed then
+		// skip the installation as otherwise it will break when running inside make
+		// as the output path to install will not be specified. Not all uninstallable
+		// modules can skip installation as some are needed for resolving make side
+		// dependencies.
+		c.SkipInstall()
 	}
 }
 
@@ -2629,8 +2658,18 @@
 	}
 }
 
+// Return true if the module is ever installable.
+func (c *Module) EverInstallable() bool {
+	return c.installer != nil &&
+		// Check to see whether the module is actually ever installable.
+		c.installer.everInstallable()
+}
+
 func (c *Module) installable() bool {
-	ret := c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid()
+	ret := c.EverInstallable() &&
+		// Check to see whether the module has been configured to not be installed.
+		proptools.BoolDefault(c.Properties.Installable, true) &&
+		!c.Properties.PreventInstall && c.outputFile.Valid()
 
 	// The platform variant doesn't need further condition. Apex variants however might not
 	// be installable because it will likely to be included in the APEX and won't appear
diff --git a/cc/compiler.go b/cc/compiler.go
index 3a87b69..fe81bd0 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -315,6 +315,18 @@
 			"-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
 	}
 
+	if ctx.canUseSdk() {
+		sdkVersion := ctx.sdkVersion()
+		if sdkVersion == "" || sdkVersion == "current" {
+			if ctx.isForPlatform() {
+				sdkVersion = strconv.Itoa(android.FutureApiLevel)
+			} else {
+				sdkVersion = strconv.Itoa(ctx.apexSdkVersion())
+			}
+		}
+		flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_SDK_VERSION__="+sdkVersion)
+	}
+
 	if ctx.useVndk() {
 		flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VNDK__")
 	}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index d849906..274ccd5 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -49,7 +49,7 @@
 	"-Wunused-but-set-variable",
 	"-fdiagnostics-color",
 
-	// arm + arm64 + mips + mips64
+	// arm + arm64
 	"-fgcse-after-reload",
 	"-frerun-cse-after-loop",
 	"-frename-registers",
@@ -68,11 +68,6 @@
 	"-fno-tree-copy-prop",
 	"-fno-tree-loop-optimize",
 
-	// mips + mips64
-	"-msynci",
-	"-mno-synci",
-	"-mno-fused-madd",
-
 	// x86 + x86_64
 	"-finline-limit=300",
 	"-fno-inline-functions-called-once",
diff --git a/cc/config/mips64_device.go b/cc/config/mips64_device.go
deleted file mode 100644
index c2af951..0000000
--- a/cc/config/mips64_device.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package config
-
-import (
-	"strings"
-
-	"android/soong/android"
-)
-
-var (
-	mips64Cflags = []string{
-		"-Umips",
-
-		// Help catch common 32/64-bit errors.
-		"-Werror=implicit-function-declaration",
-	}
-
-	mips64ClangCflags = append(mips64Cflags, []string{
-		"-fintegrated-as",
-	}...)
-
-	mips64Cppflags = []string{}
-
-	mips64Ldflags = []string{
-		"-Wl,--allow-shlib-undefined",
-	}
-
-	mips64ArchVariantCflags = map[string][]string{
-		"mips64r2": []string{
-			"-mips64r2",
-			"-msynci",
-		},
-		"mips64r6": []string{
-			"-mips64r6",
-			"-msynci",
-		},
-	}
-)
-
-const (
-	mips64GccVersion = "4.9"
-)
-
-func init() {
-	pctx.StaticVariable("mips64GccVersion", mips64GccVersion)
-
-	pctx.SourcePathVariable("Mips64GccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}")
-
-	pctx.StaticVariable("Mips64IncludeFlags", bionicHeaders("mips"))
-
-	// Clang cflags
-	pctx.StaticVariable("Mips64ClangCflags", strings.Join(ClangFilterUnknownCflags(mips64ClangCflags), " "))
-	pctx.StaticVariable("Mips64ClangLdflags", strings.Join(ClangFilterUnknownCflags(mips64Ldflags), " "))
-	pctx.StaticVariable("Mips64ClangCppflags", strings.Join(ClangFilterUnknownCflags(mips64Cppflags), " "))
-
-	// Extended cflags
-
-	// Architecture variant cflags
-	for variant, cflags := range mips64ArchVariantCflags {
-		pctx.StaticVariable("Mips64"+variant+"VariantClangCflags",
-			strings.Join(ClangFilterUnknownCflags(cflags), " "))
-	}
-}
-
-type toolchainMips64 struct {
-	toolchain64Bit
-	clangCflags          string
-	toolchainClangCflags string
-}
-
-func (t *toolchainMips64) Name() string {
-	return "mips64"
-}
-
-func (t *toolchainMips64) GccRoot() string {
-	return "${config.Mips64GccRoot}"
-}
-
-func (t *toolchainMips64) GccTriple() string {
-	return "mips64el-linux-android"
-}
-
-func (t *toolchainMips64) GccVersion() string {
-	return mips64GccVersion
-}
-
-func (t *toolchainMips64) IncludeFlags() string {
-	return "${config.Mips64IncludeFlags}"
-}
-
-func (t *toolchainMips64) ClangTriple() string {
-	return t.GccTriple()
-}
-
-func (t *toolchainMips64) ToolchainClangCflags() string {
-	return t.toolchainClangCflags
-}
-
-func (t *toolchainMips64) ClangAsflags() string {
-	return "-fno-integrated-as"
-}
-
-func (t *toolchainMips64) ClangCflags() string {
-	return t.clangCflags
-}
-
-func (t *toolchainMips64) ClangCppflags() string {
-	return "${config.Mips64ClangCppflags}"
-}
-
-func (t *toolchainMips64) ClangLdflags() string {
-	return "${config.Mips64ClangLdflags}"
-}
-
-func (t *toolchainMips64) ClangLldflags() string {
-	// TODO: define and use Mips64ClangLldflags
-	return "${config.Mips64ClangLdflags}"
-}
-
-func (toolchainMips64) LibclangRuntimeLibraryArch() string {
-	return "mips64"
-}
-
-func mips64ToolchainFactory(arch android.Arch) Toolchain {
-	return &toolchainMips64{
-		clangCflags:          "${config.Mips64ClangCflags}",
-		toolchainClangCflags: "${config.Mips64" + arch.ArchVariant + "VariantClangCflags}",
-	}
-}
-
-func init() {
-	registerToolchainFactory(android.Android, android.Mips64, mips64ToolchainFactory)
-}
diff --git a/cc/config/mips_device.go b/cc/config/mips_device.go
deleted file mode 100644
index ddbc41b..0000000
--- a/cc/config/mips_device.go
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package config
-
-import (
-	"strings"
-
-	"android/soong/android"
-)
-
-var (
-	mipsCflags = []string{
-		"-fomit-frame-pointer",
-		"-Umips",
-	}
-
-	mipsClangCflags = append(mipsCflags, []string{
-		"-fPIC",
-		"-fintegrated-as",
-	}...)
-
-	mipsCppflags = []string{}
-
-	mipsLdflags = []string{
-		"-Wl,--allow-shlib-undefined",
-	}
-
-	mipsToolchainLdflags = []string{
-		"-Wl,-melf32ltsmip",
-	}
-
-	mipsArchVariantCflags = map[string][]string{
-		"mips32-fp": []string{
-			"-mips32",
-			"-mfp32",
-			"-modd-spreg",
-			"-mno-synci",
-		},
-		"mips32r2-fp": []string{
-			"-mips32r2",
-			"-mfp32",
-			"-modd-spreg",
-			"-msynci",
-		},
-		"mips32r2-fp-xburst": []string{
-			"-mips32r2",
-			"-mfp32",
-			"-modd-spreg",
-			"-mno-fused-madd",
-			"-mno-synci",
-		},
-		"mips32r2dsp-fp": []string{
-			"-mips32r2",
-			"-mfp32",
-			"-modd-spreg",
-			"-mdsp",
-			"-msynci",
-		},
-		"mips32r2dspr2-fp": []string{
-			"-mips32r2",
-			"-mfp32",
-			"-modd-spreg",
-			"-mdspr2",
-			"-msynci",
-		},
-		"mips32r6": []string{
-			"-mips32r6",
-			"-mfp64",
-			"-mno-odd-spreg",
-			"-msynci",
-		},
-	}
-)
-
-const (
-	mipsGccVersion = "4.9"
-)
-
-func init() {
-	pctx.StaticVariable("mipsGccVersion", mipsGccVersion)
-
-	pctx.SourcePathVariable("MipsGccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}")
-
-	pctx.StaticVariable("MipsToolchainLdflags", strings.Join(mipsToolchainLdflags, " "))
-	pctx.StaticVariable("MipsIncludeFlags", bionicHeaders("mips"))
-
-	// Clang cflags
-	pctx.StaticVariable("MipsClangCflags", strings.Join(ClangFilterUnknownCflags(mipsClangCflags), " "))
-	pctx.StaticVariable("MipsClangLdflags", strings.Join(ClangFilterUnknownCflags(mipsLdflags), " "))
-	pctx.StaticVariable("MipsClangCppflags", strings.Join(ClangFilterUnknownCflags(mipsCppflags), " "))
-
-	// Extended cflags
-
-	// Architecture variant cflags
-	for variant, cflags := range mipsArchVariantCflags {
-		pctx.StaticVariable("Mips"+variant+"VariantClangCflags",
-			strings.Join(ClangFilterUnknownCflags(cflags), " "))
-	}
-}
-
-type toolchainMips struct {
-	toolchain32Bit
-	clangCflags          string
-	toolchainClangCflags string
-}
-
-func (t *toolchainMips) Name() string {
-	return "mips"
-}
-
-func (t *toolchainMips) GccRoot() string {
-	return "${config.MipsGccRoot}"
-}
-
-func (t *toolchainMips) GccTriple() string {
-	return "mips64el-linux-android"
-}
-
-func (t *toolchainMips) GccVersion() string {
-	return mipsGccVersion
-}
-
-func (t *toolchainMips) IncludeFlags() string {
-	return "${config.MipsIncludeFlags}"
-}
-
-func (t *toolchainMips) ClangTriple() string {
-	return "mipsel-linux-android"
-}
-
-func (t *toolchainMips) ToolchainClangLdflags() string {
-	return "${config.MipsToolchainLdflags}"
-}
-
-func (t *toolchainMips) ToolchainClangCflags() string {
-	return t.toolchainClangCflags
-}
-
-func (t *toolchainMips) ClangAsflags() string {
-	return "-fPIC -fno-integrated-as"
-}
-
-func (t *toolchainMips) ClangCflags() string {
-	return t.clangCflags
-}
-
-func (t *toolchainMips) ClangCppflags() string {
-	return "${config.MipsClangCppflags}"
-}
-
-func (t *toolchainMips) ClangLdflags() string {
-	return "${config.MipsClangLdflags}"
-}
-
-func (t *toolchainMips) ClangLldflags() string {
-	// TODO: define and use MipsClangLldflags
-	return "${config.MipsClangLdflags}"
-}
-
-func (toolchainMips) LibclangRuntimeLibraryArch() string {
-	return "mips"
-}
-
-func mipsToolchainFactory(arch android.Arch) Toolchain {
-	return &toolchainMips{
-		clangCflags:          "${config.MipsClangCflags}",
-		toolchainClangCflags: "${config.Mips" + arch.ArchVariant + "VariantClangCflags}",
-	}
-}
-
-func init() {
-	registerToolchainFactory(android.Android, android.Mips, mipsToolchainFactory)
-}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index ee24300..6a9b709 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -367,8 +367,6 @@
 			return
 		}
 
-		s.fuzzTargets[module.Name()] = true
-
 		hostOrTargetString := "target"
 		if ccModule.Host() {
 			hostOrTargetString = "host"
@@ -458,6 +456,17 @@
 		builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
 			"Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
 
+		// Don't add modules to 'make haiku' that are set to not be exported to the
+		// fuzzing infrastructure.
+		if config := fuzzModule.Properties.Fuzz_config; config != nil {
+			if ccModule.Host() && !BoolDefault(config.Fuzz_on_haiku_host, true) {
+				return
+			} else if !BoolDefault(config.Fuzz_on_haiku_device, true) {
+				return
+			}
+		}
+
+		s.fuzzTargets[module.Name()] = true
 		archDirs[archOs] = append(archDirs[archOs], fileToZip{fuzzZip, ""})
 	})
 
diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py
index 0de703c..7deb804 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/gen_stub_libs.py
@@ -26,8 +26,6 @@
 ALL_ARCHITECTURES = (
     'arm',
     'arm64',
-    'mips',
-    'mips64',
     'x86',
     'x86_64',
 )
diff --git a/cc/installer.go b/cc/installer.go
index 2f55ac5..200d59e 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -86,6 +86,11 @@
 	installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file)
 }
 
+func (installer *baseInstaller) everInstallable() bool {
+	// Most cc modules are installable.
+	return true
+}
+
 func (installer *baseInstaller) inData() bool {
 	return installer.location == InstallInData
 }
diff --git a/cc/library.go b/cc/library.go
index e1d0b34..6bd93f9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -817,6 +817,23 @@
 	return deps
 }
 
+func (library *libraryDecorator) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
+	specifiedDeps = library.baseLinker.linkerSpecifiedDeps(specifiedDeps)
+	var properties StaticOrSharedProperties
+	if library.static() {
+		properties = library.StaticProperties.Static
+	} else if library.shared() {
+		properties = library.SharedProperties.Shared
+	}
+
+	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs...)
+	specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, properties.System_shared_libs...)
+
+	specifiedDeps.sharedLibs = android.FirstUniqueStrings(specifiedDeps.sharedLibs)
+	specifiedDeps.systemSharedLibs = android.FirstUniqueStrings(specifiedDeps.systemSharedLibs)
+	return specifiedDeps
+}
+
 func (library *libraryDecorator) linkStatic(ctx ModuleContext,
 	flags Flags, deps PathDeps, objs Objects) android.Path {
 
@@ -1220,6 +1237,12 @@
 	}
 }
 
+func (library *libraryDecorator) everInstallable() bool {
+	// Only shared and static libraries are installed. Header libraries (which are
+	// neither static or shared) are not installed.
+	return library.shared() || library.static()
+}
+
 func (library *libraryDecorator) static() bool {
 	return library.MutatedProperties.VariantIsStatic
 }
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 656df69..843ebb0 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -19,6 +19,7 @@
 
 	"android/soong/android"
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 // This file contains support for using cc library modules within an sdk.
@@ -104,12 +105,12 @@
 	if sdkVersion != "" {
 		pbm.AddProperty("sdk_version", sdkVersion)
 	}
-	return pbm
-}
 
-func (mt *librarySdkMemberType) FinalizeModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember, bpModule android.BpModule) {
-	bpModule.AddProperty("stl", "none")
-	bpModule.AddProperty("system_shared_libs", []string{})
+	stl := ccModule.stl.Properties.Stl
+	if stl != nil {
+		pbm.AddProperty("stl", proptools.String(stl))
+	}
+	return pbm
 }
 
 func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
@@ -193,6 +194,14 @@
 		outputProperties.AddProperty("srcs", []string{nativeLibraryPath})
 	}
 
+	if len(libInfo.SharedLibs) > 0 {
+		outputProperties.AddPropertyWithTag("shared_libs", libInfo.SharedLibs, builder.SdkMemberReferencePropertyTag(false))
+	}
+
+	if len(libInfo.SystemSharedLibs) > 0 {
+		outputProperties.AddPropertyWithTag("system_shared_libs", libInfo.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
+	}
+
 	// Map from property name to the include dirs to add to the prebuilt module in the snapshot.
 	includeDirs := make(map[string][]string)
 
@@ -299,6 +308,16 @@
 	// This field is exported as its contents may not be arch specific.
 	ExportedFlags []string
 
+	// The set of shared libraries
+	//
+	// This field is exported as its contents may not be arch specific.
+	SharedLibs []string
+
+	// The set of system shared libraries
+	//
+	// This field is exported as its contents may not be arch specific.
+	SystemSharedLibs []string
+
 	// outputFile is not exported as it is always arch specific.
 	outputFile android.Path
 }
@@ -323,6 +342,13 @@
 	p.exportedGeneratedIncludeDirs = exportedGeneratedIncludeDirs
 	p.ExportedSystemIncludeDirs = ccModule.ExportedSystemIncludeDirs()
 	p.ExportedFlags = ccModule.ExportedFlags()
+	if ccModule.linker != nil {
+		specifiedDeps := specifiedDeps{}
+		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
+
+		p.SharedLibs = specifiedDeps.sharedLibs
+		p.SystemSharedLibs = specifiedDeps.systemSharedLibs
+	}
 	p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
 }
 
diff --git a/cc/linker.go b/cc/linker.go
index a7b621a..ae5ee0a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -438,11 +438,10 @@
 		}
 	}
 
-	if ctx.useSdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) {
+	if ctx.useSdk() {
 		// The bionic linker now has support gnu style hashes (which are much faster!), but shipping
 		// to older devices requires the old style hash. Fortunately, we can build with both and
 		// it'll work anywhere.
-		// This is not currently supported on MIPS architectures.
 		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--hash-style=both")
 	}
 
@@ -490,6 +489,12 @@
 	panic(fmt.Errorf("baseLinker doesn't know how to link"))
 }
 
+func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
+	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...)
+	specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, linker.Properties.System_shared_libs...)
+	return specifiedDeps
+}
+
 // Injecting version symbols
 // Some host modules want a version number, but we don't want to rebuild it every time.  Optionally add a step
 // after linking that injects a constant placeholder with the current version number.
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 5744bb2..60f931d 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -17,7 +17,6 @@
 import (
 	"fmt"
 	"path/filepath"
-	"strings"
 
 	"github.com/google/blueprint"
 
@@ -131,14 +130,6 @@
 
 	m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
 
-	// When generating NDK prebuilts, skip installing MIPS headers,
-	// but keep them when doing regular platform build.
-	// Ndk_abis property is only set to true with build/soong/scripts/build-ndk-prebuilts.sh
-	// TODO: Revert this once MIPS is supported in NDK again.
-	if ctx.Config().NdkAbis() && strings.Contains(ctx.ModuleName(), "mips") {
-		return
-	}
-
 	srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
 	for _, header := range srcFiles {
 		installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 00338b9..2a86d33 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -133,8 +133,6 @@
 	firstArchVersions := map[android.ArchType]int{
 		android.Arm:    minVersion,
 		android.Arm64:  21,
-		android.Mips:   minVersion,
-		android.Mips64: 21,
 		android.X86:    minVersion,
 		android.X86_64: 21,
 	}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 6e809bf..d32efda 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -307,8 +307,8 @@
 		}
 	}
 
-	// CFI needs gold linker, and mips toolchain does not have one.
-	if !ctx.Config().EnableCFI() || ctx.Arch().ArchType == android.Mips || ctx.Arch().ArchType == android.Mips64 {
+	// Is CFI actually enabled?
+	if !ctx.Config().EnableCFI() {
 		s.Cfi = nil
 		s.Diag.Cfi = nil
 	}
@@ -900,6 +900,11 @@
 		c.sanitize.Properties.Sanitizers = sanitizers
 		c.sanitize.Properties.DiagSanitizers = diagSanitizers
 
+		// TODO(b/150822854) Hosts have a different default behavior and assume the runtime library is used.
+		if c.Host() {
+			diagSanitizers = sanitizers
+		}
+
 		// Determine the runtime library required
 		runtimeLibrary := ""
 		var extraStaticDeps []string
@@ -995,11 +1000,6 @@
 				modules[0].(*Module).sanitize.SetSanitizer(t, true)
 			} else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep {
 				isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t)
-				if mctx.Device() && t.incompatibleWithCfi() {
-					// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
-					// are incompatible with cfi
-					c.sanitize.SetSanitizer(cfi, false)
-				}
 				if c.static() || c.header() || t == asan || t == fuzzer {
 					// Static and header libs are split into non-sanitized and sanitized variants.
 					// Shared libs are not split. However, for asan and fuzzer, we split even for shared
@@ -1021,6 +1021,12 @@
 					modules[0].(*Module).sanitize.Properties.SanitizeDep = false
 					modules[1].(*Module).sanitize.Properties.SanitizeDep = false
 
+					if mctx.Device() && t.incompatibleWithCfi() {
+						// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
+						// are incompatible with cfi
+						modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
+					}
+
 					// For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
 					// to Make, because the sanitized version has a different suffix in name.
 					// For other types of sanitizers, suppress the variation that is disabled.
@@ -1058,6 +1064,12 @@
 					if mctx.Device() && t == asan && isSanitizerEnabled {
 						modules[0].(*Module).sanitize.Properties.InSanitizerDir = true
 					}
+
+					if mctx.Device() && t.incompatibleWithCfi() {
+						// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
+						// are incompatible with cfi
+						modules[0].(*Module).sanitize.SetSanitizer(cfi, false)
+					}
 				}
 			}
 			c.sanitize.Properties.SanitizeDep = false
diff --git a/doc.go b/doc.go
index 543c460..299fd2b 100644
--- a/doc.go
+++ b/doc.go
@@ -46,8 +46,8 @@
 //
 // Target architecture
 // The target architecture is the preferred architecture supported by the selected
-// device.  It is most commonly 32-bit arm, but may also be 64-bit arm, 32-bit or
-// 64-bit x86, or mips.
+// device.  It is most commonly 32-bit arm, but may also be 64-bit arm, 32-bit
+// x86, or 64-bit x86.
 //
 // Secondary architecture
 // The secondary architecture specifies the architecture to compile a second copy
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 6ec919c..ae0dc0b 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -33,8 +33,7 @@
 // /system/framework/boot.art and should be the same for all supported
 // architectures on the device. The concrete architecture specific
 // content actually ends up in a "filename" that contains an
-// architecture specific directory name such as arm, arm64, mips,
-// mips64, x86, x86_64.
+// architecture specific directory name such as arm, arm64, x86, x86_64.
 //
 // Here are some example values for an x86_64 / x86 configuration:
 //
@@ -176,11 +175,6 @@
 		return true
 	}
 
-	if len(ctx.Config().Targets[android.Android]) == 0 {
-		// Host-only build
-		return true
-	}
-
 	return false
 }
 
@@ -199,7 +193,10 @@
 	// Include dexpreopt files for the primary boot image.
 	files := map[android.ArchType]android.OutputPaths{}
 	for _, variant := range artBootImageConfig(ctx).variants {
-		files[variant.target.Arch.ArchType] = variant.imagesDeps
+		// We also generate boot images for host (for testing), but we don't need those in the apex.
+		if variant.target.Os == android.Android {
+			files[variant.target.Arch.ArchType] = variant.imagesDeps
+		}
 	}
 	return files
 }
@@ -305,9 +302,10 @@
 	global := dexpreopt.GetGlobalConfig(ctx)
 
 	arch := image.target.Arch.ArchType
-	symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String())
+	os := image.target.Os.String() // We need to distinguish host-x86 and device-x86.
+	symbolsDir := image.symbolsDir.Join(ctx, os, image.installSubdir, arch.String())
 	symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
-	outputDir := image.dir.Join(ctx, image.installSubdir, arch.String())
+	outputDir := image.dir.Join(ctx, os, image.installSubdir, arch.String())
 	outputPath := outputDir.Join(ctx, image.stem+".oat")
 	oatLocation := dexpreopt.PathToLocation(outputPath, arch)
 	imagePath := outputPath.ReplaceExtension(ctx, "art")
@@ -375,13 +373,18 @@
 		FlagWithArg("--oat-location=", oatLocation).
 		FlagWithArg("--image=", imagePath.String()).
 		FlagWithArg("--instruction-set=", arch.String()).
-		FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]).
-		FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]).
 		FlagWithArg("--android-root=", global.EmptyDirectory).
 		FlagWithArg("--no-inline-from=", "core-oj.jar").
 		Flag("--force-determinism").
 		Flag("--abort-on-hard-verifier-error")
 
+	// Use the default variant/features for host builds.
+	// The map below contains only device CPU info (which might be x86 on some devices).
+	if image.target.Os == android.Android {
+		cmd.FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch])
+		cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
+	}
+
 	if global.BootFlags != "" {
 		cmd.Flag(global.BootFlags)
 	}
@@ -393,7 +396,6 @@
 	cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage))
 
 	installDir := filepath.Join("/", image.installSubdir, arch.String())
-	vdexInstallDir := filepath.Join("/", image.installSubdir)
 
 	var vdexInstalls android.RuleBuilderInstalls
 	var unstrippedInstalls android.RuleBuilderInstalls
@@ -412,11 +414,10 @@
 		cmd.ImplicitOutput(vdex)
 		zipFiles = append(zipFiles, vdex)
 
-		// The vdex files are identical between architectures, install them to a shared location.  The Make rules will
-		// only use the install rules for one architecture, and will create symlinks into the architecture-specific
-		// directories.
+		// Note that the vdex files are identical between architectures.
+		// Make rules will create symlinks to share them between architectures.
 		vdexInstalls = append(vdexInstalls,
-			android.RuleBuilderInstall{vdex, filepath.Join(vdexInstallDir, vdex.Base())})
+			android.RuleBuilderInstall{vdex, filepath.Join(installDir, vdex.Base())})
 	}
 
 	for _, unstrippedOat := range image.moduleFiles(ctx, symbolsDir, ".oat") {
@@ -427,7 +428,7 @@
 			android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())})
 	}
 
-	rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+arch.String(), "dexpreopt "+image.name+" jars "+arch.String())
+	rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String())
 
 	// save output and installed files for makevars
 	image.installs = rule.Installs()
@@ -545,8 +546,9 @@
 	var allPhonies android.Paths
 	for _, image := range image.variants {
 		arch := image.target.Arch.ArchType
+		suffix := image.target.String()
 		// Create a rule to call oatdump.
-		output := android.PathForOutput(ctx, "boot."+arch.String()+".oatdump.txt")
+		output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
 		rule := android.NewRuleBuilder()
 		rule.Command().
 			// TODO: for now, use the debug version for better error reporting
@@ -556,16 +558,16 @@
 			FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps.Paths()).
 			FlagWithOutput("--output=", output).
 			FlagWithArg("--instruction-set=", arch.String())
-		rule.Build(pctx, ctx, "dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+		rule.Build(pctx, ctx, "dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
 
 		// Create a phony rule that depends on the output file and prints the path.
-		phony := android.PathForPhony(ctx, "dump-oat-boot-"+arch.String())
+		phony := android.PathForPhony(ctx, "dump-oat-boot-"+suffix)
 		rule = android.NewRuleBuilder()
 		rule.Command().
 			Implicit(output).
 			ImplicitOutput(phony).
 			Text("echo").FlagWithArg("Output in ", output.String())
-		rule.Build(pctx, ctx, "phony-dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+		rule.Build(pctx, ctx, "phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
 
 		allPhonies = append(allPhonies, phony)
 	}
@@ -609,7 +611,11 @@
 		for _, current := range append(d.otherImages, image) {
 			imageNames = append(imageNames, current.name)
 			for _, current := range current.variants {
-				sfx := current.name + "_" + current.target.Arch.ArchType.String()
+				suffix := ""
+				if current.target.Os.Class == android.Host {
+					suffix = "_host"
+				}
+				sfx := current.name + suffix + "_" + current.target.Arch.ArchType.String()
 				ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls.String())
 				ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images.String())
 				ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps.Strings(), " "))
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index c3b2133..94ca8bb 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -62,7 +62,7 @@
 	bootArt := dexpreoptBootJars.Output("boot-foo.art")
 
 	expectedInputs := []string{
-		"dex_artjars/apex/com.android.art/javalib/arm64/boot.art",
+		"dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art",
 		"dex_bootjars_input/foo.jar",
 		"dex_bootjars_input/bar.jar",
 		"dex_bootjars_input/baz.jar",
@@ -81,23 +81,23 @@
 	}
 
 	expectedOutputs := []string{
-		"dex_bootjars/system/framework/arm64/boot.invocation",
+		"dex_bootjars/android/system/framework/arm64/boot.invocation",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.art",
-		"dex_bootjars/system/framework/arm64/boot-bar.art",
-		"dex_bootjars/system/framework/arm64/boot-baz.art",
+		"dex_bootjars/android/system/framework/arm64/boot-foo.art",
+		"dex_bootjars/android/system/framework/arm64/boot-bar.art",
+		"dex_bootjars/android/system/framework/arm64/boot-baz.art",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.oat",
-		"dex_bootjars/system/framework/arm64/boot-bar.oat",
-		"dex_bootjars/system/framework/arm64/boot-baz.oat",
+		"dex_bootjars/android/system/framework/arm64/boot-foo.oat",
+		"dex_bootjars/android/system/framework/arm64/boot-bar.oat",
+		"dex_bootjars/android/system/framework/arm64/boot-baz.oat",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.vdex",
-		"dex_bootjars/system/framework/arm64/boot-bar.vdex",
-		"dex_bootjars/system/framework/arm64/boot-baz.vdex",
+		"dex_bootjars/android/system/framework/arm64/boot-foo.vdex",
+		"dex_bootjars/android/system/framework/arm64/boot-bar.vdex",
+		"dex_bootjars/android/system/framework/arm64/boot-baz.vdex",
 
-		"dex_bootjars_unstripped/system/framework/arm64/boot-foo.oat",
-		"dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat",
-		"dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat",
+		"dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat",
+		"dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat",
+		"dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat",
 	}
 
 	for i := range expectedOutputs {
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index a06aec4..d77d3e1 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -68,6 +68,10 @@
 			targets = append(targets, target)
 		}
 	}
+	// We may also need the images on host in order to run host-based tests.
+	for _, target := range ctx.Config().Targets[android.BuildOs] {
+		targets = append(targets, target)
+	}
 
 	return targets
 }
@@ -152,7 +156,7 @@
 			// expands to <stem>.art for primary image and <stem>-<1st module>.art for extension
 			imageName := c.firstModuleNameOrStem() + ".art"
 
-			c.imageLocations = []string{c.dir.Join(ctx, c.installSubdir, imageName).String()}
+			c.imageLocations = []string{c.dir.Join(ctx, "android", c.installSubdir, imageName).String()}
 
 			// The path to bootclasspath dex files needs to be known at module
 			// GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled.
@@ -167,7 +171,7 @@
 			// Create target-specific variants.
 			for _, target := range targets {
 				arch := target.Arch.ArchType
-				imageDir := c.dir.Join(ctx, c.installSubdir, arch.String())
+				imageDir := c.dir.Join(ctx, target.Os.String(), c.installSubdir, arch.String())
 				variant := &bootImageVariant{
 					bootImageConfig: c,
 					target:          target,
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 5437499..1ac7444 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1345,6 +1345,7 @@
 		cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
 	} else {
 		cmd.FlagWithArg("--stubs ", stubsDir.String())
+		cmd.Flag("--exclude-documentation-from-stubs")
 	}
 }
 
diff --git a/java/system_modules.go b/java/system_modules.go
index 47de6e3..40031cb 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -255,5 +255,5 @@
 
 	pbm := builder.AddPrebuiltModule(member, "java_system_modules_import")
 	// Add the references to the libraries that form the system module.
-	pbm.AddPropertyWithTag("libs", systemModule.properties.Libs, builder.SdkMemberReferencePropertyTag())
+	pbm.AddPropertyWithTag("libs", systemModule.properties.Libs, builder.SdkMemberReferencePropertyTag(true))
 }
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 11bc902..6f9dc3c 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -297,6 +297,8 @@
 cc_prebuilt_library_shared {
     name: "mysdk_mynativelib@current",
     sdk_member_name: "mynativelib",
+    installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -307,13 +309,12 @@
             srcs: ["arm/lib/mynativelib.so"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -324,8 +325,6 @@
             srcs: ["arm/lib/mynativelib.so"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -366,6 +365,7 @@
 cc_prebuilt_binary {
     name: "mymodule_exports_mynativebinary@current",
     sdk_member_name: "mynativebinary",
+    installable: false,
     compile_multilib: "both",
     arch: {
         arm64: {
@@ -447,6 +447,7 @@
     sdk_member_name: "mynativebinary",
     device_supported: false,
     host_supported: true,
+    installable: false,
     target: {
         linux_glibc: {
             compile_multilib: "both",
@@ -539,6 +540,8 @@
         "apex1",
         "apex2",
     ],
+    installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -550,8 +553,6 @@
             export_include_dirs: ["arm/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_shared {
@@ -561,6 +562,7 @@
         "apex1",
         "apex2",
     ],
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -572,8 +574,6 @@
             export_include_dirs: ["arm/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -595,6 +595,189 @@
 	)
 }
 
+func TestSnapshotWithCcSharedLibrarySharedLibs(t *testing.T) {
+	result := testSdkWithCc(t, `
+		sdk {
+			name: "mysdk",
+			native_shared_libs: [
+				"mynativelib",
+				"myothernativelib",
+				"mysystemnativelib",
+			],
+		}
+
+		cc_library {
+			name: "mysystemnativelib",
+			srcs: [
+				"Test.cpp",
+			],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library_shared {
+			name: "myothernativelib",
+			srcs: [
+				"Test.cpp",
+			],
+			system_shared_libs: [
+				// A reference to a library that is not an sdk member. Uses libm as that
+				// is in the default set of modules available to this test and so is available
+				// both here and also when the generated Android.bp file is tested in
+				// CheckSnapshot(). This ensures that the system_shared_libs property correctly
+				// handles references to modules that are not sdk members.
+				"libm",
+			],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "mynativelib",
+			srcs: [
+				"Test.cpp",
+			],
+			shared_libs: [
+				// A reference to another sdk member.
+				"myothernativelib",
+			],
+			target: {
+				android: {
+					shared: {
+						shared_libs: [
+							// A reference to a library that is not an sdk member. The libc library
+							// is used here to check that the shared_libs property is handled correctly
+							// in a similar way to how libm is used to check system_shared_libs above.
+							"libc",
+						],
+					},
+				},
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+    name: "mysdk_mynativelib@current",
+    sdk_member_name: "mynativelib",
+    installable: false,
+    stl: "none",
+    shared_libs: [
+        "mysdk_myothernativelib@current",
+        "libc",
+    ],
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/mynativelib.so"],
+        },
+        arm: {
+            srcs: ["arm/lib/mynativelib.so"],
+        },
+    },
+}
+
+cc_prebuilt_library_shared {
+    name: "mynativelib",
+    prefer: false,
+    stl: "none",
+    shared_libs: [
+        "myothernativelib",
+        "libc",
+    ],
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/mynativelib.so"],
+        },
+        arm: {
+            srcs: ["arm/lib/mynativelib.so"],
+        },
+    },
+}
+
+cc_prebuilt_library_shared {
+    name: "mysdk_myothernativelib@current",
+    sdk_member_name: "myothernativelib",
+    installable: false,
+    stl: "none",
+    system_shared_libs: ["libm"],
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/myothernativelib.so"],
+        },
+        arm: {
+            srcs: ["arm/lib/myothernativelib.so"],
+        },
+    },
+}
+
+cc_prebuilt_library_shared {
+    name: "myothernativelib",
+    prefer: false,
+    stl: "none",
+    system_shared_libs: ["libm"],
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/myothernativelib.so"],
+        },
+        arm: {
+            srcs: ["arm/lib/myothernativelib.so"],
+        },
+    },
+}
+
+cc_prebuilt_library_shared {
+    name: "mysdk_mysystemnativelib@current",
+    sdk_member_name: "mysystemnativelib",
+    installable: false,
+    stl: "none",
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/mysystemnativelib.so"],
+        },
+        arm: {
+            srcs: ["arm/lib/mysystemnativelib.so"],
+        },
+    },
+}
+
+cc_prebuilt_library_shared {
+    name: "mysystemnativelib",
+    prefer: false,
+    stl: "none",
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/mysystemnativelib.so"],
+        },
+        arm: {
+            srcs: ["arm/lib/mysystemnativelib.so"],
+        },
+    },
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    native_shared_libs: [
+        "mysdk_mynativelib@current",
+        "mysdk_myothernativelib@current",
+        "mysdk_mysystemnativelib@current",
+    ],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
+.intermediates/myothernativelib/android_arm64_armv8-a_shared/myothernativelib.so -> arm64/lib/myothernativelib.so
+.intermediates/myothernativelib/android_arm_armv7-a-neon_shared/myothernativelib.so -> arm/lib/myothernativelib.so
+.intermediates/mysystemnativelib/android_arm64_armv8-a_shared/mysystemnativelib.so -> arm64/lib/mysystemnativelib.so
+.intermediates/mysystemnativelib/android_arm_armv7-a-neon_shared/mysystemnativelib.so -> arm/lib/mysystemnativelib.so
+`),
+	)
+}
+
 func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
 	// b/145598135 - Generating host snapshots for anything other than linux is not supported.
 	SkipIfNotLinux(t)
@@ -634,7 +817,9 @@
     sdk_member_name: "mynativelib",
     device_supported: false,
     host_supported: true,
+    installable: false,
     sdk_version: "minimum",
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -646,8 +831,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_shared {
@@ -656,6 +839,7 @@
     device_supported: false,
     host_supported: true,
     sdk_version: "minimum",
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -667,8 +851,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -735,6 +917,8 @@
     sdk_member_name: "mynativelib",
     device_supported: false,
     host_supported: true,
+    installable: false,
+    stl: "none",
     target: {
         linux_glibc_x86_64: {
             srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
@@ -746,8 +930,6 @@
             srcs: ["windows/x86_64/lib/mynativelib.dll"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_shared {
@@ -755,6 +937,7 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
+    stl: "none",
     target: {
         linux_glibc_x86_64: {
             srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
@@ -766,8 +949,6 @@
             srcs: ["windows/x86_64/lib/mynativelib.dll"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -814,6 +995,8 @@
 cc_prebuilt_library_static {
     name: "myexports_mynativelib@current",
     sdk_member_name: "mynativelib",
+    installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -825,13 +1008,12 @@
             export_include_dirs: ["arm/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_static {
     name: "mynativelib",
     prefer: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -843,8 +1025,6 @@
             export_include_dirs: ["arm/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 module_exports_snapshot {
@@ -904,6 +1084,8 @@
     sdk_member_name: "mynativelib",
     device_supported: false,
     host_supported: true,
+    installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -915,8 +1097,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_static {
@@ -924,6 +1104,7 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -935,8 +1116,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 module_exports_snapshot {
@@ -1003,6 +1182,8 @@
     sdk_member_name: "mynativelib",
     device_supported: false,
     host_supported: true,
+    installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -1010,8 +1191,6 @@
             export_include_dirs: ["x86_64/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_static {
@@ -1019,6 +1198,7 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -1026,20 +1206,18 @@
             export_include_dirs: ["x86_64/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 module_exports_snapshot {
     name: "myexports@current",
     device_supported: false,
     host_supported: true,
+    native_static_libs: ["myexports_mynativelib@current"],
     target: {
         host: {
             compile_multilib: "64",
         },
     },
-    native_static_libs: ["myexports_mynativelib@current"],
 }`),
 		checkAllCopyRules(`
 include/Test.h -> include/include/Test.h
@@ -1073,17 +1251,15 @@
 cc_prebuilt_library_headers {
     name: "mysdk_mynativeheaders@current",
     sdk_member_name: "mynativeheaders",
-    export_include_dirs: ["include/include"],
     stl: "none",
-    system_shared_libs: [],
+    export_include_dirs: ["include/include"],
 }
 
 cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
-    export_include_dirs: ["include/include"],
     stl: "none",
-    system_shared_libs: [],
+    export_include_dirs: ["include/include"],
 }
 
 sdk_snapshot {
@@ -1128,9 +1304,8 @@
     sdk_member_name: "mynativeheaders",
     device_supported: false,
     host_supported: true,
-    export_include_dirs: ["include/include"],
     stl: "none",
-    system_shared_libs: [],
+    export_include_dirs: ["include/include"],
 }
 
 cc_prebuilt_library_headers {
@@ -1138,9 +1313,8 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
-    export_include_dirs: ["include/include"],
     stl: "none",
-    system_shared_libs: [],
+    export_include_dirs: ["include/include"],
 }
 
 sdk_snapshot {
@@ -1192,6 +1366,7 @@
     name: "mysdk_mynativeheaders@current",
     sdk_member_name: "mynativeheaders",
     host_supported: true,
+    stl: "none",
     export_system_include_dirs: ["include/include"],
     target: {
         android: {
@@ -1201,14 +1376,13 @@
             export_include_dirs: ["include/include-host"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
     host_supported: true,
+    stl: "none",
     export_system_include_dirs: ["include/include"],
     target: {
         android: {
@@ -1218,8 +1392,6 @@
             export_include_dirs: ["include/include-host"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index c60002b..cbffb50 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -920,6 +920,7 @@
 module_exports_snapshot {
     name: "myexports@current",
     host_supported: true,
+    java_libs: ["myexports_myjavalib@current"],
     target: {
         android: {
             java_header_libs: ["myexports_androidjavalib@current"],
@@ -928,7 +929,6 @@
             java_header_libs: ["myexports_hostjavalib@current"],
         },
     },
-    java_libs: ["myexports_myjavalib@current"],
 }
 `),
 		checkAllCopyRules(`
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 8b9d5bc..984ed7a 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -50,9 +50,6 @@
 	// list properties, e.g. java_libs.
 	dynamicMemberTypeListProperties interface{}
 
-	// The set of exported members.
-	exportedMembers map[string]struct{}
-
 	// Information about the OsType specific member variants associated with this variant.
 	//
 	// Set by OsType specific variants when their GenerateAndroidBuildActions is invoked
@@ -233,26 +230,19 @@
 }
 
 func (s *sdk) getExportedMembers() map[string]struct{} {
-	if s.exportedMembers == nil {
-		// Collect all the exported members.
-		s.exportedMembers = make(map[string]struct{})
+	// Collect all the exported members.
+	exportedMembers := make(map[string]struct{})
 
-		for _, memberListProperty := range s.memberListProperties() {
-			names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
+	for _, memberListProperty := range s.memberListProperties() {
+		names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
 
-			// Every member specified explicitly in the properties is exported by the sdk.
-			for _, name := range names {
-				s.exportedMembers[name] = struct{}{}
-			}
+		// Every member specified explicitly in the properties is exported by the sdk.
+		for _, name := range names {
+			exportedMembers[name] = struct{}{}
 		}
 	}
 
-	return s.exportedMembers
-}
-
-func (s *sdk) isInternalMember(memberName string) bool {
-	_, ok := s.getExportedMembers()[memberName]
-	return !ok
+	return exportedMembers
 }
 
 func (s *sdk) snapshot() bool {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 96837e3..fde9230 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -16,6 +16,8 @@
 
 import (
 	"testing"
+
+	"github.com/google/blueprint/proptools"
 )
 
 // Needed in an _test.go file in this package to ensure tests run correctly, particularly in IDE.
@@ -222,3 +224,106 @@
 		checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`),
 	)
 }
+
+type EmbeddedPropertiesStruct struct {
+	S_Embedded_Common    string
+	S_Embedded_Different string
+}
+
+type testPropertiesStruct struct {
+	private     string
+	Public_Kept string `sdk:"keep"`
+	S_Common    string
+	S_Different string
+	A_Common    []string
+	A_Different []string
+	F_Common    *bool
+	F_Different *bool
+	EmbeddedPropertiesStruct
+}
+
+func TestCommonValueOptimization(t *testing.T) {
+	common := &testPropertiesStruct{}
+	structs := []*testPropertiesStruct{
+		&testPropertiesStruct{
+			private:     "common",
+			Public_Kept: "common",
+			S_Common:    "common",
+			S_Different: "upper",
+			A_Common:    []string{"first", "second"},
+			A_Different: []string{"alpha", "beta"},
+			F_Common:    proptools.BoolPtr(false),
+			F_Different: proptools.BoolPtr(false),
+			EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
+				S_Embedded_Common:    "embedded_common",
+				S_Embedded_Different: "embedded_upper",
+			},
+		},
+		&testPropertiesStruct{
+			private:     "common",
+			Public_Kept: "common",
+			S_Common:    "common",
+			S_Different: "lower",
+			A_Common:    []string{"first", "second"},
+			A_Different: []string{"alpha", "delta"},
+			F_Common:    proptools.BoolPtr(false),
+			F_Different: proptools.BoolPtr(true),
+			EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
+				S_Embedded_Common:    "embedded_common",
+				S_Embedded_Different: "embedded_lower",
+			},
+		},
+	}
+
+	extractor := newCommonValueExtractor(common)
+	extractor.extractCommonProperties(common, structs)
+
+	h := TestHelper{t}
+	h.AssertDeepEquals("common properties not correct", common,
+		&testPropertiesStruct{
+			private:     "",
+			Public_Kept: "",
+			S_Common:    "common",
+			S_Different: "",
+			A_Common:    []string{"first", "second"},
+			A_Different: []string(nil),
+			F_Common:    proptools.BoolPtr(false),
+			F_Different: nil,
+			EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
+				S_Embedded_Common:    "embedded_common",
+				S_Embedded_Different: "",
+			},
+		})
+
+	h.AssertDeepEquals("updated properties[0] not correct", structs[0],
+		&testPropertiesStruct{
+			private:     "common",
+			Public_Kept: "common",
+			S_Common:    "",
+			S_Different: "upper",
+			A_Common:    nil,
+			A_Different: []string{"alpha", "beta"},
+			F_Common:    nil,
+			F_Different: proptools.BoolPtr(false),
+			EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
+				S_Embedded_Common:    "",
+				S_Embedded_Different: "embedded_upper",
+			},
+		})
+
+	h.AssertDeepEquals("updated properties[1] not correct", structs[1],
+		&testPropertiesStruct{
+			private:     "common",
+			Public_Kept: "common",
+			S_Common:    "",
+			S_Different: "lower",
+			A_Common:    nil,
+			A_Different: []string{"alpha", "delta"},
+			F_Common:    nil,
+			F_Different: proptools.BoolPtr(true),
+			EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
+				S_Embedded_Common:    "",
+				S_Embedded_Different: "embedded_lower",
+			},
+		})
+}
diff --git a/sdk/testing.go b/sdk/testing.go
index 464c3ca..00245ce 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -19,6 +19,7 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"reflect"
 	"strings"
 	"testing"
 
@@ -176,6 +177,13 @@
 	h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual))
 }
 
+func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
+	h.t.Helper()
+	if !reflect.DeepEqual(actual, expected) {
+		h.t.Errorf("%s: expected %#v, actual %#v", message, expected, actual)
+	}
+}
+
 // Encapsulates result of processing an SDK definition. Provides support for
 // checking the state of the build structures.
 type testSdkResult struct {
diff --git a/sdk/update.go b/sdk/update.go
index a43a14b..779ba1a 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -20,6 +20,7 @@
 	"sort"
 	"strings"
 
+	"android/soong/apex"
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
@@ -225,17 +226,23 @@
 // the contents (header files, stub libraries, etc) into the zip file.
 func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) android.OutputPath {
 
-	exportedMembers := make(map[string]struct{})
+	allMembersByName := make(map[string]struct{})
+	exportedMembersByName := make(map[string]struct{})
 	var memberRefs []sdkMemberRef
 	for _, sdkVariant := range sdkVariants {
 		memberRefs = append(memberRefs, sdkVariant.memberRefs...)
 
+		// Record the names of all the members, both explicitly specified and implicitly
+		// included.
+		for _, memberRef := range sdkVariant.memberRefs {
+			allMembersByName[memberRef.variant.Name()] = struct{}{}
+		}
+
 		// Merge the exported member sets from all sdk variants.
 		for key, _ := range sdkVariant.getExportedMembers() {
-			exportedMembers[key] = struct{}{}
+			exportedMembersByName[key] = struct{}{}
 		}
 	}
-	s.exportedMembers = exportedMembers
 
 	snapshotDir := android.PathForModuleOut(ctx, "snapshot")
 
@@ -246,14 +253,16 @@
 	}
 
 	builder := &snapshotBuilder{
-		ctx:             ctx,
-		sdk:             s,
-		version:         "current",
-		snapshotDir:     snapshotDir.OutputPath,
-		copies:          make(map[string]string),
-		filesToZip:      []android.Path{bp.path},
-		bpFile:          bpFile,
-		prebuiltModules: make(map[string]*bpModule),
+		ctx:                   ctx,
+		sdk:                   s,
+		version:               "current",
+		snapshotDir:           snapshotDir.OutputPath,
+		copies:                make(map[string]string),
+		filesToZip:            []android.Path{bp.path},
+		bpFile:                bpFile,
+		prebuiltModules:       make(map[string]*bpModule),
+		allMembersByName:      allMembersByName,
+		exportedMembersByName: exportedMembersByName,
 	}
 	s.builderForTests = builder
 
@@ -330,7 +339,8 @@
 
 	// Extract the common lists of members into a separate struct.
 	commonDynamicMemberProperties := s.dynamicSdkMemberTypes.createMemberListProperties()
-	extractCommonProperties(commonDynamicMemberProperties, dynamicMemberPropertiesList)
+	extractor := newCommonValueExtractor(commonDynamicMemberProperties)
+	extractor.extractCommonProperties(commonDynamicMemberProperties, dynamicMemberPropertiesList)
 
 	// Add properties common to all os types.
 	s.addMemberPropertiesToPropertySet(builder, snapshotModule, commonDynamicMemberProperties)
@@ -400,7 +410,7 @@
 	for _, memberListProperty := range s.memberListProperties() {
 		names := memberListProperty.getter(dynamicMemberTypeListProperties)
 		if len(names) > 0 {
-			propertySet.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names))
+			propertySet.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names, false))
 		}
 	}
 }
@@ -409,7 +419,19 @@
 	name string
 }
 
-var sdkMemberReferencePropertyTag = propertyTag{"sdkMemberReferencePropertyTag"}
+// A BpPropertyTag to add to a property that contains references to other sdk members.
+//
+// This will cause the references to be rewritten to a versioned reference in the version
+// specific instance of a snapshot module.
+var requiredSdkMemberReferencePropertyTag = propertyTag{"requiredSdkMemberReferencePropertyTag"}
+var optionalSdkMemberReferencePropertyTag = propertyTag{"optionalSdkMemberReferencePropertyTag"}
+
+// A BpPropertyTag that indicates the property should only be present in the versioned
+// module.
+//
+// This will cause the property to be removed from the unversioned instance of a
+// snapshot module.
+var sdkVersionedOnlyPropertyTag = propertyTag{"sdkVersionedOnlyPropertyTag"}
 
 type unversionedToVersionedTransformation struct {
 	identityTransformation
@@ -420,14 +442,15 @@
 	// Use a versioned name for the module but remember the original name for the
 	// snapshot.
 	name := module.getValue("name").(string)
-	module.setProperty("name", t.builder.versionedSdkMemberName(name))
+	module.setProperty("name", t.builder.versionedSdkMemberName(name, true))
 	module.insertAfter("name", "sdk_member_name", name)
 	return module
 }
 
 func (t unversionedToVersionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
-	if tag == sdkMemberReferencePropertyTag {
-		return t.builder.versionedSdkMemberNames(value.([]string)), tag
+	if tag == requiredSdkMemberReferencePropertyTag || tag == optionalSdkMemberReferencePropertyTag {
+		required := tag == requiredSdkMemberReferencePropertyTag
+		return t.builder.versionedSdkMemberNames(value.([]string), required), tag
 	} else {
 		return value, tag
 	}
@@ -441,7 +464,7 @@
 func (t unversionedTransformation) transformModule(module *bpModule) *bpModule {
 	// If the module is an internal member then use a unique name for it.
 	name := module.getValue("name").(string)
-	module.setProperty("name", t.builder.unversionedSdkMemberName(name))
+	module.setProperty("name", t.builder.unversionedSdkMemberName(name, true))
 
 	// Set prefer: false - this is not strictly required as that is the default.
 	module.insertAfter("name", "prefer", false)
@@ -450,8 +473,12 @@
 }
 
 func (t unversionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
-	if tag == sdkMemberReferencePropertyTag {
-		return t.builder.unversionedSdkMemberNames(value.([]string)), tag
+	if tag == requiredSdkMemberReferencePropertyTag || tag == optionalSdkMemberReferencePropertyTag {
+		required := tag == requiredSdkMemberReferencePropertyTag
+		return t.builder.unversionedSdkMemberNames(value.([]string), required), tag
+	} else if tag == sdkVersionedOnlyPropertyTag {
+		// The property is not allowed in the unversioned module so remove it.
+		return nil, nil
 	} else {
 		return value, tag
 	}
@@ -483,41 +510,53 @@
 
 func outputPropertySet(contents *generatedContents, set *bpPropertySet) {
 	contents.Indent()
+
+	// Output the properties first, followed by the nested sets. This ensures a
+	// consistent output irrespective of whether property sets are created before
+	// or after the properties. This simplifies the creation of the module.
 	for _, name := range set.order {
 		value := set.getValue(name)
 
-		reflectedValue := reflect.ValueOf(value)
-		t := reflectedValue.Type()
-
-		kind := t.Kind()
-		switch kind {
-		case reflect.Slice:
-			length := reflectedValue.Len()
+		switch v := value.(type) {
+		case []string:
+			length := len(v)
 			if length > 1 {
 				contents.Printfln("%s: [", name)
 				contents.Indent()
 				for i := 0; i < length; i = i + 1 {
-					contents.Printfln("%q,", reflectedValue.Index(i).Interface())
+					contents.Printfln("%q,", v[i])
 				}
 				contents.Dedent()
 				contents.Printfln("],")
 			} else if length == 0 {
 				contents.Printfln("%s: [],", name)
 			} else {
-				contents.Printfln("%s: [%q],", name, reflectedValue.Index(0).Interface())
+				contents.Printfln("%s: [%q],", name, v[0])
 			}
-		case reflect.Bool:
-			contents.Printfln("%s: %t,", name, reflectedValue.Bool())
 
-		case reflect.Ptr:
-			contents.Printfln("%s: {", name)
-			outputPropertySet(contents, reflectedValue.Interface().(*bpPropertySet))
-			contents.Printfln("},")
+		case bool:
+			contents.Printfln("%s: %t,", name, v)
+
+		case *bpPropertySet:
+			// Do not write property sets in the properties phase.
 
 		default:
 			contents.Printfln("%s: %q,", name, value)
 		}
 	}
+
+	for _, name := range set.order {
+		value := set.getValue(name)
+
+		// Only write property sets in the sets phase.
+		switch v := value.(type) {
+		case *bpPropertySet:
+			contents.Printfln("%s: {", name)
+			outputPropertySet(contents, v)
+			contents.Printfln("},")
+		}
+	}
+
 	contents.Dedent()
 }
 
@@ -543,6 +582,12 @@
 
 	prebuiltModules map[string]*bpModule
 	prebuiltOrder   []*bpModule
+
+	// The set of all members by name.
+	allMembersByName map[string]struct{}
+
+	// The set of exported members by name.
+	exportedMembersByName map[string]struct{}
 }
 
 func (s *snapshotBuilder) CopyToSnapshot(src android.Path, dest string) {
@@ -596,7 +641,7 @@
 
 	variant := member.Variants()[0]
 
-	if s.sdk.isInternalMember(name) {
+	if s.isInternalMember(name) {
 		// An internal member is only referenced from the sdk snapshot which is in the
 		// same package so can be marked as private.
 		m.AddProperty("visibility", []string{"//visibility:private"})
@@ -626,11 +671,26 @@
 	// Where available copy apex_available properties from the member.
 	if apexAware, ok := variant.(interface{ ApexAvailable() []string }); ok {
 		apexAvailable := apexAware.ApexAvailable()
+
+		// Add in any white listed apex available settings.
+		apexAvailable = append(apexAvailable, apex.WhitelistedApexAvailable(member.Name())...)
+
 		if len(apexAvailable) > 0 {
+			// Remove duplicates and sort.
+			apexAvailable = android.FirstUniqueStrings(apexAvailable)
+			sort.Strings(apexAvailable)
+
 			m.AddProperty("apex_available", apexAvailable)
 		}
 	}
 
+	// Disable installation in the versioned module of those modules that are ever installable.
+	if installable, ok := variant.(interface{ EverInstallable() bool }); ok {
+		if installable.EverInstallable() {
+			m.AddPropertyWithTag("installable", false, sdkVersionedOnlyPropertyTag)
+		}
+	}
+
 	s.prebuiltModules[name] = m
 	s.prebuiltOrder = append(s.prebuiltOrder, m)
 	return m
@@ -645,40 +705,66 @@
 	}
 }
 
-func (s *snapshotBuilder) SdkMemberReferencePropertyTag() android.BpPropertyTag {
-	return sdkMemberReferencePropertyTag
+func (s *snapshotBuilder) SdkMemberReferencePropertyTag(required bool) android.BpPropertyTag {
+	if required {
+		return requiredSdkMemberReferencePropertyTag
+	} else {
+		return optionalSdkMemberReferencePropertyTag
+	}
+}
+
+func (s *snapshotBuilder) OptionalSdkMemberReferencePropertyTag() android.BpPropertyTag {
+	return optionalSdkMemberReferencePropertyTag
 }
 
 // Get a versioned name appropriate for the SDK snapshot version being taken.
-func (s *snapshotBuilder) versionedSdkMemberName(unversionedName string) string {
+func (s *snapshotBuilder) versionedSdkMemberName(unversionedName string, required bool) string {
+	if _, ok := s.allMembersByName[unversionedName]; !ok {
+		if required {
+			s.ctx.ModuleErrorf("Required member reference %s is not a member of the sdk", unversionedName)
+		}
+		return unversionedName
+	}
 	return versionedSdkMemberName(s.ctx, unversionedName, s.version)
 }
 
-func (s *snapshotBuilder) versionedSdkMemberNames(members []string) []string {
+func (s *snapshotBuilder) versionedSdkMemberNames(members []string, required bool) []string {
 	var references []string = nil
 	for _, m := range members {
-		references = append(references, s.versionedSdkMemberName(m))
+		references = append(references, s.versionedSdkMemberName(m, required))
 	}
 	return references
 }
 
 // Get an internal name unique to the sdk.
-func (s *snapshotBuilder) unversionedSdkMemberName(unversionedName string) string {
-	if s.sdk.isInternalMember(unversionedName) {
+func (s *snapshotBuilder) unversionedSdkMemberName(unversionedName string, required bool) string {
+	if _, ok := s.allMembersByName[unversionedName]; !ok {
+		if required {
+			s.ctx.ModuleErrorf("Required member reference %s is not a member of the sdk", unversionedName)
+		}
+		return unversionedName
+	}
+
+	if s.isInternalMember(unversionedName) {
 		return s.ctx.ModuleName() + "_" + unversionedName
 	} else {
 		return unversionedName
 	}
 }
 
-func (s *snapshotBuilder) unversionedSdkMemberNames(members []string) []string {
+func (s *snapshotBuilder) unversionedSdkMemberNames(members []string, required bool) []string {
 	var references []string = nil
 	for _, m := range members {
-		references = append(references, s.unversionedSdkMemberName(m))
+		references = append(references, s.unversionedSdkMemberName(m, required))
 	}
 	return references
 }
 
+func (s *snapshotBuilder) isInternalMember(memberName string) bool {
+	_, ok := s.exportedMembersByName[memberName]
+	return !ok
+}
+
 type sdkMemberRef struct {
 	memberType android.SdkMemberType
 	variant    android.SdkAware
@@ -746,6 +832,9 @@
 	// The set of properties that are common across all architectures and os types.
 	commonProperties := createVariantPropertiesStruct(android.CommonOS)
 
+	// Create common value extractor that can be used to optimize the properties.
+	commonValueExtractor := newCommonValueExtractor(commonProperties)
+
 	// The list of property structures which are os type specific but common across
 	// architectures within that os type.
 	var osSpecificPropertiesList []android.SdkMemberProperties
@@ -794,7 +883,7 @@
 				archPropertiesList = append(archPropertiesList, archInfo.Properties)
 			}
 
-			extractCommonProperties(osInfo.Properties, archPropertiesList)
+			commonValueExtractor.extractCommonProperties(osInfo.Properties, archPropertiesList)
 
 			// Choose setting for compile_multilib that is appropriate for the arch variants supplied.
 			var multilib string
@@ -815,7 +904,7 @@
 	}
 
 	// Extract properties which are common across all architectures and os types.
-	extractCommonProperties(commonProperties, osSpecificPropertiesList)
+	commonValueExtractor.extractCommonProperties(commonProperties, osSpecificPropertiesList)
 
 	// Add the common properties to the module.
 	commonProperties.AddToPropertySet(sdkModuleContext, builder, bpModule)
@@ -894,8 +983,6 @@
 			}
 		}
 	}
-
-	memberType.FinalizeModule(sdkModuleContext, builder, member, bpModule)
 }
 
 // Compute the list of possible os types that this sdk could support.
@@ -917,6 +1004,90 @@
 	return osTypes
 }
 
+// Given a struct value, access a field within that struct (or one of its embedded
+// structs).
+type fieldAccessorFunc func(structValue reflect.Value) reflect.Value
+
+// Supports extracting common values from a number of instances of a properties
+// structure into a separate common set of properties.
+type commonValueExtractor struct {
+	// The getters for every field from which common values can be extracted.
+	fieldGetters []fieldAccessorFunc
+}
+
+// Create a new common value extractor for the structure type for the supplied
+// properties struct.
+//
+// The returned extractor can be used on any properties structure of the same type
+// as the supplied set of properties.
+func newCommonValueExtractor(propertiesStruct interface{}) *commonValueExtractor {
+	structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type()
+	extractor := &commonValueExtractor{}
+	extractor.gatherFields(structType, nil)
+	return extractor
+}
+
+// Gather the fields from the supplied structure type from which common values will
+// be extracted.
+//
+// This is recursive function. If it encounters an embedded field (no field name)
+// that is a struct then it will recurse into that struct passing in the accessor
+// for the field. That will then be used in the accessors for the fields in the
+// embedded struct.
+func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc) {
+	for f := 0; f < structType.NumField(); f++ {
+		field := structType.Field(f)
+		if field.PkgPath != "" {
+			// Ignore unexported fields.
+			continue
+		}
+
+		// Ignore fields whose value should be kept.
+		if proptools.HasTag(field, "sdk", "keep") {
+			continue
+		}
+
+		// Save a copy of the field index for use in the function.
+		fieldIndex := f
+		fieldGetter := func(value reflect.Value) reflect.Value {
+			if containingStructAccessor != nil {
+				// This is an embedded structure so first access the field for the embedded
+				// structure.
+				value = containingStructAccessor(value)
+			}
+
+			// Skip through interface and pointer values to find the structure.
+			value = getStructValue(value)
+
+			// Return the field.
+			return value.Field(fieldIndex)
+		}
+
+		if field.Type.Kind() == reflect.Struct && field.Anonymous {
+			// Gather fields from the embedded structure.
+			e.gatherFields(field.Type, fieldGetter)
+		} else {
+			e.fieldGetters = append(e.fieldGetters, fieldGetter)
+		}
+	}
+}
+
+func getStructValue(value reflect.Value) reflect.Value {
+foundStruct:
+	for {
+		kind := value.Kind()
+		switch kind {
+		case reflect.Interface, reflect.Ptr:
+			value = value.Elem()
+		case reflect.Struct:
+			break foundStruct
+		default:
+			panic(fmt.Errorf("expecting struct, interface or pointer, found %v of kind %s", value, kind))
+		}
+	}
+	return value
+}
+
 // Extract common properties from a slice of property structures of the same type.
 //
 // All the property structures must be of the same type.
@@ -927,7 +1098,7 @@
 // have the same value (using DeepEquals) across all the input properties. If it does not then no
 // change is made. Otherwise, the common value is stored in the field in the commonProperties
 // and the field in each of the input properties structure is set to its default value.
-func extractCommonProperties(commonProperties interface{}, inputPropertiesSlice interface{}) {
+func (e *commonValueExtractor) extractCommonProperties(commonProperties interface{}, inputPropertiesSlice interface{}) {
 	commonPropertiesValue := reflect.ValueOf(commonProperties)
 	commonStructValue := commonPropertiesValue.Elem()
 	propertiesStructType := commonStructValue.Type()
@@ -935,25 +1106,16 @@
 	// Create an empty structure from which default values for the field can be copied.
 	emptyStructValue := reflect.New(propertiesStructType).Elem()
 
-	for f := 0; f < propertiesStructType.NumField(); f++ {
+	for _, fieldGetter := range e.fieldGetters {
 		// Check to see if all the structures have the same value for the field. The commonValue
 		// is nil on entry to the loop and if it is nil on exit then there is no common value,
 		// otherwise it points to the common value.
 		var commonValue *reflect.Value
 		sliceValue := reflect.ValueOf(inputPropertiesSlice)
 
-		field := propertiesStructType.Field(f)
-		if field.Name == "SdkMemberPropertiesBase" {
-			continue
-		}
-
 		for i := 0; i < sliceValue.Len(); i++ {
-			structValue := sliceValue.Index(i).Elem().Elem()
-			fieldValue := structValue.Field(f)
-			if !fieldValue.CanInterface() {
-				// The field is not exported so ignore it.
-				continue
-			}
+			itemValue := sliceValue.Index(i)
+			fieldValue := fieldGetter(itemValue)
 
 			if commonValue == nil {
 				// Use the first value as the commonProperties value.
@@ -971,11 +1133,11 @@
 		// If the fields all have a common value then store it in the common struct field
 		// and set the input struct's field to the empty value.
 		if commonValue != nil {
-			emptyValue := emptyStructValue.Field(f)
-			commonStructValue.Field(f).Set(*commonValue)
+			emptyValue := fieldGetter(emptyStructValue)
+			fieldGetter(commonStructValue).Set(*commonValue)
 			for i := 0; i < sliceValue.Len(); i++ {
-				structValue := sliceValue.Index(i).Elem().Elem()
-				fieldValue := structValue.Field(f)
+				itemValue := sliceValue.Index(i)
+				fieldValue := fieldGetter(itemValue)
 				fieldValue.Set(emptyValue)
 			}
 		}
diff --git a/ui/build/config.go b/ui/build/config.go
index 5b9d10a..55e0d03 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -611,10 +611,6 @@
 		product = "aosp_arm"
 	case "arm64":
 		product = "aosm_arm64"
-	case "mips":
-		product = "aosp_mips"
-	case "mips64":
-		product = "aosp_mips64"
 	case "x86":
 		product = "aosp_x86"
 	case "x86_64":
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 0749fe3..4fc1f01 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -38,6 +38,7 @@
 	executable := config.PrebuiltBuildTool("ninja")
 	args := []string{
 		"-d", "keepdepfile",
+		"-d", "keeprsp",
 		"--frontend_file", fifo,
 	}