Merge "Revert "Share vdex files in the ART apex between architectures (...""
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 eb79123..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
 }
 
@@ -207,7 +208,7 @@
 }
 
 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) {
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/prebuilt.go b/android/prebuilt.go
index 2d16f65..c902ec8 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -50,12 +50,9 @@
 
 type Prebuilt struct {
 	properties PrebuiltProperties
-	module     Module
-	srcs       *[]string
 
-	// Metadata for single source Prebuilt modules.
-	srcProps reflect.Value
-	srcField reflect.StructField
+	srcsSupplier     PrebuiltSrcsSupplier
+	srcsPropertyName string
 }
 
 func (p *Prebuilt) Name(name string) string {
@@ -72,31 +69,26 @@
 // preference configs. We'll want to add native support for dynamic source cases if we end up having
 // more modules like this.
 func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
-	if p.srcs != nil {
-		if len(*p.srcs) == 0 {
-			ctx.PropertyErrorf("srcs", "missing prebuilt source file")
+	if p.srcsSupplier != nil {
+		srcs := p.srcsSupplier()
+
+		if len(srcs) == 0 {
+			ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
 			return nil
 		}
 
-		if len(*p.srcs) > 1 {
-			ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
+		if len(srcs) > 1 {
+			ctx.PropertyErrorf(p.srcsPropertyName, "multiple prebuilt source files")
 			return nil
 		}
 
 		// Return the singleton source after expanding any filegroup in the
 		// sources.
-		return PathForModuleSrc(ctx, (*p.srcs)[0])
-	} else {
-		if !p.srcProps.IsValid() {
-			ctx.ModuleErrorf("prebuilt source was not set")
-		}
-		src := p.getSingleSourceFieldValue()
-		if src == "" {
-			ctx.PropertyErrorf(proptools.FieldNameForProperty(p.srcField.Name),
-				"missing prebuilt source file")
-			return nil
-		}
+		src := srcs[0]
 		return PathForModuleSrc(ctx, src)
+	} else {
+		ctx.ModuleErrorf("prebuilt source was not set")
+		return nil
 	}
 }
 
@@ -104,18 +96,80 @@
 	return p.properties.UsePrebuilt
 }
 
-func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
+// Called to provide the srcs value for the prebuilt module.
+//
+// Return the src value or nil if it is not available.
+type PrebuiltSrcsSupplier func() []string
+
+// Initialize the module as a prebuilt module that uses the provided supplier to access the
+// prebuilt sources of the module.
+//
+// The supplier will be called multiple times and must return the same values each time it
+// is called. If it returns an empty array (or nil) then the prebuilt module will not be used
+// as a replacement for a source module with the same name even if prefer = true.
+//
+// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array
+// containing exactly one source file.
+//
+// The provided property name is used to provide helpful error messages in the event that
+// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided.
+func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) {
 	p := module.Prebuilt()
 	module.AddProperties(&p.properties)
-	p.srcs = srcs
+
+	if srcsSupplier == nil {
+		panic(fmt.Errorf("srcsSupplier must not be nil"))
+	}
+	if srcsPropertyName == "" {
+		panic(fmt.Errorf("srcsPropertyName must not be empty"))
+	}
+
+	p.srcsSupplier = srcsSupplier
+	p.srcsPropertyName = srcsPropertyName
+}
+
+func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
+	if srcs == nil {
+		panic(fmt.Errorf("srcs must not be nil"))
+	}
+
+	srcsSupplier := func() []string {
+		return *srcs
+	}
+
+	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
 }
 
 func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
-	p := module.Prebuilt()
-	module.AddProperties(&p.properties)
-	p.srcProps = reflect.ValueOf(srcProps).Elem()
-	p.srcField, _ = p.srcProps.Type().FieldByName(srcField)
-	p.checkSingleSourceProperties()
+	srcPropsValue := reflect.ValueOf(srcProps).Elem()
+	srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
+	if !srcPropsValue.IsValid() || srcStructField.Name == "" {
+		panic(fmt.Errorf("invalid single source prebuilt %+v", module))
+	}
+
+	if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface {
+		panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps))
+	}
+
+	srcFieldIndex := srcStructField.Index
+	srcPropertyName := proptools.PropertyNameForField(srcField)
+
+	srcsSupplier := func() []string {
+		value := srcPropsValue.FieldByIndex(srcFieldIndex)
+		if value.Kind() == reflect.Ptr {
+			value = value.Elem()
+		}
+		if value.Kind() != reflect.String {
+			panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one but was %d %q", srcPropertyName, value.Kind(), value))
+		}
+		src := value.String()
+		if src == "" {
+			return nil
+		}
+		return []string{src}
+	}
+
+	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName)
 }
 
 type PrebuiltInterface interface {
@@ -152,7 +206,7 @@
 func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
 	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
 		p := m.Prebuilt()
-		if p.srcs == nil && !p.srcProps.IsValid() {
+		if p.srcsSupplier == nil {
 			panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
 		}
 		if !p.properties.SourceExists {
@@ -191,11 +245,7 @@
 // usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
 // will be used if it is marked "prefer" or if the source module is disabled.
 func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
-	if p.srcs != nil && len(*p.srcs) == 0 {
-		return false
-	}
-
-	if p.srcProps.IsValid() && p.getSingleSourceFieldValue() == "" {
+	if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 {
 		return false
 	}
 
@@ -210,24 +260,3 @@
 func (p *Prebuilt) SourceExists() bool {
 	return p.properties.SourceExists
 }
-
-func (p *Prebuilt) checkSingleSourceProperties() {
-	if !p.srcProps.IsValid() || p.srcField.Name == "" {
-		panic(fmt.Errorf("invalid single source prebuilt %+v", p))
-	}
-
-	if p.srcProps.Kind() != reflect.Struct && p.srcProps.Kind() != reflect.Interface {
-		panic(fmt.Errorf("invalid single source prebuilt %+v", p.srcProps))
-	}
-}
-
-func (p *Prebuilt) getSingleSourceFieldValue() string {
-	value := p.srcProps.FieldByIndex(p.srcField.Index)
-	if value.Kind() == reflect.Ptr {
-		value = value.Elem()
-	}
-	if value.Kind() != reflect.String {
-		panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one", p.srcField.Name))
-	}
-	return value.String()
-}
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 cddd72b..46aaa8b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -126,7 +126,6 @@
 		"libpcre2",
 		"libprocessgroup_headers",
 		"libqemu_pipe",
-		"libselinux",
 		"libsystem_headers",
 		"libutils_headers",
 	}
@@ -524,7 +523,6 @@
 		"libprocessgroup",
 		"libprocessgroup_headers",
 		"libprocinfo",
-		"libselinux",
 		"libsonivox",
 		"libspeexresampler",
 		"libspeexresampler",
@@ -1059,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 {
@@ -1307,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
@@ -1359,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
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1f395b6..5468c77 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -168,6 +168,7 @@
 		"vendor/foo/devkeys/testkey.pem":             nil,
 		"NOTICE":                                     nil,
 		"custom_notice":                              nil,
+		"custom_notice_for_static_lib":               nil,
 		"testkey2.avbpubkey":                         nil,
 		"testkey2.pem":                               nil,
 		"myapex-arm64.apex":                          nil,
@@ -372,6 +373,20 @@
 			system_shared_libs: [],
 			stl: "none",
 			notice: "custom_notice",
+			static_libs: ["libstatic"],
+			// TODO: remove //apex_available:platform
+			apex_available: [
+				"//apex_available:platform",
+				"myapex",
+			],
+		}
+
+		cc_library_static {
+			name: "libstatic",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			notice: "custom_notice_for_static_lib",
 			// TODO: remove //apex_available:platform
 			apex_available: [
 				"//apex_available:platform",
@@ -470,11 +485,12 @@
 
 	mergeNoticesRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("mergeNoticesRule")
 	noticeInputs := mergeNoticesRule.Inputs.Strings()
-	if len(noticeInputs) != 2 {
-		t.Errorf("number of input notice files: expected = 2, actual = %q", len(noticeInputs))
+	if len(noticeInputs) != 3 {
+		t.Errorf("number of input notice files: expected = 3, actual = %q", len(noticeInputs))
 	}
 	ensureListContains(t, noticeInputs, "NOTICE")
 	ensureListContains(t, noticeInputs, "custom_notice")
+	ensureListContains(t, noticeInputs, "custom_notice_for_static_lib")
 
 	depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("myapex-deps-info.txt").Args["content"], "\\n")
 	ensureListContains(t, depsInfo, "myjar <- myapex")
@@ -1763,6 +1779,7 @@
 			name: "otherapex",
 			key: "myapex.key",
 			native_shared_libs: ["mylib", "mylib2"],
+			min_sdk_version: "29",
 		}
 
 		apex_key {
@@ -1797,15 +1814,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 +3680,7 @@
 			apps: ["override_app"],
 			overrides: ["unknownapex"],
 			logging_parent: "com.foo.bar",
+			package_name: "test.overridden.package",
 		}
 
 		apex_key {
@@ -3711,7 +3732,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 +3754,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..67bc206 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")
@@ -226,19 +228,15 @@
 }
 
 func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName string) android.NoticeOutputs {
-	noticeFiles := []android.Path{}
-	for _, f := range a.filesInfo {
-		if f.module != nil {
-			notices := f.module.NoticeFiles()
-			if len(notices) > 0 {
-				noticeFiles = append(noticeFiles, notices...)
-			}
+	var noticeFiles android.Paths
+
+	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+		if externalDep {
+			return
 		}
-	}
-	// append the notice file specified in the apex module itself
-	if len(a.NoticeFiles()) > 0 {
-		noticeFiles = append(noticeFiles, a.NoticeFiles()...)
-	}
+		notices := to.NoticeFiles()
+		noticeFiles = append(noticeFiles, notices...)
+	})
 
 	if len(noticeFiles) == 0 {
 		return android.NoticeOutputs{}
@@ -354,7 +352,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 +451,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 +482,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 +495,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 +654,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 4310a36..61ae10a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -292,6 +292,7 @@
 	staticBinary() bool
 	header() bool
 	toolchain() config.Toolchain
+	canUseSdk() bool
 	useSdk() bool
 	sdkVersion() string
 	useVndk() bool
@@ -315,6 +316,7 @@
 	useClangLld(actx ModuleContext) bool
 	isForPlatform() bool
 	apexName() string
+	apexSdkVersion() int
 	hasStubsVariants() bool
 	isStubs() bool
 	bootstrap() bool
@@ -368,6 +370,15 @@
 
 	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 {
@@ -1048,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
@@ -1182,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()
 }
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/library.go b/cc/library.go
index 47ac7b0..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 {
 
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/prebuilt.go b/cc/prebuilt.go
index 2c18ac3..7f21721 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -23,6 +23,7 @@
 }
 
 func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("cc_prebuilt_library", PrebuiltLibraryFactory)
 	ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
 	ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
 	ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
@@ -96,10 +97,16 @@
 	p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
 
 	// TODO(ccross): verify shared library dependencies
-	if len(p.properties.Srcs) > 0 {
+	srcs := p.prebuiltSrcs()
+	if len(srcs) > 0 {
 		builderFlags := flagsToBuilderFlags(flags)
 
-		in := p.Prebuilt.SingleSourcePath(ctx)
+		if len(srcs) > 1 {
+			ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
+			return nil
+		}
+
+		in := android.PathForModuleSrc(ctx, srcs[0])
 
 		if p.shared() {
 			p.unstrippedOutputFile = in
@@ -123,6 +130,18 @@
 	return nil
 }
 
+func (p *prebuiltLibraryLinker) prebuiltSrcs() []string {
+	srcs := p.properties.Srcs
+	if p.static() {
+		srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs...)
+	}
+	if p.shared() {
+		srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs...)
+	}
+
+	return srcs
+}
+
 func (p *prebuiltLibraryLinker) shared() bool {
 	return p.libraryDecorator.shared()
 }
@@ -146,13 +165,28 @@
 
 	module.AddProperties(&prebuilt.properties)
 
-	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
+	srcsSupplier := func() []string {
+		return prebuilt.prebuiltSrcs()
+	}
+
+	android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
 
 	// Prebuilt libraries can be used in SDKs.
 	android.InitSdkAwareModule(module)
 	return module, library
 }
 
+// cc_prebuilt_library installs a precompiled shared library that are
+// listed in the srcs property in the device's directory.
+func PrebuiltLibraryFactory() android.Module {
+	module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+
+	// Prebuilt shared libraries can be included in APEXes
+	android.InitApexModule(module)
+
+	return module.Init()
+}
+
 // cc_prebuilt_library_shared installs a precompiled shared library that are
 // listed in the srcs property in the device's directory.
 func PrebuiltSharedLibraryFactory() android.Module {
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 3d809fc..0eca97f 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -59,36 +59,38 @@
 			name: "libe",
 			srcs: ["libe.a"],
 		}
+
+		cc_library {
+			name: "libf",
+		}
+
+		cc_prebuilt_library {
+			name: "libf",
+			static: {
+				srcs: ["libf.a"],
+			},
+			shared: {
+				srcs: ["libf.so"],
+			},
+		}
 	`
 
-	fs := map[string][]byte{
-		"liba.so": nil,
-		"libb.a":  nil,
-		"libd.so": nil,
-		"libe.a":  nil,
-	}
-
-	config := TestConfig(buildDir, android.Android, nil, bp, fs)
-
-	ctx := CreateTestContext()
-
-	ctx.Register(config)
-
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
+	ctx := testPrebuilt(t, bp)
 
 	// Verify that all the modules exist and that their dependencies were connected correctly
 	liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
 	libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
 	libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
 	libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
+	libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
+	libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
 
 	prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
 	prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
 	prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
 	prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
+	prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
+	prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
 
 	hasDep := func(m android.Module, wantDep android.Module) bool {
 		t.Helper()
@@ -116,4 +118,89 @@
 	if !hasDep(libe, prebuiltLibe) {
 		t.Errorf("libe missing dependency on prebuilt_libe")
 	}
+
+	if !hasDep(libfStatic, prebuiltLibfStatic) {
+		t.Errorf("libf static missing dependency on prebuilt_libf")
+	}
+
+	if !hasDep(libfShared, prebuiltLibfShared) {
+		t.Errorf("libf shared missing dependency on prebuilt_libf")
+	}
+}
+
+func testPrebuilt(t *testing.T, bp string) *android.TestContext {
+	fs := map[string][]byte{
+		"liba.so": nil,
+		"libb.a":  nil,
+		"libd.so": nil,
+		"libe.a":  nil,
+		"libf.a":  nil,
+		"libf.so": nil,
+	}
+	config := TestConfig(buildDir, android.Android, nil, bp, fs)
+	ctx := CreateTestContext()
+
+	// Enable androidmk support.
+	// * Register the singleton
+	// * Configure that we are inside make
+	// * Add CommonOS to ensure that androidmk processing works.
+	android.RegisterAndroidMkBuildComponents(ctx)
+	android.SetInMakeForTests(config)
+
+	ctx.Register(config)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+	return ctx
+}
+
+func TestPrebuiltLibraryShared(t *testing.T) {
+	ctx := testPrebuilt(t, `
+	cc_prebuilt_library_shared {
+		name: "libtest",
+		srcs: ["libf.so"],
+    strip: {
+        none: true,
+    },
+	}
+	`)
+
+	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
+	assertString(t, shared.OutputFile().String(), "libf.so")
+}
+
+func TestPrebuiltLibraryStatic(t *testing.T) {
+	ctx := testPrebuilt(t, `
+	cc_prebuilt_library_static {
+		name: "libtest",
+		srcs: ["libf.a"],
+	}
+	`)
+
+	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+	assertString(t, static.OutputFile().String(), "libf.a")
+}
+
+func TestPrebuiltLibrary(t *testing.T) {
+	ctx := testPrebuilt(t, `
+	cc_prebuilt_library {
+		name: "libtest",
+		static: {
+			srcs: ["libf.a"],
+		},
+		shared: {
+			srcs: ["libf.so"],
+		},
+    strip: {
+        none: true,
+    },
+	}
+	`)
+
+	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
+	assertString(t, shared.OutputFile().String(), "libf.so")
+
+	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+	assertString(t, static.OutputFile().String(), "libf.a")
 }
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 252c9e7..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
 	}
@@ -1000,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
@@ -1026,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.
@@ -1063,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 7ccf828..a3b264e 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:
 //
@@ -547,7 +546,11 @@
 	var allPhonies android.Paths
 	for _, image := range image.variants {
 		arch := image.target.Arch.ArchType
-		suffix := image.target.String()
+		suffix := arch.String()
+		// Host and target might both use x86 arch. We need to ensure the names are unique.
+		if image.target.Os.Class == android.Host {
+			suffix = "host-" + suffix
+		}
 		// Create a rule to call oatdump.
 		output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
 		rule := android.NewRuleBuilder()
@@ -570,7 +573,10 @@
 			Text("echo").FlagWithArg("Output in ", output.String())
 		rule.Build(pctx, ctx, "phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
 
-		allPhonies = append(allPhonies, phony)
+		// TODO: We need to make imageLocations per-variant to make oatdump work on host.
+		if image.target.Os == android.Android {
+			allPhonies = append(allPhonies, phony)
+		}
 	}
 
 	phony := android.PathForPhony(ctx, "dump-oat-boot")
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 2b0fd3c..6f9dc3c 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -298,6 +298,7 @@
     name: "mysdk_mynativelib@current",
     sdk_member_name: "mynativelib",
     installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -308,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: {
@@ -325,8 +325,6 @@
             srcs: ["arm/lib/mynativelib.so"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -543,6 +541,7 @@
         "apex2",
     ],
     installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -554,8 +553,6 @@
             export_include_dirs: ["arm/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_shared {
@@ -565,6 +562,7 @@
         "apex1",
         "apex2",
     ],
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -576,8 +574,6 @@
             export_include_dirs: ["arm/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -599,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)
@@ -640,6 +819,7 @@
     host_supported: true,
     installable: false,
     sdk_version: "minimum",
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -651,8 +831,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_shared {
@@ -661,6 +839,7 @@
     device_supported: false,
     host_supported: true,
     sdk_version: "minimum",
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -672,8 +851,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -741,6 +918,7 @@
     device_supported: false,
     host_supported: true,
     installable: false,
+    stl: "none",
     target: {
         linux_glibc_x86_64: {
             srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
@@ -752,8 +930,6 @@
             srcs: ["windows/x86_64/lib/mynativelib.dll"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_shared {
@@ -761,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"],
@@ -772,8 +949,6 @@
             srcs: ["windows/x86_64/lib/mynativelib.dll"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 sdk_snapshot {
@@ -821,6 +996,7 @@
     name: "myexports_mynativelib@current",
     sdk_member_name: "mynativelib",
     installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         arm64: {
@@ -832,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: {
@@ -850,8 +1025,6 @@
             export_include_dirs: ["arm/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 module_exports_snapshot {
@@ -912,6 +1085,7 @@
     device_supported: false,
     host_supported: true,
     installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -923,8 +1097,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_static {
@@ -932,6 +1104,7 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -943,8 +1116,6 @@
             export_include_dirs: ["x86/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 module_exports_snapshot {
@@ -1012,6 +1183,7 @@
     device_supported: false,
     host_supported: true,
     installable: false,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -1019,8 +1191,6 @@
             export_include_dirs: ["x86_64/include_gen/mynativelib"],
         },
     },
-    stl: "none",
-    system_shared_libs: [],
 }
 
 cc_prebuilt_library_static {
@@ -1028,6 +1198,7 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
+    stl: "none",
     export_include_dirs: ["include/include"],
     arch: {
         x86_64: {
@@ -1035,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
@@ -1082,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 {
@@ -1137,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 {
@@ -1147,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 {
@@ -1201,6 +1366,7 @@
     name: "mysdk_mynativeheaders@current",
     sdk_member_name: "mynativeheaders",
     host_supported: true,
+    stl: "none",
     export_system_include_dirs: ["include/include"],
     target: {
         android: {
@@ -1210,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: {
@@ -1227,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 1a631dd..c622ddf 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -226,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")
 
@@ -247,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
 
@@ -402,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))
 		}
 	}
 }
@@ -415,7 +423,8 @@
 //
 // This will cause the references to be rewritten to a versioned reference in the version
 // specific instance of a snapshot module.
-var sdkMemberReferencePropertyTag = propertyTag{"sdkMemberReferencePropertyTag"}
+var requiredSdkMemberReferencePropertyTag = propertyTag{"requiredSdkMemberReferencePropertyTag"}
+var optionalSdkMemberReferencePropertyTag = propertyTag{"optionalSdkMemberReferencePropertyTag"}
 
 // A BpPropertyTag that indicates the property should only be present in the versioned
 // module.
@@ -433,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
 	}
@@ -454,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)
@@ -463,8 +473,9 @@
 }
 
 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
@@ -499,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()
 }
 
@@ -559,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) {
@@ -612,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"})
@@ -676,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
@@ -738,11 +793,168 @@
 type osTypeSpecificInfo struct {
 	baseInfo
 
-	// The list of arch type specific info for this os type.
-	archTypes []*archTypeSpecificInfo
+	osType android.OsType
 
-	// True if the member has common arch variants for this os type.
-	commonArch bool
+	// The list of arch type specific info for this os type.
+	//
+	// Nil if there is one variant whose arch type is common
+	archInfos []*archTypeSpecificInfo
+}
+
+type variantPropertiesFactoryFunc func() android.SdkMemberProperties
+
+// Create a new osTypeSpecificInfo for the specified os type and its properties
+// structures populated with information from the variants.
+func newOsTypeSpecificInfo(osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, osTypeVariants []android.SdkAware) *osTypeSpecificInfo {
+	osInfo := &osTypeSpecificInfo{
+		osType: osType,
+	}
+
+	osSpecificVariantPropertiesFactory := func() android.SdkMemberProperties {
+		properties := variantPropertiesFactory()
+		properties.Base().Os = osType
+		return properties
+	}
+
+	// Create a structure into which properties common across the architectures in
+	// this os type will be stored.
+	osInfo.Properties = osSpecificVariantPropertiesFactory()
+
+	// Group the variants by arch type.
+	var variantsByArchName = make(map[string][]android.SdkAware)
+	var archTypes []android.ArchType
+	for _, variant := range osTypeVariants {
+		archType := variant.Target().Arch.ArchType
+		archTypeName := archType.Name
+		if _, ok := variantsByArchName[archTypeName]; !ok {
+			archTypes = append(archTypes, archType)
+		}
+
+		variantsByArchName[archTypeName] = append(variantsByArchName[archTypeName], variant)
+	}
+
+	if commonVariants, ok := variantsByArchName["common"]; ok {
+		if len(osTypeVariants) != 1 {
+			panic("Expected to only have 1 variant when arch type is common but found " + string(len(osTypeVariants)))
+		}
+
+		// A common arch type only has one variant and its properties should be treated
+		// as common to the os type.
+		osInfo.Properties.PopulateFromVariant(commonVariants[0])
+	} else {
+		// Create an arch specific info for each supported architecture type.
+		for _, archType := range archTypes {
+			archTypeName := archType.Name
+
+			archVariants := variantsByArchName[archTypeName]
+			archInfo := newArchSpecificInfo(archType, osSpecificVariantPropertiesFactory, archVariants)
+
+			osInfo.archInfos = append(osInfo.archInfos, archInfo)
+		}
+	}
+
+	return osInfo
+}
+
+// Optimize the properties by extracting common properties from arch type specific
+// properties into os type specific properties.
+func (osInfo *osTypeSpecificInfo) optimizeProperties(commonValueExtractor *commonValueExtractor) {
+	// Nothing to do if there is only a single common architecture.
+	if len(osInfo.archInfos) == 0 {
+		return
+	}
+
+	var archPropertiesList []android.SdkMemberProperties
+	for _, archInfo := range osInfo.archInfos {
+		archPropertiesList = append(archPropertiesList, archInfo.Properties)
+	}
+
+	commonValueExtractor.extractCommonProperties(osInfo.Properties, archPropertiesList)
+
+	// Choose setting for compile_multilib that is appropriate for the arch variants supplied.
+	var multilib string
+	archVariantCount := len(osInfo.archInfos)
+	if archVariantCount == 2 {
+		multilib = "both"
+	} else if archVariantCount == 1 {
+		if strings.HasSuffix(osInfo.archInfos[0].archType.Name, "64") {
+			multilib = "64"
+		} else {
+			multilib = "32"
+		}
+	}
+
+	osInfo.Properties.Base().Compile_multilib = multilib
+}
+
+// Add the properties for an os to a property set.
+//
+// Maps the properties related to the os variants through to an appropriate
+// module structure that will produce equivalent set of variants when it is
+// processed in a build.
+func (osInfo *osTypeSpecificInfo) addToPropertySet(
+	builder *snapshotBuilder,
+	bpModule android.BpModule,
+	targetPropertySet android.BpPropertySet) {
+
+	var osPropertySet android.BpPropertySet
+	var archPropertySet android.BpPropertySet
+	var archOsPrefix string
+	if osInfo.Properties.Base().Os_count == 1 {
+		// There is only one os type present in the variants so don't bother
+		// with adding target specific properties.
+
+		// Create a structure that looks like:
+		// module_type {
+		//   name: "...",
+		//   ...
+		//   <common properties>
+		//   ...
+		//   <single os type specific properties>
+		//
+		//   arch: {
+		//     <arch specific sections>
+		//   }
+		//
+		osPropertySet = bpModule
+		archPropertySet = osPropertySet.AddPropertySet("arch")
+
+		// Arch specific properties need to be added to an arch specific section
+		// within arch.
+		archOsPrefix = ""
+	} else {
+		// Create a structure that looks like:
+		// module_type {
+		//   name: "...",
+		//   ...
+		//   <common properties>
+		//   ...
+		//   target: {
+		//     <arch independent os specific sections, e.g. android>
+		//     ...
+		//     <arch and os specific sections, e.g. android_x86>
+		//   }
+		//
+		osType := osInfo.osType
+		osPropertySet = targetPropertySet.AddPropertySet(osType.Name)
+		archPropertySet = targetPropertySet
+
+		// Arch specific properties need to be added to an os and arch specific
+		// section prefixed with <os>_.
+		archOsPrefix = osType.Name + "_"
+	}
+
+	// Add the os specific but arch independent properties to the module.
+	osInfo.Properties.AddToPropertySet(builder.ctx, builder, osPropertySet)
+
+	// Add arch (and possibly os) specific sections for each set of arch (and possibly
+	// os) specific properties.
+	//
+	// The archInfos list will be empty if the os contains variants for the common
+	// architecture.
+	for _, archInfo := range osInfo.archInfos {
+		archInfo.addToPropertySet(builder, archPropertySet, archOsPrefix)
+	}
 }
 
 type archTypeSpecificInfo struct {
@@ -751,6 +963,32 @@
 	archType android.ArchType
 }
 
+// Create a new archTypeSpecificInfo for the specified arch type and its properties
+// structures populated with information from the variants.
+func newArchSpecificInfo(archType android.ArchType, variantPropertiesFactory variantPropertiesFactoryFunc, archVariants []android.SdkAware) *archTypeSpecificInfo {
+
+	if len(archVariants) != 1 {
+		panic(fmt.Errorf("expected one arch specific variant but found %d", len(archVariants)))
+	}
+
+	// Create an arch specific info into which the variant properties can be copied.
+	archInfo := &archTypeSpecificInfo{archType: archType}
+
+	// Create the properties into which the arch type specific properties will be
+	// added.
+	archInfo.Properties = variantPropertiesFactory()
+	archInfo.Properties.PopulateFromVariant(archVariants[0])
+
+	return archInfo
+}
+
+// Add the properties for an arch type to a property set.
+func (archInfo *archTypeSpecificInfo) addToPropertySet(builder *snapshotBuilder, archPropertySet android.BpPropertySet, archOsPrefix string) {
+	archTypeName := archInfo.archType.Name
+	archTypePropertySet := archPropertySet.AddPropertySet(archOsPrefix + archTypeName)
+	archInfo.Properties.AddToPropertySet(builder.ctx, builder, archTypePropertySet)
+}
+
 func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, builder *snapshotBuilder, member *sdkMember, bpModule android.BpModule) {
 
 	memberType := member.memberType
@@ -764,18 +1002,18 @@
 	}
 
 	osCount := len(variantsByOsType)
-	createVariantPropertiesStruct := func(os android.OsType) android.SdkMemberProperties {
+	variantPropertiesFactory := func() android.SdkMemberProperties {
 		properties := memberType.CreateVariantPropertiesStruct()
 		base := properties.Base()
 		base.Os_count = osCount
-		base.Os = os
 		return properties
 	}
 
 	osTypeToInfo := make(map[android.OsType]*osTypeSpecificInfo)
 
 	// The set of properties that are common across all architectures and os types.
-	commonProperties := createVariantPropertiesStruct(android.CommonOS)
+	commonProperties := variantPropertiesFactory()
+	commonProperties.Base().Os = android.CommonOS
 
 	// Create common value extractor that can be used to optimize the properties.
 	commonValueExtractor := newCommonValueExtractor(commonProperties)
@@ -785,67 +1023,14 @@
 	var osSpecificPropertiesList []android.SdkMemberProperties
 
 	for osType, osTypeVariants := range variantsByOsType {
-		// Group the properties for each variant by arch type within the os.
-		osInfo := &osTypeSpecificInfo{}
+		osInfo := newOsTypeSpecificInfo(osType, variantPropertiesFactory, osTypeVariants)
 		osTypeToInfo[osType] = osInfo
-
-		// Create a structure into which properties common across the architectures in
-		// this os type will be stored. Add it to the list of os type specific yet
-		// architecture independent properties structs.
-		osInfo.Properties = createVariantPropertiesStruct(osType)
+		// Add the os specific properties to a list of os type specific yet architecture
+		// independent properties structs.
 		osSpecificPropertiesList = append(osSpecificPropertiesList, osInfo.Properties)
 
-		commonArch := false
-		for _, variant := range osTypeVariants {
-			var properties android.SdkMemberProperties
-
-			// Get the info associated with the arch type inside the os info.
-			archType := variant.Target().Arch.ArchType
-
-			if archType.Name == "common" {
-				// The arch type is common so populate the common properties directly.
-				properties = osInfo.Properties
-
-				commonArch = true
-			} else {
-				archInfo := &archTypeSpecificInfo{archType: archType}
-				properties = createVariantPropertiesStruct(osType)
-				archInfo.Properties = properties
-
-				osInfo.archTypes = append(osInfo.archTypes, archInfo)
-			}
-
-			properties.PopulateFromVariant(variant)
-		}
-
-		if commonArch {
-			if len(osTypeVariants) != 1 {
-				panic("Expected to only have 1 variant when arch type is common but found " + string(len(variants)))
-			}
-		} else {
-			var archPropertiesList []android.SdkMemberProperties
-			for _, archInfo := range osInfo.archTypes {
-				archPropertiesList = append(archPropertiesList, archInfo.Properties)
-			}
-
-			commonValueExtractor.extractCommonProperties(osInfo.Properties, archPropertiesList)
-
-			// Choose setting for compile_multilib that is appropriate for the arch variants supplied.
-			var multilib string
-			archVariantCount := len(osInfo.archTypes)
-			if archVariantCount == 2 {
-				multilib = "both"
-			} else if archVariantCount == 1 {
-				if strings.HasSuffix(osInfo.archTypes[0].archType.Name, "64") {
-					multilib = "64"
-				} else {
-					multilib = "32"
-				}
-			}
-
-			osInfo.commonArch = commonArch
-			osInfo.Properties.Base().Compile_multilib = multilib
-		}
+		// Optimize the properties across all the variants for a specific os type.
+		osInfo.optimizeProperties(commonValueExtractor)
 	}
 
 	// Extract properties which are common across all architectures and os types.
@@ -865,71 +1050,8 @@
 			continue
 		}
 
-		var osPropertySet android.BpPropertySet
-		var archOsPrefix string
-		if len(osTypeToInfo) == 1 {
-			// There is only one os type present in the variants sp don't bother
-			// with adding target specific properties.
-
-			// Create a structure that looks like:
-			// module_type {
-			//   name: "...",
-			//   ...
-			//   <common properties>
-			//   ...
-			//   <single os type specific properties>
-			//
-			//   arch: {
-			//     <arch specific sections>
-			//   }
-			//
-			osPropertySet = bpModule
-
-			// Arch specific properties need to be added to an arch specific section
-			// within arch.
-			archOsPrefix = ""
-		} else {
-			// Create a structure that looks like:
-			// module_type {
-			//   name: "...",
-			//   ...
-			//   <common properties>
-			//   ...
-			//   target: {
-			//     <arch independent os specific sections, e.g. android>
-			//     ...
-			//     <arch and os specific sections, e.g. android_x86>
-			//   }
-			//
-			osPropertySet = targetPropertySet.AddPropertySet(osType.Name)
-
-			// Arch specific properties need to be added to an os and arch specific
-			// section prefixed with <os>_.
-			archOsPrefix = osType.Name + "_"
-		}
-
-		osInfo.Properties.AddToPropertySet(sdkModuleContext, builder, osPropertySet)
-		if !osInfo.commonArch {
-			// Either add the arch specific sections into the target or arch sections
-			// depending on whether they will also be os specific.
-			var archPropertySet android.BpPropertySet
-			if archOsPrefix == "" {
-				archPropertySet = osPropertySet.AddPropertySet("arch")
-			} else {
-				archPropertySet = targetPropertySet
-			}
-
-			// Add arch (and possibly os) specific sections for each set of
-			// arch (and possibly os) specific properties.
-			for _, av := range osInfo.archTypes {
-				archTypePropertySet := archPropertySet.AddPropertySet(archOsPrefix + av.archType.Name)
-
-				av.Properties.AddToPropertySet(sdkModuleContext, builder, archTypePropertySet)
-			}
-		}
+		osInfo.addToPropertySet(builder, bpModule, targetPropertySet)
 	}
-
-	memberType.FinalizeModule(sdkModuleContext, builder, member, bpModule)
 }
 
 // Compute the list of possible os types that this sdk could support.
@@ -951,7 +1073,8 @@
 	return osTypes
 }
 
-// Given a struct value, access a field within that struct.
+// 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
@@ -969,13 +1092,18 @@
 func newCommonValueExtractor(propertiesStruct interface{}) *commonValueExtractor {
 	structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type()
 	extractor := &commonValueExtractor{}
-	extractor.gatherFields(structType)
+	extractor.gatherFields(structType, nil)
 	return extractor
 }
 
 // Gather the fields from the supplied structure type from which common values will
 // be extracted.
-func (e *commonValueExtractor) gatherFields(structType reflect.Type) {
+//
+// 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 != "" {
@@ -983,14 +1111,20 @@
 			continue
 		}
 
-		// Ignore embedded structures.
-		if field.Type.Kind() == reflect.Struct && field.Anonymous {
+		// 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)
 
@@ -998,7 +1132,12 @@
 			return value.Field(fieldIndex)
 		}
 
-		e.fieldGetters = append(e.fieldGetters, fieldGetter)
+		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)
+		}
 	}
 }
 
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":