Merge "Have `symlink_preferred_arch: true` honor the `stem` property."
diff --git a/android/api_levels.go b/android/api_levels.go
index 51d4703..961685a 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -85,7 +85,7 @@
 // * Numeric API levels are simply converted.
 // * "minimum" and "current" are not currently handled since the former is
 //   NDK specific and the latter has inconsistent meaning.
-func ApiStrToNum(ctx BaseContext, apiLevel string) (int, error) {
+func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) {
 	num, ok := getApiLevelsMap(ctx.Config())[apiLevel]
 	if ok {
 		return num, nil
diff --git a/android/arch.go b/android/arch.go
index 04eb1e2..f4a3c06 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1129,7 +1129,7 @@
 
 var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
 
-func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
+func (m *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
 	dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value {
 
 	src = src.FieldByName(field)
@@ -1167,16 +1167,16 @@
 }
 
 // Rewrite the module's properties structs to contain arch-specific values.
-func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
-	arch := a.Arch()
-	os := a.Os()
+func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
+	arch := m.Arch()
+	os := m.Os()
 
-	for i := range a.generalProperties {
-		genProps := a.generalProperties[i]
-		if a.archProperties[i] == nil {
+	for i := range m.generalProperties {
+		genProps := m.generalProperties[i]
+		if m.archProperties[i] == nil {
 			continue
 		}
-		for _, archProperties := range a.archProperties[i] {
+		for _, archProperties := range m.archProperties[i] {
 			archPropValues := reflect.ValueOf(archProperties).Elem()
 
 			archProp := archPropValues.FieldByName("Arch")
@@ -1197,7 +1197,7 @@
 			if arch.ArchType != Common {
 				field := proptools.FieldNameForProperty(t.Name)
 				prefix := "arch." + t.Name
-				archStruct := a.appendProperties(ctx, genProps, archProp, field, prefix)
+				archStruct := m.appendProperties(ctx, genProps, archProp, field, prefix)
 
 				// Handle arch-variant-specific properties in the form:
 				// arch: {
@@ -1209,7 +1209,7 @@
 				if v != "" {
 					field := proptools.FieldNameForProperty(v)
 					prefix := "arch." + t.Name + "." + v
-					a.appendProperties(ctx, genProps, archStruct, field, prefix)
+					m.appendProperties(ctx, genProps, archStruct, field, prefix)
 				}
 
 				// Handle cpu-variant-specific properties in the form:
@@ -1223,7 +1223,7 @@
 					if c != "" {
 						field := proptools.FieldNameForProperty(c)
 						prefix := "arch." + t.Name + "." + c
-						a.appendProperties(ctx, genProps, archStruct, field, prefix)
+						m.appendProperties(ctx, genProps, archStruct, field, prefix)
 					}
 				}
 
@@ -1236,7 +1236,7 @@
 				for _, feature := range arch.ArchFeatures {
 					field := proptools.FieldNameForProperty(feature)
 					prefix := "arch." + t.Name + "." + feature
-					a.appendProperties(ctx, genProps, archStruct, field, prefix)
+					m.appendProperties(ctx, genProps, archStruct, field, prefix)
 				}
 
 				// Handle multilib-specific properties in the form:
@@ -1247,7 +1247,7 @@
 				// },
 				field = proptools.FieldNameForProperty(t.Multilib)
 				prefix = "multilib." + t.Multilib
-				a.appendProperties(ctx, genProps, multilibProp, field, prefix)
+				m.appendProperties(ctx, genProps, multilibProp, field, prefix)
 			}
 
 			// Handle host-specific properties in the form:
@@ -1259,7 +1259,7 @@
 			if os.Class == Host || os.Class == HostCross {
 				field = "Host"
 				prefix = "target.host"
-				a.appendProperties(ctx, genProps, targetProp, field, prefix)
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
 			}
 
 			// Handle target OS generalities of the form:
@@ -1274,24 +1274,24 @@
 			if os.Linux() {
 				field = "Linux"
 				prefix = "target.linux"
-				a.appendProperties(ctx, genProps, targetProp, field, prefix)
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
 
 				if arch.ArchType != Common {
 					field = "Linux_" + arch.ArchType.Name
 					prefix = "target.linux_" + arch.ArchType.Name
-					a.appendProperties(ctx, genProps, targetProp, field, prefix)
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
 				}
 			}
 
 			if os.Bionic() {
 				field = "Bionic"
 				prefix = "target.bionic"
-				a.appendProperties(ctx, genProps, targetProp, field, prefix)
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
 
 				if arch.ArchType != Common {
 					field = "Bionic_" + t.Name
 					prefix = "target.bionic_" + t.Name
-					a.appendProperties(ctx, genProps, targetProp, field, prefix)
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
 				}
 			}
 
@@ -1321,18 +1321,18 @@
 			// },
 			field = os.Field
 			prefix = "target." + os.Name
-			a.appendProperties(ctx, genProps, targetProp, field, prefix)
+			m.appendProperties(ctx, genProps, targetProp, field, prefix)
 
 			if arch.ArchType != Common {
 				field = os.Field + "_" + t.Name
 				prefix = "target." + os.Name + "_" + t.Name
-				a.appendProperties(ctx, genProps, targetProp, field, prefix)
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
 			}
 
 			if (os.Class == Host || os.Class == HostCross) && os != Windows {
 				field := "Not_windows"
 				prefix := "target.not_windows"
-				a.appendProperties(ctx, genProps, targetProp, field, prefix)
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
 			}
 
 			// Handle 64-bit device properties in the form:
@@ -1352,11 +1352,11 @@
 				if ctx.Config().Android64() {
 					field := "Android64"
 					prefix := "target.android64"
-					a.appendProperties(ctx, genProps, targetProp, field, prefix)
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
 				} else {
 					field := "Android32"
 					prefix := "target.android32"
-					a.appendProperties(ctx, genProps, targetProp, field, prefix)
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
 				}
 
 				if (arch.ArchType == X86 && (hasArmAbi(arch) ||
@@ -1365,7 +1365,7 @@
 						hasX86AndroidArch(ctx.Config().Targets[Android])) {
 					field := "Arm_on_x86"
 					prefix := "target.arm_on_x86"
-					a.appendProperties(ctx, genProps, targetProp, field, prefix)
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
 				}
 				if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
 					hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
@@ -1373,7 +1373,7 @@
 						hasX8664AndroidArch(ctx.Config().Targets[Android])) {
 					field := "Arm_on_x86_64"
 					prefix := "target.arm_on_x86_64"
-					a.appendProperties(ctx, genProps, targetProp, field, prefix)
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
 				}
 			}
 		}
diff --git a/android/hooks.go b/android/hooks.go
index d55678e..2d2f797 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -27,7 +27,7 @@
 // been applied.
 type LoadHookContext interface {
 	// TODO: a new context that includes Config() but not Target(), etc.?
-	BaseContext
+	BaseModuleContext
 	AppendProperties(...interface{})
 	PrependProperties(...interface{})
 	CreateModule(blueprint.ModuleFactory, ...interface{})
@@ -36,7 +36,7 @@
 // Arch hooks are run after the module has been split into architecture variants, and can be used
 // to add architecture-specific properties.
 type ArchHookContext interface {
-	BaseContext
+	BaseModuleContext
 	AppendProperties(...interface{})
 	PrependProperties(...interface{})
 }
@@ -129,18 +129,18 @@
 
 func LoadHookMutator(ctx TopDownMutatorContext) {
 	if m, ok := ctx.Module().(Module); ok {
-		// Cast through *androidTopDownMutatorContext because AppendProperties is implemented
-		// on *androidTopDownMutatorContext but not exposed through TopDownMutatorContext
-		var loadHookCtx LoadHookContext = ctx.(*androidTopDownMutatorContext)
+		// Cast through *topDownMutatorContext because AppendProperties is implemented
+		// on *topDownMutatorContext but not exposed through TopDownMutatorContext
+		var loadHookCtx LoadHookContext = ctx.(*topDownMutatorContext)
 		m.base().hooks.runLoadHooks(loadHookCtx, m.base())
 	}
 }
 
 func archHookMutator(ctx TopDownMutatorContext) {
 	if m, ok := ctx.Module().(Module); ok {
-		// Cast through *androidTopDownMutatorContext because AppendProperties is implemented
-		// on *androidTopDownMutatorContext but not exposed through TopDownMutatorContext
-		var archHookCtx ArchHookContext = ctx.(*androidTopDownMutatorContext)
+		// Cast through *topDownMutatorContext because AppendProperties is implemented
+		// on *topDownMutatorContext but not exposed through TopDownMutatorContext
+		var archHookCtx ArchHookContext = ctx.(*topDownMutatorContext)
 		m.base().hooks.runArchHooks(archHookCtx, m.base())
 	}
 }
diff --git a/android/module.go b/android/module.go
index eb9b0fc..88eba87 100644
--- a/android/module.go
+++ b/android/module.go
@@ -18,7 +18,6 @@
 	"fmt"
 	"path"
 	"path/filepath"
-	"sort"
 	"strings"
 	"text/scanner"
 
@@ -56,7 +55,30 @@
 
 type ModuleBuildParams BuildParams
 
-type androidBaseContext interface {
+// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
+// a Config instead of an interface{}, plus some extra methods that return Android-specific information
+// about the current module.
+type BaseModuleContext interface {
+	ModuleName() string
+	ModuleDir() string
+	ModuleType() string
+	Config() Config
+
+	ContainsProperty(name string) bool
+	Errorf(pos scanner.Position, fmt string, args ...interface{})
+	ModuleErrorf(fmt string, args ...interface{})
+	PropertyErrorf(property, fmt string, args ...interface{})
+	Failed() bool
+
+	// GlobWithDeps returns a list of files that match the specified pattern but do not match any
+	// of the patterns in excludes.  It also adds efficient dependencies to rerun the primary
+	// builder whenever a file matching the pattern as added or removed, without rerunning if a
+	// file that does not match the pattern is added to a searched directory.
+	GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+	Fs() pathtools.FileSystem
+	AddNinjaFileDeps(deps ...string)
+
 	Target() Target
 	TargetPrimary() bool
 	MultiTargets() []Target
@@ -78,37 +100,12 @@
 	DeviceConfig() DeviceConfig
 }
 
+// Deprecated: use BaseModuleContext instead
 type BaseContext interface {
 	BaseModuleContext
-	androidBaseContext
-}
-
-// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
-// a Config instead of an interface{}.
-type BaseModuleContext interface {
-	ModuleName() string
-	ModuleDir() string
-	ModuleType() string
-	Config() Config
-
-	ContainsProperty(name string) bool
-	Errorf(pos scanner.Position, fmt string, args ...interface{})
-	ModuleErrorf(fmt string, args ...interface{})
-	PropertyErrorf(property, fmt string, args ...interface{})
-	Failed() bool
-
-	// GlobWithDeps returns a list of files that match the specified pattern but do not match any
-	// of the patterns in excludes.  It also adds efficient dependencies to rerun the primary
-	// builder whenever a file matching the pattern as added or removed, without rerunning if a
-	// file that does not match the pattern is added to a searched directory.
-	GlobWithDeps(pattern string, excludes []string) ([]string, error)
-
-	Fs() pathtools.FileSystem
-	AddNinjaFileDeps(deps ...string)
 }
 
 type ModuleContext interface {
-	androidBaseContext
 	BaseModuleContext
 
 	// Deprecated: use ModuleContext.Build instead.
@@ -457,9 +454,9 @@
 // The ModuleBase type is responsible for implementing the GenerateBuildActions
 // method to support the blueprint.Module interface. This method will then call
 // the module's GenerateAndroidBuildActions method once for each build variant
-// that is to be built. GenerateAndroidBuildActions is passed a
-// AndroidModuleContext rather than the usual blueprint.ModuleContext.
-// AndroidModuleContext exposes extra functionality specific to the Android build
+// that is to be built. GenerateAndroidBuildActions is passed a ModuleContext
+// rather than the usual blueprint.ModuleContext.
+// ModuleContext exposes extra functionality specific to the Android build
 // system including details about the particular build variant that is to be
 // generated.
 //
@@ -526,83 +523,83 @@
 	prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
 }
 
-func (a *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
+func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
 
-func (a *ModuleBase) AddProperties(props ...interface{}) {
-	a.registerProps = append(a.registerProps, props...)
+func (m *ModuleBase) AddProperties(props ...interface{}) {
+	m.registerProps = append(m.registerProps, props...)
 }
 
-func (a *ModuleBase) GetProperties() []interface{} {
-	return a.registerProps
+func (m *ModuleBase) GetProperties() []interface{} {
+	return m.registerProps
 }
 
-func (a *ModuleBase) BuildParamsForTests() []BuildParams {
-	return a.buildParams
+func (m *ModuleBase) BuildParamsForTests() []BuildParams {
+	return m.buildParams
 }
 
-func (a *ModuleBase) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
-	return a.ruleParams
+func (m *ModuleBase) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
+	return m.ruleParams
 }
 
-func (a *ModuleBase) VariablesForTests() map[string]string {
-	return a.variables
+func (m *ModuleBase) VariablesForTests() map[string]string {
+	return m.variables
 }
 
-func (a *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) {
-	a.prefer32 = prefer32
+func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) {
+	m.prefer32 = prefer32
 }
 
 // Name returns the name of the module.  It may be overridden by individual module types, for
 // example prebuilts will prepend prebuilt_ to the name.
-func (a *ModuleBase) Name() string {
-	return String(a.nameProperties.Name)
+func (m *ModuleBase) Name() string {
+	return String(m.nameProperties.Name)
 }
 
 // BaseModuleName returns the name of the module as specified in the blueprints file.
-func (a *ModuleBase) BaseModuleName() string {
-	return String(a.nameProperties.Name)
+func (m *ModuleBase) BaseModuleName() string {
+	return String(m.nameProperties.Name)
 }
 
-func (a *ModuleBase) base() *ModuleBase {
-	return a
+func (m *ModuleBase) base() *ModuleBase {
+	return m
 }
 
-func (a *ModuleBase) SetTarget(target Target, multiTargets []Target, primary bool) {
-	a.commonProperties.CompileTarget = target
-	a.commonProperties.CompileMultiTargets = multiTargets
-	a.commonProperties.CompilePrimary = primary
+func (m *ModuleBase) SetTarget(target Target, multiTargets []Target, primary bool) {
+	m.commonProperties.CompileTarget = target
+	m.commonProperties.CompileMultiTargets = multiTargets
+	m.commonProperties.CompilePrimary = primary
 }
 
-func (a *ModuleBase) Target() Target {
-	return a.commonProperties.CompileTarget
+func (m *ModuleBase) Target() Target {
+	return m.commonProperties.CompileTarget
 }
 
-func (a *ModuleBase) TargetPrimary() bool {
-	return a.commonProperties.CompilePrimary
+func (m *ModuleBase) TargetPrimary() bool {
+	return m.commonProperties.CompilePrimary
 }
 
-func (a *ModuleBase) MultiTargets() []Target {
-	return a.commonProperties.CompileMultiTargets
+func (m *ModuleBase) MultiTargets() []Target {
+	return m.commonProperties.CompileMultiTargets
 }
 
-func (a *ModuleBase) Os() OsType {
-	return a.Target().Os
+func (m *ModuleBase) Os() OsType {
+	return m.Target().Os
 }
 
-func (a *ModuleBase) Host() bool {
-	return a.Os().Class == Host || a.Os().Class == HostCross
+func (m *ModuleBase) Host() bool {
+	return m.Os().Class == Host || m.Os().Class == HostCross
 }
 
-func (a *ModuleBase) Arch() Arch {
-	return a.Target().Arch
+func (m *ModuleBase) Arch() Arch {
+	return m.Target().Arch
 }
 
-func (a *ModuleBase) ArchSpecific() bool {
-	return a.commonProperties.ArchSpecific
+func (m *ModuleBase) ArchSpecific() bool {
+	return m.commonProperties.ArchSpecific
 }
 
-func (a *ModuleBase) OsClassSupported() []OsClass {
-	switch a.commonProperties.HostOrDeviceSupported {
+func (m *ModuleBase) OsClassSupported() []OsClass {
+	switch m.commonProperties.HostOrDeviceSupported {
 	case HostSupported:
 		return []OsClass{Host, HostCross}
 	case HostSupportedNoCross:
@@ -611,13 +608,13 @@
 		return []OsClass{Device}
 	case HostAndDeviceSupported, HostAndDeviceDefault:
 		var supported []OsClass
-		if Bool(a.hostAndDeviceProperties.Host_supported) ||
-			(a.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
-				a.hostAndDeviceProperties.Host_supported == nil) {
+		if Bool(m.hostAndDeviceProperties.Host_supported) ||
+			(m.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
+				m.hostAndDeviceProperties.Host_supported == nil) {
 			supported = append(supported, Host, HostCross)
 		}
-		if a.hostAndDeviceProperties.Device_supported == nil ||
-			*a.hostAndDeviceProperties.Device_supported {
+		if m.hostAndDeviceProperties.Device_supported == nil ||
+			*m.hostAndDeviceProperties.Device_supported {
 			supported = append(supported, Device)
 		}
 		return supported
@@ -626,49 +623,49 @@
 	}
 }
 
-func (a *ModuleBase) DeviceSupported() bool {
-	return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
-		a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
-			(a.hostAndDeviceProperties.Device_supported == nil ||
-				*a.hostAndDeviceProperties.Device_supported)
+func (m *ModuleBase) DeviceSupported() bool {
+	return m.commonProperties.HostOrDeviceSupported == DeviceSupported ||
+		m.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
+			(m.hostAndDeviceProperties.Device_supported == nil ||
+				*m.hostAndDeviceProperties.Device_supported)
 }
 
-func (a *ModuleBase) Platform() bool {
-	return !a.DeviceSpecific() && !a.SocSpecific() && !a.ProductSpecific() && !a.ProductServicesSpecific()
+func (m *ModuleBase) Platform() bool {
+	return !m.DeviceSpecific() && !m.SocSpecific() && !m.ProductSpecific() && !m.ProductServicesSpecific()
 }
 
-func (a *ModuleBase) DeviceSpecific() bool {
-	return Bool(a.commonProperties.Device_specific)
+func (m *ModuleBase) DeviceSpecific() bool {
+	return Bool(m.commonProperties.Device_specific)
 }
 
-func (a *ModuleBase) SocSpecific() bool {
-	return Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
+func (m *ModuleBase) SocSpecific() bool {
+	return Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Proprietary) || Bool(m.commonProperties.Soc_specific)
 }
 
-func (a *ModuleBase) ProductSpecific() bool {
-	return Bool(a.commonProperties.Product_specific)
+func (m *ModuleBase) ProductSpecific() bool {
+	return Bool(m.commonProperties.Product_specific)
 }
 
-func (a *ModuleBase) ProductServicesSpecific() bool {
-	return Bool(a.commonProperties.Product_services_specific)
+func (m *ModuleBase) ProductServicesSpecific() bool {
+	return Bool(m.commonProperties.Product_services_specific)
 }
 
-func (a *ModuleBase) Enabled() bool {
-	if a.commonProperties.Enabled == nil {
-		return !a.Os().DefaultDisabled
+func (m *ModuleBase) Enabled() bool {
+	if m.commonProperties.Enabled == nil {
+		return !m.Os().DefaultDisabled
 	}
-	return *a.commonProperties.Enabled
+	return *m.commonProperties.Enabled
 }
 
-func (a *ModuleBase) SkipInstall() {
-	a.commonProperties.SkipInstall = true
+func (m *ModuleBase) SkipInstall() {
+	m.commonProperties.SkipInstall = true
 }
 
-func (a *ModuleBase) ExportedToMake() bool {
-	return a.commonProperties.NamespaceExportedToMake
+func (m *ModuleBase) ExportedToMake() bool {
+	return m.commonProperties.NamespaceExportedToMake
 }
 
-func (a *ModuleBase) computeInstallDeps(
+func (m *ModuleBase) computeInstallDeps(
 	ctx blueprint.ModuleContext) Paths {
 
 	result := Paths{}
@@ -683,35 +680,35 @@
 	return result
 }
 
-func (a *ModuleBase) filesToInstall() Paths {
-	return a.installFiles
+func (m *ModuleBase) filesToInstall() Paths {
+	return m.installFiles
 }
 
-func (p *ModuleBase) NoAddressSanitizer() bool {
-	return p.noAddressSanitizer
+func (m *ModuleBase) NoAddressSanitizer() bool {
+	return m.noAddressSanitizer
 }
 
-func (p *ModuleBase) InstallInData() bool {
+func (m *ModuleBase) InstallInData() bool {
 	return false
 }
 
-func (p *ModuleBase) InstallInSanitizerDir() bool {
+func (m *ModuleBase) InstallInSanitizerDir() bool {
 	return false
 }
 
-func (p *ModuleBase) InstallInRecovery() bool {
-	return Bool(p.commonProperties.Recovery)
+func (m *ModuleBase) InstallInRecovery() bool {
+	return Bool(m.commonProperties.Recovery)
 }
 
-func (a *ModuleBase) Owner() string {
-	return String(a.commonProperties.Owner)
+func (m *ModuleBase) Owner() string {
+	return String(m.commonProperties.Owner)
 }
 
-func (a *ModuleBase) NoticeFile() OptionalPath {
-	return a.noticeFile
+func (m *ModuleBase) NoticeFile() OptionalPath {
+	return m.noticeFile
 }
 
-func (a *ModuleBase) generateModuleTarget(ctx ModuleContext) {
+func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
 	allInstalledFiles := Paths{}
 	allCheckbuildFiles := Paths{}
 	ctx.VisitAllModuleVariants(func(module Module) {
@@ -736,7 +733,7 @@
 			Default:   !ctx.Config().EmbeddedInMake(),
 		})
 		deps = append(deps, name)
-		a.installTarget = name
+		m.installTarget = name
 	}
 
 	if len(allCheckbuildFiles) > 0 {
@@ -747,7 +744,7 @@
 			Implicits: allCheckbuildFiles,
 		})
 		deps = append(deps, name)
-		a.checkbuildTarget = name
+		m.checkbuildTarget = name
 	}
 
 	if len(deps) > 0 {
@@ -763,26 +760,26 @@
 			Implicits: deps,
 		})
 
-		a.blueprintDir = ctx.ModuleDir()
+		m.blueprintDir = ctx.ModuleDir()
 	}
 }
 
-func determineModuleKind(a *ModuleBase, ctx blueprint.BaseModuleContext) moduleKind {
-	var socSpecific = Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
-	var deviceSpecific = Bool(a.commonProperties.Device_specific)
-	var productSpecific = Bool(a.commonProperties.Product_specific)
-	var productServicesSpecific = Bool(a.commonProperties.Product_services_specific)
+func determineModuleKind(m *ModuleBase, ctx blueprint.BaseModuleContext) moduleKind {
+	var socSpecific = Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Proprietary) || Bool(m.commonProperties.Soc_specific)
+	var deviceSpecific = Bool(m.commonProperties.Device_specific)
+	var productSpecific = Bool(m.commonProperties.Product_specific)
+	var productServicesSpecific = Bool(m.commonProperties.Product_services_specific)
 
 	msg := "conflicting value set here"
 	if socSpecific && deviceSpecific {
 		ctx.PropertyErrorf("device_specific", "a module cannot be specific to SoC and device at the same time.")
-		if Bool(a.commonProperties.Vendor) {
+		if Bool(m.commonProperties.Vendor) {
 			ctx.PropertyErrorf("vendor", msg)
 		}
-		if Bool(a.commonProperties.Proprietary) {
+		if Bool(m.commonProperties.Proprietary) {
 			ctx.PropertyErrorf("proprietary", msg)
 		}
-		if Bool(a.commonProperties.Soc_specific) {
+		if Bool(m.commonProperties.Soc_specific) {
 			ctx.PropertyErrorf("soc_specific", msg)
 		}
 	}
@@ -801,13 +798,13 @@
 		if deviceSpecific {
 			ctx.PropertyErrorf("device_specific", msg)
 		} else {
-			if Bool(a.commonProperties.Vendor) {
+			if Bool(m.commonProperties.Vendor) {
 				ctx.PropertyErrorf("vendor", msg)
 			}
-			if Bool(a.commonProperties.Proprietary) {
+			if Bool(m.commonProperties.Proprietary) {
 				ctx.PropertyErrorf("proprietary", msg)
 			}
-			if Bool(a.commonProperties.Soc_specific) {
+			if Bool(m.commonProperties.Soc_specific) {
 				ctx.PropertyErrorf("soc_specific", msg)
 			}
 		}
@@ -826,25 +823,26 @@
 	}
 }
 
-func (a *ModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl {
-	return androidBaseContextImpl{
-		target:        a.commonProperties.CompileTarget,
-		targetPrimary: a.commonProperties.CompilePrimary,
-		multiTargets:  a.commonProperties.CompileMultiTargets,
-		kind:          determineModuleKind(a, ctx),
-		config:        ctx.Config().(Config),
+func (m *ModuleBase) baseModuleContextFactory(ctx blueprint.BaseModuleContext) baseModuleContext {
+	return baseModuleContext{
+		BaseModuleContext: ctx,
+		target:            m.commonProperties.CompileTarget,
+		targetPrimary:     m.commonProperties.CompilePrimary,
+		multiTargets:      m.commonProperties.CompileMultiTargets,
+		kind:              determineModuleKind(m, ctx),
+		config:            ctx.Config().(Config),
 	}
 }
 
-func (a *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
-	ctx := &androidModuleContext{
-		module:                 a.module,
-		ModuleContext:          blueprintCtx,
-		androidBaseContextImpl: a.androidBaseContextFactory(blueprintCtx),
-		installDeps:            a.computeInstallDeps(blueprintCtx),
-		installFiles:           a.installFiles,
-		missingDeps:            blueprintCtx.GetMissingDependencies(),
-		variables:              make(map[string]string),
+func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
+	ctx := &moduleContext{
+		module:            m.module,
+		ModuleContext:     blueprintCtx,
+		baseModuleContext: m.baseModuleContextFactory(blueprintCtx),
+		installDeps:       m.computeInstallDeps(blueprintCtx),
+		installFiles:      m.installFiles,
+		missingDeps:       blueprintCtx.GetMissingDependencies(),
+		variables:         make(map[string]string),
 	}
 
 	if ctx.config.captureBuild {
@@ -869,55 +867,56 @@
 	ctx.Variable(pctx, "moduleDescSuffix", s)
 
 	// Some common property checks for properties that will be used later in androidmk.go
-	if a.commonProperties.Dist.Dest != nil {
-		_, err := validateSafePath(*a.commonProperties.Dist.Dest)
+	if m.commonProperties.Dist.Dest != nil {
+		_, err := validateSafePath(*m.commonProperties.Dist.Dest)
 		if err != nil {
 			ctx.PropertyErrorf("dist.dest", "%s", err.Error())
 		}
 	}
-	if a.commonProperties.Dist.Dir != nil {
-		_, err := validateSafePath(*a.commonProperties.Dist.Dir)
+	if m.commonProperties.Dist.Dir != nil {
+		_, err := validateSafePath(*m.commonProperties.Dist.Dir)
 		if err != nil {
 			ctx.PropertyErrorf("dist.dir", "%s", err.Error())
 		}
 	}
-	if a.commonProperties.Dist.Suffix != nil {
-		if strings.Contains(*a.commonProperties.Dist.Suffix, "/") {
+	if m.commonProperties.Dist.Suffix != nil {
+		if strings.Contains(*m.commonProperties.Dist.Suffix, "/") {
 			ctx.PropertyErrorf("dist.suffix", "Suffix may not contain a '/' character.")
 		}
 	}
 
-	if a.Enabled() {
-		a.module.GenerateAndroidBuildActions(ctx)
+	if m.Enabled() {
+		m.module.GenerateAndroidBuildActions(ctx)
 		if ctx.Failed() {
 			return
 		}
 
-		a.installFiles = append(a.installFiles, ctx.installFiles...)
-		a.checkbuildFiles = append(a.checkbuildFiles, ctx.checkbuildFiles...)
+		m.installFiles = append(m.installFiles, ctx.installFiles...)
+		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
 
-		notice := proptools.StringDefault(a.commonProperties.Notice, "NOTICE")
-		if m := SrcIsModule(notice); m != "" {
-			a.noticeFile = ctx.ExpandOptionalSource(&notice, "notice")
+		notice := proptools.StringDefault(m.commonProperties.Notice, "NOTICE")
+		if module := SrcIsModule(notice); module != "" {
+			m.noticeFile = ctx.ExpandOptionalSource(&notice, "notice")
 		} else {
 			noticePath := filepath.Join(ctx.ModuleDir(), notice)
-			a.noticeFile = ExistentPathForSource(ctx, noticePath)
+			m.noticeFile = ExistentPathForSource(ctx, noticePath)
 		}
 	}
 
-	if a == ctx.FinalModule().(Module).base() {
-		a.generateModuleTarget(ctx)
+	if m == ctx.FinalModule().(Module).base() {
+		m.generateModuleTarget(ctx)
 		if ctx.Failed() {
 			return
 		}
 	}
 
-	a.buildParams = ctx.buildParams
-	a.ruleParams = ctx.ruleParams
-	a.variables = ctx.variables
+	m.buildParams = ctx.buildParams
+	m.ruleParams = ctx.ruleParams
+	m.variables = ctx.variables
 }
 
-type androidBaseContextImpl struct {
+type baseModuleContext struct {
+	blueprint.BaseModuleContext
 	target        Target
 	multiTargets  []Target
 	targetPrimary bool
@@ -926,9 +925,9 @@
 	config        Config
 }
 
-type androidModuleContext struct {
+type moduleContext struct {
 	blueprint.ModuleContext
-	androidBaseContextImpl
+	baseModuleContext
 	installDeps     Paths
 	installFiles    Paths
 	checkbuildFiles Paths
@@ -941,8 +940,8 @@
 	variables   map[string]string
 }
 
-func (a *androidModuleContext) ninjaError(desc string, outputs []string, err error) {
-	a.ModuleContext.Build(pctx.PackageContext, blueprint.BuildParams{
+func (m *moduleContext) ninjaError(desc string, outputs []string, err error) {
+	m.ModuleContext.Build(pctx.PackageContext, blueprint.BuildParams{
 		Rule:        ErrorRule,
 		Description: desc,
 		Outputs:     outputs,
@@ -954,12 +953,12 @@
 	return
 }
 
-func (a *androidModuleContext) Config() Config {
-	return a.ModuleContext.Config().(Config)
+func (m *moduleContext) Config() Config {
+	return m.ModuleContext.Config().(Config)
 }
 
-func (a *androidModuleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
-	a.Build(pctx, BuildParams(params))
+func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
+	m.Build(pctx, BuildParams(params))
 }
 
 func convertBuildParams(params BuildParams) blueprint.BuildParams {
@@ -1002,29 +1001,29 @@
 	return bparams
 }
 
-func (a *androidModuleContext) Variable(pctx PackageContext, name, value string) {
-	if a.config.captureBuild {
-		a.variables[name] = value
+func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
+	if m.config.captureBuild {
+		m.variables[name] = value
 	}
 
-	a.ModuleContext.Variable(pctx.PackageContext, name, value)
+	m.ModuleContext.Variable(pctx.PackageContext, name, value)
 }
 
-func (a *androidModuleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
+func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
 	argNames ...string) blueprint.Rule {
 
-	rule := a.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...)
+	rule := m.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...)
 
-	if a.config.captureBuild {
-		a.ruleParams[rule] = params
+	if m.config.captureBuild {
+		m.ruleParams[rule] = params
 	}
 
 	return rule
 }
 
-func (a *androidModuleContext) Build(pctx PackageContext, params BuildParams) {
-	if a.config.captureBuild {
-		a.buildParams = append(a.buildParams, params)
+func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
+	if m.config.captureBuild {
+		m.buildParams = append(m.buildParams, params)
 	}
 
 	bparams := convertBuildParams(params)
@@ -1033,39 +1032,39 @@
 		bparams.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
 	}
 
-	if a.missingDeps != nil {
-		a.ninjaError(bparams.Description, bparams.Outputs,
+	if m.missingDeps != nil {
+		m.ninjaError(bparams.Description, bparams.Outputs,
 			fmt.Errorf("module %s missing dependencies: %s\n",
-				a.ModuleName(), strings.Join(a.missingDeps, ", ")))
+				m.ModuleName(), strings.Join(m.missingDeps, ", ")))
 		return
 	}
 
-	a.ModuleContext.Build(pctx.PackageContext, bparams)
+	m.ModuleContext.Build(pctx.PackageContext, bparams)
 }
 
-func (a *androidModuleContext) GetMissingDependencies() []string {
-	return a.missingDeps
+func (m *moduleContext) GetMissingDependencies() []string {
+	return m.missingDeps
 }
 
-func (a *androidModuleContext) AddMissingDependencies(deps []string) {
+func (m *moduleContext) AddMissingDependencies(deps []string) {
 	if deps != nil {
-		a.missingDeps = append(a.missingDeps, deps...)
-		a.missingDeps = FirstUniqueStrings(a.missingDeps)
+		m.missingDeps = append(m.missingDeps, deps...)
+		m.missingDeps = FirstUniqueStrings(m.missingDeps)
 	}
 }
 
-func (a *androidModuleContext) validateAndroidModule(module blueprint.Module) Module {
+func (m *moduleContext) validateAndroidModule(module blueprint.Module) Module {
 	aModule, _ := module.(Module)
 	if aModule == nil {
-		a.ModuleErrorf("module %q not an android module", a.OtherModuleName(aModule))
+		m.ModuleErrorf("module %q not an android module", m.OtherModuleName(aModule))
 		return nil
 	}
 
 	if !aModule.Enabled() {
-		if a.Config().AllowMissingDependencies() {
-			a.AddMissingDependencies([]string{a.OtherModuleName(aModule)})
+		if m.Config().AllowMissingDependencies() {
+			m.AddMissingDependencies([]string{m.OtherModuleName(aModule)})
 		} else {
-			a.ModuleErrorf("depends on disabled module %q", a.OtherModuleName(aModule))
+			m.ModuleErrorf("depends on disabled module %q", m.OtherModuleName(aModule))
 		}
 		return nil
 	}
@@ -1073,15 +1072,15 @@
 	return aModule
 }
 
-func (a *androidModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
+func (m *moduleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
 	type dep struct {
 		mod blueprint.Module
 		tag blueprint.DependencyTag
 	}
 	var deps []dep
-	a.VisitDirectDepsBlueprint(func(m blueprint.Module) {
-		if aModule, _ := m.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
-			returnedTag := a.ModuleContext.OtherModuleDependencyTag(aModule)
+	m.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+		if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
+			returnedTag := m.ModuleContext.OtherModuleDependencyTag(aModule)
 			if tag == nil || returnedTag == tag {
 				deps = append(deps, dep{aModule, returnedTag})
 			}
@@ -1091,17 +1090,17 @@
 		return deps[0].mod, deps[0].tag
 	} else if len(deps) >= 2 {
 		panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
-			name, a.ModuleName()))
+			name, m.ModuleName()))
 	} else {
 		return nil, nil
 	}
 }
 
-func (a *androidModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
+func (m *moduleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
 	var deps []Module
-	a.VisitDirectDepsBlueprint(func(m blueprint.Module) {
-		if aModule, _ := m.(Module); aModule != nil {
-			if a.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
+	m.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+		if aModule, _ := module.(Module); aModule != nil {
+			if m.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
 				deps = append(deps, aModule)
 			}
 		}
@@ -1109,42 +1108,42 @@
 	return deps
 }
 
-func (a *androidModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
-	m, _ := a.getDirectDepInternal(name, tag)
-	return m
+func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
+	module, _ := m.getDirectDepInternal(name, tag)
+	return module
 }
 
-func (a *androidModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
-	return a.getDirectDepInternal(name, nil)
+func (m *moduleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
+	return m.getDirectDepInternal(name, nil)
 }
 
-func (a *androidModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
-	a.ModuleContext.VisitDirectDeps(visit)
+func (m *moduleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
+	m.ModuleContext.VisitDirectDeps(visit)
 }
 
-func (a *androidModuleContext) VisitDirectDeps(visit func(Module)) {
-	a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
-		if aModule := a.validateAndroidModule(module); aModule != nil {
+func (m *moduleContext) VisitDirectDeps(visit func(Module)) {
+	m.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+		if aModule := m.validateAndroidModule(module); aModule != nil {
 			visit(aModule)
 		}
 	})
 }
 
-func (a *androidModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
-	a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
-		if aModule := a.validateAndroidModule(module); aModule != nil {
-			if a.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
+func (m *moduleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
+	m.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+		if aModule := m.validateAndroidModule(module); aModule != nil {
+			if m.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
 				visit(aModule)
 			}
 		}
 	})
 }
 
-func (a *androidModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
-	a.ModuleContext.VisitDirectDepsIf(
+func (m *moduleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
+	m.ModuleContext.VisitDirectDepsIf(
 		// pred
 		func(module blueprint.Module) bool {
-			if aModule := a.validateAndroidModule(module); aModule != nil {
+			if aModule := m.validateAndroidModule(module); aModule != nil {
 				return pred(aModule)
 			} else {
 				return false
@@ -1156,19 +1155,19 @@
 		})
 }
 
-func (a *androidModuleContext) VisitDepsDepthFirst(visit func(Module)) {
-	a.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
-		if aModule := a.validateAndroidModule(module); aModule != nil {
+func (m *moduleContext) VisitDepsDepthFirst(visit func(Module)) {
+	m.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
+		if aModule := m.validateAndroidModule(module); aModule != nil {
 			visit(aModule)
 		}
 	})
 }
 
-func (a *androidModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
-	a.ModuleContext.VisitDepsDepthFirstIf(
+func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
+	m.ModuleContext.VisitDepsDepthFirstIf(
 		// pred
 		func(module blueprint.Module) bool {
-			if aModule := a.validateAndroidModule(module); aModule != nil {
+			if aModule := m.validateAndroidModule(module); aModule != nil {
 				return pred(aModule)
 			} else {
 				return false
@@ -1180,14 +1179,14 @@
 		})
 }
 
-func (a *androidModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
-	a.ModuleContext.WalkDeps(visit)
+func (m *moduleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
+	m.ModuleContext.WalkDeps(visit)
 }
 
-func (a *androidModuleContext) WalkDeps(visit func(Module, Module) bool) {
-	a.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
-		childAndroidModule := a.validateAndroidModule(child)
-		parentAndroidModule := a.validateAndroidModule(parent)
+func (m *moduleContext) WalkDeps(visit func(Module, Module) bool) {
+	m.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
+		childAndroidModule := m.validateAndroidModule(child)
+		parentAndroidModule := m.validateAndroidModule(parent)
 		if childAndroidModule != nil && parentAndroidModule != nil {
 			return visit(childAndroidModule, parentAndroidModule)
 		} else {
@@ -1196,143 +1195,143 @@
 	})
 }
 
-func (a *androidModuleContext) VisitAllModuleVariants(visit func(Module)) {
-	a.ModuleContext.VisitAllModuleVariants(func(module blueprint.Module) {
+func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
+	m.ModuleContext.VisitAllModuleVariants(func(module blueprint.Module) {
 		visit(module.(Module))
 	})
 }
 
-func (a *androidModuleContext) PrimaryModule() Module {
-	return a.ModuleContext.PrimaryModule().(Module)
+func (m *moduleContext) PrimaryModule() Module {
+	return m.ModuleContext.PrimaryModule().(Module)
 }
 
-func (a *androidModuleContext) FinalModule() Module {
-	return a.ModuleContext.FinalModule().(Module)
+func (m *moduleContext) FinalModule() Module {
+	return m.ModuleContext.FinalModule().(Module)
 }
 
-func (a *androidBaseContextImpl) Target() Target {
-	return a.target
+func (b *baseModuleContext) Target() Target {
+	return b.target
 }
 
-func (a *androidBaseContextImpl) TargetPrimary() bool {
-	return a.targetPrimary
+func (b *baseModuleContext) TargetPrimary() bool {
+	return b.targetPrimary
 }
 
-func (a *androidBaseContextImpl) MultiTargets() []Target {
-	return a.multiTargets
+func (b *baseModuleContext) MultiTargets() []Target {
+	return b.multiTargets
 }
 
-func (a *androidBaseContextImpl) Arch() Arch {
-	return a.target.Arch
+func (b *baseModuleContext) Arch() Arch {
+	return b.target.Arch
 }
 
-func (a *androidBaseContextImpl) Os() OsType {
-	return a.target.Os
+func (b *baseModuleContext) Os() OsType {
+	return b.target.Os
 }
 
-func (a *androidBaseContextImpl) Host() bool {
-	return a.target.Os.Class == Host || a.target.Os.Class == HostCross
+func (b *baseModuleContext) Host() bool {
+	return b.target.Os.Class == Host || b.target.Os.Class == HostCross
 }
 
-func (a *androidBaseContextImpl) Device() bool {
-	return a.target.Os.Class == Device
+func (b *baseModuleContext) Device() bool {
+	return b.target.Os.Class == Device
 }
 
-func (a *androidBaseContextImpl) Darwin() bool {
-	return a.target.Os == Darwin
+func (b *baseModuleContext) Darwin() bool {
+	return b.target.Os == Darwin
 }
 
-func (a *androidBaseContextImpl) Fuchsia() bool {
-	return a.target.Os == Fuchsia
+func (b *baseModuleContext) Fuchsia() bool {
+	return b.target.Os == Fuchsia
 }
 
-func (a *androidBaseContextImpl) Windows() bool {
-	return a.target.Os == Windows
+func (b *baseModuleContext) Windows() bool {
+	return b.target.Os == Windows
 }
 
-func (a *androidBaseContextImpl) Debug() bool {
-	return a.debug
+func (b *baseModuleContext) Debug() bool {
+	return b.debug
 }
 
-func (a *androidBaseContextImpl) PrimaryArch() bool {
-	if len(a.config.Targets[a.target.Os]) <= 1 {
+func (b *baseModuleContext) PrimaryArch() bool {
+	if len(b.config.Targets[b.target.Os]) <= 1 {
 		return true
 	}
-	return a.target.Arch.ArchType == a.config.Targets[a.target.Os][0].Arch.ArchType
+	return b.target.Arch.ArchType == b.config.Targets[b.target.Os][0].Arch.ArchType
 }
 
-func (a *androidBaseContextImpl) AConfig() Config {
-	return a.config
+func (b *baseModuleContext) AConfig() Config {
+	return b.config
 }
 
-func (a *androidBaseContextImpl) DeviceConfig() DeviceConfig {
-	return DeviceConfig{a.config.deviceConfig}
+func (b *baseModuleContext) DeviceConfig() DeviceConfig {
+	return DeviceConfig{b.config.deviceConfig}
 }
 
-func (a *androidBaseContextImpl) Platform() bool {
-	return a.kind == platformModule
+func (b *baseModuleContext) Platform() bool {
+	return b.kind == platformModule
 }
 
-func (a *androidBaseContextImpl) DeviceSpecific() bool {
-	return a.kind == deviceSpecificModule
+func (b *baseModuleContext) DeviceSpecific() bool {
+	return b.kind == deviceSpecificModule
 }
 
-func (a *androidBaseContextImpl) SocSpecific() bool {
-	return a.kind == socSpecificModule
+func (b *baseModuleContext) SocSpecific() bool {
+	return b.kind == socSpecificModule
 }
 
-func (a *androidBaseContextImpl) ProductSpecific() bool {
-	return a.kind == productSpecificModule
+func (b *baseModuleContext) ProductSpecific() bool {
+	return b.kind == productSpecificModule
 }
 
-func (a *androidBaseContextImpl) ProductServicesSpecific() bool {
-	return a.kind == productServicesSpecificModule
+func (b *baseModuleContext) ProductServicesSpecific() bool {
+	return b.kind == productServicesSpecificModule
 }
 
 // Makes this module a platform module, i.e. not specific to soc, device,
 // product, or product_services.
-func (a *ModuleBase) MakeAsPlatform() {
-	a.commonProperties.Vendor = boolPtr(false)
-	a.commonProperties.Proprietary = boolPtr(false)
-	a.commonProperties.Soc_specific = boolPtr(false)
-	a.commonProperties.Product_specific = boolPtr(false)
-	a.commonProperties.Product_services_specific = boolPtr(false)
+func (m *ModuleBase) MakeAsPlatform() {
+	m.commonProperties.Vendor = boolPtr(false)
+	m.commonProperties.Proprietary = boolPtr(false)
+	m.commonProperties.Soc_specific = boolPtr(false)
+	m.commonProperties.Product_specific = boolPtr(false)
+	m.commonProperties.Product_services_specific = boolPtr(false)
 }
 
-func (a *ModuleBase) EnableNativeBridgeSupportByDefault() {
-	a.commonProperties.Native_bridge_supported = boolPtr(true)
+func (m *ModuleBase) EnableNativeBridgeSupportByDefault() {
+	m.commonProperties.Native_bridge_supported = boolPtr(true)
 }
 
-func (a *androidModuleContext) InstallInData() bool {
-	return a.module.InstallInData()
+func (m *moduleContext) InstallInData() bool {
+	return m.module.InstallInData()
 }
 
-func (a *androidModuleContext) InstallInSanitizerDir() bool {
-	return a.module.InstallInSanitizerDir()
+func (m *moduleContext) InstallInSanitizerDir() bool {
+	return m.module.InstallInSanitizerDir()
 }
 
-func (a *androidModuleContext) InstallInRecovery() bool {
-	return a.module.InstallInRecovery()
+func (m *moduleContext) InstallInRecovery() bool {
+	return m.module.InstallInRecovery()
 }
 
-func (a *androidModuleContext) skipInstall(fullInstallPath OutputPath) bool {
-	if a.module.base().commonProperties.SkipInstall {
+func (m *moduleContext) skipInstall(fullInstallPath OutputPath) bool {
+	if m.module.base().commonProperties.SkipInstall {
 		return true
 	}
 
 	// We'll need a solution for choosing which of modules with the same name in different
 	// namespaces to install.  For now, reuse the list of namespaces exported to Make as the
 	// list of namespaces to install in a Soong-only build.
-	if !a.module.base().commonProperties.NamespaceExportedToMake {
+	if !m.module.base().commonProperties.NamespaceExportedToMake {
 		return true
 	}
 
-	if a.Device() {
-		if a.Config().SkipDeviceInstall() {
+	if m.Device() {
+		if m.Config().SkipDeviceInstall() {
 			return true
 		}
 
-		if a.Config().SkipMegaDeviceInstall(fullInstallPath.String()) {
+		if m.Config().SkipMegaDeviceInstall(fullInstallPath.String()) {
 			return true
 		}
 	}
@@ -1340,29 +1339,29 @@
 	return false
 }
 
-func (a *androidModuleContext) InstallFile(installPath OutputPath, name string, srcPath Path,
+func (m *moduleContext) InstallFile(installPath OutputPath, name string, srcPath Path,
 	deps ...Path) OutputPath {
-	return a.installFile(installPath, name, srcPath, Cp, deps)
+	return m.installFile(installPath, name, srcPath, Cp, deps)
 }
 
-func (a *androidModuleContext) InstallExecutable(installPath OutputPath, name string, srcPath Path,
+func (m *moduleContext) InstallExecutable(installPath OutputPath, name string, srcPath Path,
 	deps ...Path) OutputPath {
-	return a.installFile(installPath, name, srcPath, CpExecutable, deps)
+	return m.installFile(installPath, name, srcPath, CpExecutable, deps)
 }
 
-func (a *androidModuleContext) installFile(installPath OutputPath, name string, srcPath Path,
+func (m *moduleContext) installFile(installPath OutputPath, name string, srcPath Path,
 	rule blueprint.Rule, deps []Path) OutputPath {
 
-	fullInstallPath := installPath.Join(a, name)
-	a.module.base().hooks.runInstallHooks(a, fullInstallPath, false)
+	fullInstallPath := installPath.Join(m, name)
+	m.module.base().hooks.runInstallHooks(m, fullInstallPath, false)
 
-	if !a.skipInstall(fullInstallPath) {
+	if !m.skipInstall(fullInstallPath) {
 
-		deps = append(deps, a.installDeps...)
+		deps = append(deps, m.installDeps...)
 
 		var implicitDeps, orderOnlyDeps Paths
 
-		if a.Host() {
+		if m.Host() {
 			// Installed host modules might be used during the build, depend directly on their
 			// dependencies so their timestamp is updated whenever their dependency is updated
 			implicitDeps = deps
@@ -1370,73 +1369,73 @@
 			orderOnlyDeps = deps
 		}
 
-		a.Build(pctx, BuildParams{
+		m.Build(pctx, BuildParams{
 			Rule:        rule,
 			Description: "install " + fullInstallPath.Base(),
 			Output:      fullInstallPath,
 			Input:       srcPath,
 			Implicits:   implicitDeps,
 			OrderOnly:   orderOnlyDeps,
-			Default:     !a.Config().EmbeddedInMake(),
+			Default:     !m.Config().EmbeddedInMake(),
 		})
 
-		a.installFiles = append(a.installFiles, fullInstallPath)
+		m.installFiles = append(m.installFiles, fullInstallPath)
 	}
-	a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
+	m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
 	return fullInstallPath
 }
 
-func (a *androidModuleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath {
-	fullInstallPath := installPath.Join(a, name)
-	a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
+func (m *moduleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath {
+	fullInstallPath := installPath.Join(m, name)
+	m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
 
-	if !a.skipInstall(fullInstallPath) {
+	if !m.skipInstall(fullInstallPath) {
 
 		relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
 		if err != nil {
 			panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
 		}
-		a.Build(pctx, BuildParams{
+		m.Build(pctx, BuildParams{
 			Rule:        Symlink,
 			Description: "install symlink " + fullInstallPath.Base(),
 			Output:      fullInstallPath,
 			OrderOnly:   Paths{srcPath},
-			Default:     !a.Config().EmbeddedInMake(),
+			Default:     !m.Config().EmbeddedInMake(),
 			Args: map[string]string{
 				"fromPath": relPath,
 			},
 		})
 
-		a.installFiles = append(a.installFiles, fullInstallPath)
-		a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
+		m.installFiles = append(m.installFiles, fullInstallPath)
+		m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
 	}
 	return fullInstallPath
 }
 
 // installPath/name -> absPath where absPath might be a path that is available only at runtime
 // (e.g. /apex/...)
-func (a *androidModuleContext) InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath {
-	fullInstallPath := installPath.Join(a, name)
-	a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
+func (m *moduleContext) InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath {
+	fullInstallPath := installPath.Join(m, name)
+	m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
 
-	if !a.skipInstall(fullInstallPath) {
-		a.Build(pctx, BuildParams{
+	if !m.skipInstall(fullInstallPath) {
+		m.Build(pctx, BuildParams{
 			Rule:        Symlink,
 			Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
 			Output:      fullInstallPath,
-			Default:     !a.Config().EmbeddedInMake(),
+			Default:     !m.Config().EmbeddedInMake(),
 			Args: map[string]string{
 				"fromPath": absPath,
 			},
 		})
 
-		a.installFiles = append(a.installFiles, fullInstallPath)
+		m.installFiles = append(m.installFiles, fullInstallPath)
 	}
 	return fullInstallPath
 }
 
-func (a *androidModuleContext) CheckbuildFile(srcPath Path) {
-	a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
+func (m *moduleContext) CheckbuildFile(srcPath Path) {
+	m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
 }
 
 type fileInstaller interface {
@@ -1551,54 +1550,54 @@
 // be tagged with `android:"path" to support automatic source module dependency resolution.
 //
 // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
-func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths {
-	return PathsForModuleSrcExcludes(ctx, srcFiles, excludes)
+func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
+	return PathsForModuleSrcExcludes(m, srcFiles, excludes)
 }
 
 // Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
 // be tagged with `android:"path" to support automatic source module dependency resolution.
 //
 // Deprecated: use PathForModuleSrc instead.
-func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path {
-	return PathForModuleSrc(ctx, srcFile)
+func (m *moduleContext) ExpandSource(srcFile, prop string) Path {
+	return PathForModuleSrc(m, srcFile)
 }
 
 // Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
 // the srcFile is non-nil.  The property must be tagged with `android:"path" to support automatic source module
 // dependency resolution.
-func (ctx *androidModuleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath {
+func (m *moduleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath {
 	if srcFile != nil {
-		return OptionalPathForPath(PathForModuleSrc(ctx, *srcFile))
+		return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
 	}
 	return OptionalPath{}
 }
 
-func (ctx *androidModuleContext) RequiredModuleNames() []string {
-	return ctx.module.base().commonProperties.Required
+func (m *moduleContext) RequiredModuleNames() []string {
+	return m.module.base().commonProperties.Required
 }
 
-func (ctx *androidModuleContext) HostRequiredModuleNames() []string {
-	return ctx.module.base().commonProperties.Host_required
+func (m *moduleContext) HostRequiredModuleNames() []string {
+	return m.module.base().commonProperties.Host_required
 }
 
-func (ctx *androidModuleContext) TargetRequiredModuleNames() []string {
-	return ctx.module.base().commonProperties.Target_required
+func (m *moduleContext) TargetRequiredModuleNames() []string {
+	return m.module.base().commonProperties.Target_required
 }
 
-func (ctx *androidModuleContext) Glob(globPattern string, excludes []string) Paths {
-	ret, err := ctx.GlobWithDeps(globPattern, excludes)
+func (m *moduleContext) Glob(globPattern string, excludes []string) Paths {
+	ret, err := m.GlobWithDeps(globPattern, excludes)
 	if err != nil {
-		ctx.ModuleErrorf("glob: %s", err.Error())
+		m.ModuleErrorf("glob: %s", err.Error())
 	}
-	return pathsForModuleSrcFromFullPath(ctx, ret, true)
+	return pathsForModuleSrcFromFullPath(m, ret, true)
 }
 
-func (ctx *androidModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
-	ret, err := ctx.GlobWithDeps(globPattern, excludes)
+func (m *moduleContext) GlobFiles(globPattern string, excludes []string) Paths {
+	ret, err := m.GlobWithDeps(globPattern, excludes)
 	if err != nil {
-		ctx.ModuleErrorf("glob: %s", err.Error())
+		m.ModuleErrorf("glob: %s", err.Error())
 	}
-	return pathsForModuleSrcFromFullPath(ctx, ret, false)
+	return pathsForModuleSrcFromFullPath(m, ret, false)
 }
 
 func init() {
@@ -1658,17 +1657,8 @@
 		return
 	}
 
-	sortedKeys := func(m map[string]Paths) []string {
-		s := make([]string, 0, len(m))
-		for k := range m {
-			s = append(s, k)
-		}
-		sort.Strings(s)
-		return s
-	}
-
 	// Ensure ancestor directories are in modulesInDir
-	dirs := sortedKeys(modulesInDir)
+	dirs := SortedStringKeys(modulesInDir)
 	for _, dir := range dirs {
 		dir := parentDir(dir)
 		for dir != "." && dir != "/" {
@@ -1681,7 +1671,6 @@
 	}
 
 	// Make directories build their direct subdirectories
-	dirs = sortedKeys(modulesInDir)
 	for _, dir := range dirs {
 		p := parentDir(dir)
 		if p != "." && p != "/" {
@@ -1738,8 +1727,7 @@
 	}
 
 	// Wrap those into host|host-cross|target phony rules
-	osClasses := sortedKeys(osClass)
-	for _, class := range osClasses {
+	for _, class := range SortedStringKeys(osClass) {
 		ctx.Build(pctx, BuildParams{
 			Rule:      blueprint.Phony,
 			Output:    PathForPhony(ctx, class),
diff --git a/android/mutator.go b/android/mutator.go
index 0e80249..cd0d152 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -66,8 +66,8 @@
 }
 
 type RegisterMutatorsContext interface {
-	TopDown(name string, m AndroidTopDownMutator) MutatorHandle
-	BottomUp(name string, m AndroidBottomUpMutator) MutatorHandle
+	TopDown(name string, m TopDownMutator) MutatorHandle
+	BottomUp(name string, m BottomUpMutator) MutatorHandle
 }
 
 type RegisterMutatorFunc func(RegisterMutatorsContext)
@@ -110,11 +110,10 @@
 	postDeps = append(postDeps, f)
 }
 
-type AndroidTopDownMutator func(TopDownMutatorContext)
+type TopDownMutator func(TopDownMutatorContext)
 
 type TopDownMutatorContext interface {
 	BaseModuleContext
-	androidBaseContext
 
 	OtherModuleExists(name string) bool
 	Rename(name string)
@@ -141,17 +140,16 @@
 	GetWalkPath() []Module
 }
 
-type androidTopDownMutatorContext struct {
+type topDownMutatorContext struct {
 	blueprint.TopDownMutatorContext
-	androidBaseContextImpl
+	baseModuleContext
 	walkPath []Module
 }
 
-type AndroidBottomUpMutator func(BottomUpMutatorContext)
+type BottomUpMutator func(BottomUpMutatorContext)
 
 type BottomUpMutatorContext interface {
 	BaseModuleContext
-	androidBaseContext
 
 	OtherModuleExists(name string) bool
 	Rename(name string)
@@ -168,17 +166,17 @@
 	ReplaceDependencies(string)
 }
 
-type androidBottomUpMutatorContext struct {
+type bottomUpMutatorContext struct {
 	blueprint.BottomUpMutatorContext
-	androidBaseContextImpl
+	baseModuleContext
 }
 
-func (x *registerMutatorsContext) BottomUp(name string, m AndroidBottomUpMutator) MutatorHandle {
+func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
 	f := func(ctx blueprint.BottomUpMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
-			actx := &androidBottomUpMutatorContext{
+			actx := &bottomUpMutatorContext{
 				BottomUpMutatorContext: ctx,
-				androidBaseContextImpl: a.base().androidBaseContextFactory(ctx),
+				baseModuleContext:      a.base().baseModuleContextFactory(ctx),
 			}
 			m(actx)
 		}
@@ -188,12 +186,12 @@
 	return mutator
 }
 
-func (x *registerMutatorsContext) TopDown(name string, m AndroidTopDownMutator) MutatorHandle {
+func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle {
 	f := func(ctx blueprint.TopDownMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
-			actx := &androidTopDownMutatorContext{
-				TopDownMutatorContext:  ctx,
-				androidBaseContextImpl: a.base().androidBaseContextFactory(ctx),
+			actx := &topDownMutatorContext{
+				TopDownMutatorContext: ctx,
+				baseModuleContext:     a.base().baseModuleContextFactory(ctx),
 			}
 			m(actx)
 		}
@@ -218,39 +216,39 @@
 	}
 }
 
-func (a *androidTopDownMutatorContext) Config() Config {
-	return a.config
+func (t *topDownMutatorContext) Config() Config {
+	return t.config
 }
 
-func (a *androidBottomUpMutatorContext) Config() Config {
-	return a.config
+func (b *bottomUpMutatorContext) Config() Config {
+	return b.config
 }
 
-func (a *androidTopDownMutatorContext) Module() Module {
-	module, _ := a.TopDownMutatorContext.Module().(Module)
+func (t *topDownMutatorContext) Module() Module {
+	module, _ := t.TopDownMutatorContext.Module().(Module)
 	return module
 }
 
-func (a *androidTopDownMutatorContext) VisitDirectDeps(visit func(Module)) {
-	a.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
+func (t *topDownMutatorContext) VisitDirectDeps(visit func(Module)) {
+	t.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
 		if aModule, _ := module.(Module); aModule != nil {
 			visit(aModule)
 		}
 	})
 }
 
-func (a *androidTopDownMutatorContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
-	a.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
+func (t *topDownMutatorContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
+	t.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
 		if aModule, _ := module.(Module); aModule != nil {
-			if a.TopDownMutatorContext.OtherModuleDependencyTag(aModule) == tag {
+			if t.TopDownMutatorContext.OtherModuleDependencyTag(aModule) == tag {
 				visit(aModule)
 			}
 		}
 	})
 }
 
-func (a *androidTopDownMutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
-	a.TopDownMutatorContext.VisitDirectDepsIf(
+func (t *topDownMutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
+	t.TopDownMutatorContext.VisitDirectDepsIf(
 		// pred
 		func(module blueprint.Module) bool {
 			if aModule, _ := module.(Module); aModule != nil {
@@ -265,16 +263,16 @@
 		})
 }
 
-func (a *androidTopDownMutatorContext) VisitDepsDepthFirst(visit func(Module)) {
-	a.TopDownMutatorContext.VisitDepsDepthFirst(func(module blueprint.Module) {
+func (t *topDownMutatorContext) VisitDepsDepthFirst(visit func(Module)) {
+	t.TopDownMutatorContext.VisitDepsDepthFirst(func(module blueprint.Module) {
 		if aModule, _ := module.(Module); aModule != nil {
 			visit(aModule)
 		}
 	})
 }
 
-func (a *androidTopDownMutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
-	a.TopDownMutatorContext.VisitDepsDepthFirstIf(
+func (t *topDownMutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
+	t.TopDownMutatorContext.VisitDepsDepthFirstIf(
 		// pred
 		func(module blueprint.Module) bool {
 			if aModule, _ := module.(Module); aModule != nil {
@@ -289,17 +287,17 @@
 		})
 }
 
-func (a *androidTopDownMutatorContext) WalkDeps(visit func(Module, Module) bool) {
-	a.walkPath = []Module{a.Module()}
-	a.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool {
+func (t *topDownMutatorContext) WalkDeps(visit func(Module, Module) bool) {
+	t.walkPath = []Module{t.Module()}
+	t.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool {
 		childAndroidModule, _ := child.(Module)
 		parentAndroidModule, _ := parent.(Module)
 		if childAndroidModule != nil && parentAndroidModule != nil {
 			// record walkPath before visit
-			for a.walkPath[len(a.walkPath)-1] != parentAndroidModule {
-				a.walkPath = a.walkPath[0 : len(a.walkPath)-1]
+			for t.walkPath[len(t.walkPath)-1] != parentAndroidModule {
+				t.walkPath = t.walkPath[0 : len(t.walkPath)-1]
 			}
-			a.walkPath = append(a.walkPath, childAndroidModule)
+			t.walkPath = append(t.walkPath, childAndroidModule)
 			return visit(childAndroidModule, parentAndroidModule)
 		} else {
 			return false
@@ -307,17 +305,17 @@
 	})
 }
 
-func (a *androidTopDownMutatorContext) GetWalkPath() []Module {
-	return a.walkPath
+func (t *topDownMutatorContext) GetWalkPath() []Module {
+	return t.walkPath
 }
 
-func (a *androidTopDownMutatorContext) AppendProperties(props ...interface{}) {
+func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
 	for _, p := range props {
-		err := proptools.AppendMatchingProperties(a.Module().base().customizableProperties,
+		err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
 			p, nil)
 		if err != nil {
 			if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
-				a.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+				t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
 			} else {
 				panic(err)
 			}
@@ -325,13 +323,13 @@
 	}
 }
 
-func (a *androidTopDownMutatorContext) PrependProperties(props ...interface{}) {
+func (t *topDownMutatorContext) PrependProperties(props ...interface{}) {
 	for _, p := range props {
-		err := proptools.PrependMatchingProperties(a.Module().base().customizableProperties,
+		err := proptools.PrependMatchingProperties(t.Module().base().customizableProperties,
 			p, nil)
 		if err != nil {
 			if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
-				a.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+				t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
 			} else {
 				panic(err)
 			}
diff --git a/android/paths.go b/android/paths.go
index 3915ff4..52d22d5 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -41,9 +41,7 @@
 var _ PathContext = ModuleContext(nil)
 
 type ModuleInstallPathContext interface {
-	PathContext
-
-	androidBaseContext
+	BaseModuleContext
 
 	InstallInData() bool
 	InstallInSanitizerDir() bool
diff --git a/android/paths_test.go b/android/paths_test.go
index 85c8d84..78cfbbe 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -200,7 +200,7 @@
 }
 
 type moduleInstallPathContextImpl struct {
-	androidBaseContextImpl
+	baseModuleContext
 
 	inData         bool
 	inSanitizerDir bool
@@ -212,7 +212,7 @@
 }
 
 func (m moduleInstallPathContextImpl) Config() Config {
-	return m.androidBaseContextImpl.config
+	return m.baseModuleContext.config
 }
 
 func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
@@ -244,7 +244,7 @@
 		{
 			name: "host binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: hostTarget,
 				},
 			},
@@ -255,7 +255,7 @@
 		{
 			name: "system binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 				},
 			},
@@ -265,7 +265,7 @@
 		{
 			name: "vendor binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   socSpecificModule,
 				},
@@ -276,7 +276,7 @@
 		{
 			name: "odm binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   deviceSpecificModule,
 				},
@@ -287,7 +287,7 @@
 		{
 			name: "product binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productSpecificModule,
 				},
@@ -298,7 +298,7 @@
 		{
 			name: "product_services binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productServicesSpecificModule,
 				},
@@ -310,7 +310,7 @@
 		{
 			name: "system native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 				},
 				inData: true,
@@ -321,7 +321,7 @@
 		{
 			name: "vendor native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   socSpecificModule,
 				},
@@ -333,7 +333,7 @@
 		{
 			name: "odm native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   deviceSpecificModule,
 				},
@@ -345,7 +345,7 @@
 		{
 			name: "product native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productSpecificModule,
 				},
@@ -358,7 +358,7 @@
 		{
 			name: "product_services native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productServicesSpecificModule,
 				},
@@ -371,7 +371,7 @@
 		{
 			name: "sanitized system binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 				},
 				inSanitizerDir: true,
@@ -382,7 +382,7 @@
 		{
 			name: "sanitized vendor binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   socSpecificModule,
 				},
@@ -394,7 +394,7 @@
 		{
 			name: "sanitized odm binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   deviceSpecificModule,
 				},
@@ -406,7 +406,7 @@
 		{
 			name: "sanitized product binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productSpecificModule,
 				},
@@ -419,7 +419,7 @@
 		{
 			name: "sanitized product_services binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productServicesSpecificModule,
 				},
@@ -432,7 +432,7 @@
 		{
 			name: "sanitized system native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 				},
 				inData:         true,
@@ -444,7 +444,7 @@
 		{
 			name: "sanitized vendor native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   socSpecificModule,
 				},
@@ -457,7 +457,7 @@
 		{
 			name: "sanitized odm native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   deviceSpecificModule,
 				},
@@ -470,7 +470,7 @@
 		{
 			name: "sanitized product native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productSpecificModule,
 				},
@@ -483,7 +483,7 @@
 		{
 			name: "sanitized product_services native test binary",
 			ctx: &moduleInstallPathContextImpl{
-				androidBaseContextImpl: androidBaseContextImpl{
+				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
 					kind:   productServicesSpecificModule,
 				},
@@ -497,7 +497,7 @@
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			tc.ctx.androidBaseContextImpl.config = testConfig
+			tc.ctx.baseModuleContext.config = testConfig
 			output := PathForModuleInstall(tc.ctx, tc.in...)
 			if output.basePath.path != tc.out {
 				t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
diff --git a/android/util.go b/android/util.go
index f7a3437..3b8bc78 100644
--- a/android/util.go
+++ b/android/util.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"reflect"
 	"regexp"
 	"runtime"
 	"sort"
@@ -77,10 +78,15 @@
 	return string(ret)
 }
 
-func sortedKeys(m map[string][]string) []string {
-	s := make([]string, 0, len(m))
-	for k := range m {
-		s = append(s, k)
+func SortedStringKeys(m interface{}) []string {
+	v := reflect.ValueOf(m)
+	if v.Kind() != reflect.Map {
+		panic(fmt.Sprintf("%#v is not a map", m))
+	}
+	keys := v.MapKeys()
+	s := make([]string, 0, len(keys))
+	for _, key := range keys {
+		s = append(s, key.String())
 	}
 	sort.Strings(s)
 	return s
diff --git a/android/variable.go b/android/variable.go
index d039a16..b4f31c6 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -402,12 +402,12 @@
 	}
 }
 
-func (a *ModuleBase) setVariableProperties(ctx BottomUpMutatorContext,
+func (m *ModuleBase) setVariableProperties(ctx BottomUpMutatorContext,
 	prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) {
 
 	printfIntoProperties(ctx, prefix, productVariablePropertyValue, variableValue)
 
-	err := proptools.AppendMatchingProperties(a.generalProperties,
+	err := proptools.AppendMatchingProperties(m.generalProperties,
 		productVariablePropertyValue.Addr().Interface(), nil)
 	if err != nil {
 		if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
diff --git a/androidmk/Android.bp b/androidmk/Android.bp
index 1d939b0..79fe530 100644
--- a/androidmk/Android.bp
+++ b/androidmk/Android.bp
@@ -30,6 +30,7 @@
         "androidmk-parser",
         "blueprint-parser",
         "bpfix-lib",
+        "soong-android",
     ],
 }
 
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 24057af..62aa3dc 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -15,9 +15,9 @@
 package main
 
 import (
+	"android/soong/android"
 	mkparser "android/soong/androidmk/parser"
 	"fmt"
-	"sort"
 	"strings"
 
 	bpparser "github.com/google/blueprint/parser"
@@ -335,15 +335,6 @@
 	}
 }
 
-func sortedMapKeys(inputMap map[string]string) (sortedKeys []string) {
-	keys := make([]string, 0, len(inputMap))
-	for key := range inputMap {
-		keys = append(keys, key)
-	}
-	sort.Strings(keys)
-	return keys
-}
-
 // splitAndAssign splits a Make list into components and then
 // creates the corresponding variable assignments.
 func splitAndAssign(ctx variableAssignmentContext, splitFunc listSplitFunc, namesByClassification map[string]string) error {
@@ -357,7 +348,7 @@
 		return err
 	}
 
-	for _, nameClassification := range sortedMapKeys(namesByClassification) {
+	for _, nameClassification := range android.SortedStringKeys(namesByClassification) {
 		name := namesByClassification[nameClassification]
 		if component, ok := lists[nameClassification]; ok && !emptyList(component) {
 			err = setVariable(ctx.file, ctx.append, ctx.prefix, name, component, true)
diff --git a/apex/apex.go b/apex/apex.go
index aed7d6f..41a21c9 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -552,7 +552,7 @@
 	}
 }
 
-func (a *apexBundle) getCertString(ctx android.BaseContext) string {
+func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
 	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
 	if overridden {
 		return ":" + certificate
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 32ccf4c..272d3d4 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -156,12 +156,18 @@
 
 func (library *libraryDecorator) androidMkWriteExportedFlags(w io.Writer) {
 	exportedFlags := library.exportedFlags()
+	for _, dir := range library.exportedDirs() {
+		exportedFlags = append(exportedFlags, "-I"+dir)
+	}
+	for _, dir := range library.exportedSystemDirs() {
+		exportedFlags = append(exportedFlags, "-isystem "+dir)
+	}
 	if len(exportedFlags) > 0 {
 		fmt.Fprintln(w, "LOCAL_EXPORT_CFLAGS :=", strings.Join(exportedFlags, " "))
 	}
-	exportedFlagsDeps := library.exportedFlagsDeps()
-	if len(exportedFlagsDeps) > 0 {
-		fmt.Fprintln(w, "LOCAL_EXPORT_C_INCLUDE_DEPS :=", strings.Join(exportedFlagsDeps.Strings(), " "))
+	exportedDeps := library.exportedDeps()
+	if len(exportedDeps) > 0 {
+		fmt.Fprintln(w, "LOCAL_EXPORT_C_INCLUDE_DEPS :=", strings.Join(exportedDeps.Strings(), " "))
 	}
 }
 
diff --git a/cc/binary.go b/cc/binary.go
index 476803f..d0909f1 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -388,7 +388,7 @@
 
 	TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs,
 		deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
-		builderFlags, outputFile)
+		builderFlags, outputFile, nil)
 
 	objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
 	objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
diff --git a/cc/builder.go b/cc/builder.go
index d2727b3..7cf5c29 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -26,6 +26,7 @@
 	"strings"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/pathtools"
 
 	"android/soong/android"
 	"android/soong/cc/config"
@@ -611,7 +612,7 @@
 // and shared libraries, to a shared library (.so) or dynamic executable
 func TransformObjToDynamicBinary(ctx android.ModuleContext,
 	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
-	crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath) {
+	crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath, implicitOutputs android.WritablePaths) {
 
 	ldCmd := "${config.ClangBin}/clang++"
 
@@ -648,7 +649,11 @@
 	}
 
 	for _, lib := range sharedLibs {
-		libFlagsList = append(libFlagsList, lib.String())
+		libFile := lib.String()
+		if ctx.Windows() {
+			libFile = pathtools.ReplaceExtension(libFile, "lib")
+		}
+		libFlagsList = append(libFlagsList, libFile)
 	}
 
 	deps = append(deps, staticLibs...)
@@ -659,11 +664,12 @@
 	}
 
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        ld,
-		Description: "link " + outputFile.Base(),
-		Output:      outputFile,
-		Inputs:      objFiles,
-		Implicits:   deps,
+		Rule:            ld,
+		Description:     "link " + outputFile.Base(),
+		Output:          outputFile,
+		ImplicitOutputs: implicitOutputs,
+		Inputs:          objFiles,
+		Implicits:       deps,
 		Args: map[string]string{
 			"ldCmd":    ldCmd,
 			"crtBegin": crtBegin.String(),
diff --git a/cc/cc.go b/cc/cc.go
index e61857d..26d3d98 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -119,8 +119,13 @@
 	GeneratedSources android.Paths
 	GeneratedHeaders android.Paths
 
-	Flags, ReexportedFlags []string
-	ReexportedFlagsDeps    android.Paths
+	Flags                []string
+	IncludeDirs          []string
+	SystemIncludeDirs    []string
+	ReexportedDirs       []string
+	ReexportedSystemDirs []string
+	ReexportedFlags      []string
+	ReexportedDeps       android.Paths
 
 	// Paths to crt*.o files
 	CrtBegin, CrtEnd android.OptionalPath
@@ -278,7 +283,7 @@
 }
 
 type BaseModuleContext interface {
-	android.BaseContext
+	android.BaseModuleContext
 	ModuleContextIntf
 }
 
@@ -641,7 +646,7 @@
 }
 
 type baseModuleContext struct {
-	android.BaseContext
+	android.BaseModuleContext
 	moduleContextImpl
 }
 
@@ -988,6 +993,14 @@
 	flags.ConlyFlags, _ = filterList(flags.ConlyFlags, config.IllegalFlags)
 
 	flags.GlobalFlags = append(flags.GlobalFlags, deps.Flags...)
+
+	for _, dir := range deps.IncludeDirs {
+		flags.GlobalFlags = append(flags.GlobalFlags, "-I"+dir)
+	}
+	for _, dir := range deps.SystemIncludeDirs {
+		flags.GlobalFlags = append(flags.GlobalFlags, "-isystem "+dir)
+	}
+
 	c.flags = flags
 	// We need access to all the flags seen by a source file.
 	if c.sabi != nil {
@@ -1040,7 +1053,7 @@
 	}
 }
 
-func (c *Module) toolchain(ctx android.BaseContext) config.Toolchain {
+func (c *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
 	if c.cachedToolchain == nil {
 		c.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
 	}
@@ -1161,7 +1174,7 @@
 
 func (c *Module) beginMutator(actx android.BottomUpMutatorContext) {
 	ctx := &baseModuleContext{
-		BaseContext: actx,
+		BaseModuleContext: actx,
 		moduleContextImpl: moduleContextImpl{
 			mod: c,
 		},
@@ -1578,6 +1591,13 @@
 	llndkLibraries := llndkLibraries(ctx.Config())
 	vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
 
+	reexportExporter := func(exporter exportedFlagsProducer) {
+		depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.exportedDirs()...)
+		depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...)
+		depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.exportedFlags()...)
+		depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.exportedDeps()...)
+	}
+
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		depName := ctx.OtherModuleName(dep)
 		depTag := ctx.OtherModuleDependencyTag(dep)
@@ -1599,14 +1619,13 @@
 				if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
 					depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders,
 						genRule.GeneratedDeps()...)
-					flags := includeDirsToFlags(genRule.GeneratedHeaderDirs())
-					depPaths.Flags = append(depPaths.Flags, flags)
+					dirs := genRule.GeneratedHeaderDirs().Strings()
+					depPaths.IncludeDirs = append(depPaths.IncludeDirs, dirs...)
 					if depTag == genHeaderExportDepTag {
-						depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, flags)
-						depPaths.ReexportedFlagsDeps = append(depPaths.ReexportedFlagsDeps,
-							genRule.GeneratedDeps()...)
+						depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, dirs...)
+						depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, genRule.GeneratedDeps()...)
 						// Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
-						c.sabi.Properties.ReexportedIncludeFlags = append(c.sabi.Properties.ReexportedIncludeFlags, flags)
+						c.sabi.Properties.ReexportedIncludes = append(c.sabi.Properties.ReexportedIncludes, dirs...)
 
 					}
 				} else {
@@ -1644,10 +1663,9 @@
 		if depTag == reuseObjTag {
 			if l, ok := ccDep.compiler.(libraryInterface); ok {
 				c.staticVariant = ccDep
-				objs, flags, deps := l.reuseObjs()
+				objs, exporter := l.reuseObjs()
 				depPaths.Objs = depPaths.Objs.Append(objs)
-				depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, flags...)
-				depPaths.ReexportedFlagsDeps = append(depPaths.ReexportedFlagsDeps, deps...)
+				reexportExporter(exporter)
 				return
 			}
 		}
@@ -1710,18 +1728,20 @@
 			}
 
 			if i, ok := ccDep.linker.(exportedFlagsProducer); ok {
-				flags := i.exportedFlags()
-				deps := i.exportedFlagsDeps()
-				depPaths.Flags = append(depPaths.Flags, flags...)
-				depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, deps...)
+				depPaths.IncludeDirs = append(depPaths.IncludeDirs, i.exportedDirs()...)
+				depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...)
+				depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, i.exportedDeps()...)
+				depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...)
 
 				if t.reexportFlags {
-					depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, flags...)
-					depPaths.ReexportedFlagsDeps = append(depPaths.ReexportedFlagsDeps, deps...)
+					reexportExporter(i)
 					// Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
 					// Re-exported shared library headers must be included as well since they can help us with type information
 					// about template instantiations (instantiated from their headers).
-					c.sabi.Properties.ReexportedIncludeFlags = append(c.sabi.Properties.ReexportedIncludeFlags, flags...)
+					// -isystem headers are not included since for bionic libraries, abi-filtering is taken care of by version
+					// scripts.
+					c.sabi.Properties.ReexportedIncludes = append(
+						c.sabi.Properties.ReexportedIncludes, i.exportedDirs()...)
 				}
 			}
 
@@ -1883,12 +1903,16 @@
 
 	// Dedup exported flags from dependencies
 	depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
+	depPaths.IncludeDirs = android.FirstUniqueStrings(depPaths.IncludeDirs)
+	depPaths.SystemIncludeDirs = android.FirstUniqueStrings(depPaths.SystemIncludeDirs)
 	depPaths.GeneratedHeaders = android.FirstUniquePaths(depPaths.GeneratedHeaders)
+	depPaths.ReexportedDirs = android.FirstUniqueStrings(depPaths.ReexportedDirs)
+	depPaths.ReexportedSystemDirs = android.FirstUniqueStrings(depPaths.ReexportedSystemDirs)
 	depPaths.ReexportedFlags = android.FirstUniqueStrings(depPaths.ReexportedFlags)
-	depPaths.ReexportedFlagsDeps = android.FirstUniquePaths(depPaths.ReexportedFlagsDeps)
+	depPaths.ReexportedDeps = android.FirstUniquePaths(depPaths.ReexportedDeps)
 
 	if c.sabi != nil {
-		c.sabi.Properties.ReexportedIncludeFlags = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludeFlags)
+		c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
 	}
 
 	return depPaths
diff --git a/cc/compiler.go b/cc/compiler.go
index 7667ae7..fd6184b 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -225,11 +225,6 @@
 		deps = protoDeps(ctx, deps, &compiler.Proto, Bool(compiler.Properties.Proto.Static))
 	}
 
-	if compiler.hasSrcExt(".sysprop") {
-		deps.HeaderLibs = append(deps.HeaderLibs, "libbase_headers")
-		deps.SharedLibs = append(deps.SharedLibs, "liblog")
-	}
-
 	if Bool(compiler.Properties.Openmp) {
 		deps.StaticLibs = append(deps.StaticLibs, "libomp")
 	}
diff --git a/cc/kernel_headers.go b/cc/kernel_headers.go
index c1da578..fff419e 100644
--- a/cc/kernel_headers.go
+++ b/cc/kernel_headers.go
@@ -25,9 +25,7 @@
 func (stub *kernelHeadersDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
 	if ctx.Device() {
 		f := &stub.libraryDecorator.flagExporter
-		for _, dir := range ctx.DeviceConfig().DeviceKernelHeaderDirs() {
-			f.flags = append(f.flags, "-isystem "+dir)
-		}
+		f.reexportSystemDirs(ctx.DeviceConfig().DeviceKernelHeaderDirs()...)
 	}
 	return stub.libraryDecorator.linkStatic(ctx, flags, deps, objs)
 }
diff --git a/cc/library.go b/cc/library.go
index d9c00dc..725208a 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -15,6 +15,7 @@
 package cc
 
 import (
+	"fmt"
 	"io"
 	"path/filepath"
 	"regexp"
@@ -207,8 +208,10 @@
 type flagExporter struct {
 	Properties FlagExporterProperties
 
-	flags     []string
-	flagsDeps android.Paths
+	dirs       []string
+	systemDirs []string
+	flags      []string
+	deps       android.Paths
 }
 
 func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
@@ -219,32 +222,57 @@
 	}
 }
 
-func (f *flagExporter) exportIncludes(ctx ModuleContext, inc string) {
-	includeDirs := f.exportedIncludes(ctx)
-	for _, dir := range includeDirs.Strings() {
-		f.flags = append(f.flags, inc+dir)
-	}
+func (f *flagExporter) exportIncludes(ctx ModuleContext) {
+	f.dirs = append(f.dirs, f.exportedIncludes(ctx).Strings()...)
 }
 
-func (f *flagExporter) reexportFlags(flags []string) {
+func (f *flagExporter) exportIncludesAsSystem(ctx ModuleContext) {
+	f.systemDirs = append(f.systemDirs, f.exportedIncludes(ctx).Strings()...)
+}
+
+func (f *flagExporter) reexportDirs(dirs ...string) {
+	f.dirs = append(f.dirs, dirs...)
+}
+
+func (f *flagExporter) reexportSystemDirs(dirs ...string) {
+	f.systemDirs = append(f.systemDirs, dirs...)
+}
+
+func (f *flagExporter) reexportFlags(flags ...string) {
+	for _, flag := range flags {
+		if strings.HasPrefix(flag, "-I") || strings.HasPrefix(flag, "-isystem") {
+			panic(fmt.Errorf("Exporting invalid flag %q: "+
+				"use reexportDirs or reexportSystemDirs to export directories", flag))
+		}
+	}
 	f.flags = append(f.flags, flags...)
 }
 
-func (f *flagExporter) reexportDeps(deps android.Paths) {
-	f.flagsDeps = append(f.flagsDeps, deps...)
+func (f *flagExporter) reexportDeps(deps ...android.Path) {
+	f.deps = append(f.deps, deps...)
+}
+
+func (f *flagExporter) exportedDirs() []string {
+	return f.dirs
+}
+
+func (f *flagExporter) exportedSystemDirs() []string {
+	return f.systemDirs
 }
 
 func (f *flagExporter) exportedFlags() []string {
 	return f.flags
 }
 
-func (f *flagExporter) exportedFlagsDeps() android.Paths {
-	return f.flagsDeps
+func (f *flagExporter) exportedDeps() android.Paths {
+	return f.deps
 }
 
 type exportedFlagsProducer interface {
+	exportedDirs() []string
+	exportedSystemDirs() []string
 	exportedFlags() []string
-	exportedFlagsDeps() android.Paths
+	exportedDeps() android.Paths
 }
 
 var _ exportedFlagsProducer = (*flagExporter)(nil)
@@ -256,9 +284,7 @@
 	MutatedProperties LibraryMutatedProperties
 
 	// For reusing static library objects for shared library
-	reuseObjects       Objects
-	reuseExportedFlags []string
-	reuseExportedDeps  android.Paths
+	reuseObjects Objects
 
 	// table-of-contents file to optimize out relinking when possible
 	tocFile android.OptionalPath
@@ -360,9 +386,10 @@
 				)
 			}
 		} else {
-			f = append(f,
-				"-shared",
-				"-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
+			f = append(f, "-shared")
+			if !ctx.Windows() {
+				f = append(f, "-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
+			}
 		}
 
 		flags.LdFlags = append(f, flags.LdFlags...)
@@ -404,25 +431,6 @@
 	return flags
 }
 
-func extractExportIncludesFromFlags(flags []string) []string {
-	// This method is used in the  generation of rules which produce
-	// abi-dumps for source files. Exported headers are needed to infer the
-	// abi exported by a library and filter out the rest of the abi dumped
-	// from a source. We extract the include flags exported by a library.
-	// This includes the flags exported which are re-exported from static
-	// library dependencies, exported header library dependencies and
-	// generated header dependencies. -isystem headers are not included
-	// since for bionic libraries, abi-filtering is taken care of by version
-	// scripts.
-	var exportedIncludes []string
-	for _, flag := range flags {
-		if strings.HasPrefix(flag, "-I") {
-			exportedIncludes = append(exportedIncludes, flag)
-		}
-	}
-	return exportedIncludes
-}
-
 func (library *libraryDecorator) shouldCreateVndkSourceAbiDump(ctx ModuleContext) bool {
 	if library.Properties.Header_abi_checker.Enabled != nil {
 		return Bool(library.Properties.Header_abi_checker.Enabled)
@@ -455,8 +463,8 @@
 		for _, dir := range exportIncludeDirs.Strings() {
 			SourceAbiFlags = append(SourceAbiFlags, "-I"+dir)
 		}
-		for _, reexportedInclude := range extractExportIncludesFromFlags(library.sabi.Properties.ReexportedIncludeFlags) {
-			SourceAbiFlags = append(SourceAbiFlags, reexportedInclude)
+		for _, reexportedInclude := range library.sabi.Properties.ReexportedIncludes {
+			SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
 		}
 		flags.SAbiFlags = SourceAbiFlags
 		total_length := len(library.baseCompiler.Properties.Srcs) + len(deps.GeneratedSources) + len(library.Properties.Shared.Srcs) +
@@ -486,7 +494,7 @@
 	getWholeStaticMissingDeps() []string
 	static() bool
 	objs() Objects
-	reuseObjs() (Objects, []string, android.Paths)
+	reuseObjs() (Objects, exportedFlagsProducer)
 	toc() android.OptionalPath
 
 	// Returns true if the build options for the module have selected a static or shared build
@@ -696,6 +704,14 @@
 	outputFile := android.PathForModuleOut(ctx, fileName)
 	ret := outputFile
 
+	var implicitOutputs android.WritablePaths
+	if ctx.Windows() {
+		importLibraryPath := android.PathForModuleOut(ctx, pathtools.ReplaceExtension(fileName, "lib"))
+
+		flags.LdFlags = append(flags.LdFlags, "-Wl,--out-implib="+importLibraryPath.String())
+		implicitOutputs = append(implicitOutputs, importLibraryPath)
+	}
+
 	builderFlags := flagsToBuilderFlags(flags)
 
 	// Optimize out relinking against shared libraries whose interface hasn't changed by
@@ -747,7 +763,7 @@
 
 	TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
 		deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
-		linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
+		linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs)
 
 	objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
 	objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
@@ -805,8 +821,8 @@
 		for _, dir := range exportIncludeDirs.Strings() {
 			SourceAbiFlags = append(SourceAbiFlags, "-I"+dir)
 		}
-		for _, reexportedInclude := range extractExportIncludesFromFlags(library.sabi.Properties.ReexportedIncludeFlags) {
-			SourceAbiFlags = append(SourceAbiFlags, reexportedInclude)
+		for _, reexportedInclude := range library.sabi.Properties.ReexportedIncludes {
+			SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
 		}
 		exportedHeaderFlags := strings.Join(SourceAbiFlags, " ")
 		library.sAbiOutputFile = TransformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
@@ -833,19 +849,17 @@
 		out = library.linkShared(ctx, flags, deps, objs)
 	}
 
-	library.exportIncludes(ctx, "-I")
-	library.reexportFlags(deps.ReexportedFlags)
-	library.reexportDeps(deps.ReexportedFlagsDeps)
+	library.exportIncludes(ctx)
+	library.reexportDirs(deps.ReexportedDirs...)
+	library.reexportSystemDirs(deps.ReexportedSystemDirs...)
+	library.reexportFlags(deps.ReexportedFlags...)
+	library.reexportDeps(deps.ReexportedDeps...)
 
 	if Bool(library.Properties.Aidl.Export_aidl_headers) {
 		if library.baseCompiler.hasSrcExt(".aidl") {
-			flags := []string{
-				"-I" + android.PathForModuleGen(ctx, "aidl").String(),
-			}
-			library.reexportFlags(flags)
-			library.reuseExportedFlags = append(library.reuseExportedFlags, flags...)
-			library.reexportDeps(library.baseCompiler.pathDeps) // TODO: restrict to aidl deps
-			library.reuseExportedDeps = append(library.reuseExportedDeps, library.baseCompiler.pathDeps...)
+			dir := android.PathForModuleGen(ctx, "aidl").String()
+			library.reexportDirs(dir)
+			library.reexportDeps(library.baseCompiler.pathDeps...) // TODO: restrict to aidl deps
 		}
 	}
 
@@ -853,26 +867,16 @@
 		if library.baseCompiler.hasSrcExt(".proto") {
 			includes := []string{}
 			if flags.proto.CanonicalPathFromRoot {
-				includes = append(includes, "-I"+flags.proto.SubDir.String())
+				includes = append(includes, flags.proto.SubDir.String())
 			}
-			includes = append(includes, "-I"+flags.proto.Dir.String())
-			library.reexportFlags(includes)
-			library.reuseExportedFlags = append(library.reuseExportedFlags, includes...)
-			library.reexportDeps(library.baseCompiler.pathDeps) // TODO: restrict to proto deps
-			library.reuseExportedDeps = append(library.reuseExportedDeps, library.baseCompiler.pathDeps...)
+			includes = append(includes, flags.proto.Dir.String())
+			library.reexportDirs(includes...)
+			library.reexportDeps(library.baseCompiler.pathDeps...) // TODO: restrict to proto deps
 		}
 	}
 
 	if library.baseCompiler.hasSrcExt(".sysprop") {
-		internalFlags := []string{
-			"-I" + android.PathForModuleGen(ctx, "sysprop", "include").String(),
-		}
-		systemFlags := []string{
-			"-I" + android.PathForModuleGen(ctx, "sysprop/system", "include").String(),
-		}
-
-		flags := internalFlags
-
+		dir := android.PathForModuleGen(ctx, "sysprop", "include").String()
 		if library.Properties.Sysprop.Platform != nil {
 			isProduct := ctx.ProductSpecific() && !ctx.useVndk()
 			isVendor := ctx.useVndk()
@@ -881,17 +885,16 @@
 			useSystem := isProduct || (isOwnerPlatform == isVendor)
 
 			if useSystem {
-				flags = systemFlags
+				dir = android.PathForModuleGen(ctx, "sysprop/system", "include").String()
 			}
 		}
 
-		library.reexportFlags(flags)
-		library.reexportDeps(library.baseCompiler.pathDeps)
-		library.reuseExportedFlags = append(library.reuseExportedFlags, flags...)
+		library.reexportDirs(dir)
+		library.reexportDeps(library.baseCompiler.pathDeps...)
 	}
 
 	if library.buildStubs() {
-		library.reexportFlags([]string{"-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion()})
+		library.reexportFlags("-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion())
 	}
 
 	return out
@@ -913,8 +916,8 @@
 	return library.objects
 }
 
-func (library *libraryDecorator) reuseObjs() (Objects, []string, android.Paths) {
-	return library.reuseObjects, library.reuseExportedFlags, library.reuseExportedDeps
+func (library *libraryDecorator) reuseObjs() (Objects, exportedFlagsProducer) {
+	return library.reuseObjects, &library.flagExporter
 }
 
 func (library *libraryDecorator) toc() android.OptionalPath {
diff --git a/cc/linker.go b/cc/linker.go
index fafefdc..dda2fcb 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -295,10 +295,6 @@
 	if ctx.Darwin() {
 		return false
 	}
-	// http://b/110800681 - lld cannot link Android's Windows modules yet.
-	if ctx.Windows() {
-		return false
-	}
 	if linker.Properties.Use_clang_lld != nil {
 		return Bool(linker.Properties.Use_clang_lld)
 	}
@@ -352,7 +348,7 @@
 			// darwin defaults to treating undefined symbols as errors
 			flags.LdFlags = append(flags.LdFlags, "-Wl,-undefined,dynamic_lookup")
 		}
-	} else if !ctx.Darwin() {
+	} else if !ctx.Darwin() && !ctx.Windows() {
 		flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
 	}
 
@@ -389,7 +385,7 @@
 
 	flags.LdFlags = append(flags.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...)
 
-	if ctx.Host() {
+	if ctx.Host() && !ctx.Windows() {
 		rpath_prefix := `\$$ORIGIN/`
 		if ctx.Darwin() {
 			rpath_prefix = "@loader_path/"
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 6cdf5c7..8290103 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -134,6 +134,7 @@
 	if !Bool(stub.Properties.Unversioned) {
 		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
 		flags.LdFlags = append(flags.LdFlags, linkerScriptFlag)
+		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
 	}
 
 	if len(stub.Properties.Export_preprocessed_headers) > 0 {
@@ -144,17 +145,17 @@
 			timestampFiles = append(timestampFiles, stub.processHeaders(ctx, dir, genHeaderOutDir))
 		}
 
-		includePrefix := "-I"
 		if Bool(stub.Properties.Export_headers_as_system) {
-			includePrefix = "-isystem "
+			stub.reexportSystemDirs(genHeaderOutDir.String())
+		} else {
+			stub.reexportDirs(genHeaderOutDir.String())
 		}
 
-		stub.reexportFlags([]string{includePrefix + genHeaderOutDir.String()})
-		stub.reexportDeps(timestampFiles)
+		stub.reexportDeps(timestampFiles...)
 	}
 
 	if Bool(stub.Properties.Export_headers_as_system) {
-		stub.exportIncludes(ctx, "-isystem ")
+		stub.exportIncludesAsSystem(ctx)
 		stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
 	}
 
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index ff990b5..969cb3f 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -121,7 +121,7 @@
 	}
 }
 
-func normalizeNdkApiLevel(ctx android.BaseContext, apiLevel string,
+func normalizeNdkApiLevel(ctx android.BaseModuleContext, apiLevel string,
 	arch android.Arch) (string, error) {
 
 	if apiLevel == "current" {
@@ -167,7 +167,7 @@
 	return strconv.Atoi(firstSupportedVersion)
 }
 
-func shouldUseVersionScript(ctx android.BaseContext, stub *stubDecorator) (bool, error) {
+func shouldUseVersionScript(ctx android.BaseModuleContext, stub *stubDecorator) (bool, error) {
 	// unversioned_until is normally empty, in which case we should use the version script.
 	if String(stub.properties.Unversioned_until) == "" {
 		return true, nil
@@ -337,6 +337,7 @@
 	if useVersionScript {
 		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
 		flags.LdFlags = append(flags.LdFlags, linkerScriptFlag)
+		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
 	}
 
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index fb16887..4356732 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -151,7 +151,7 @@
 		ctx.ModuleErrorf("NDK prebuilt libraries must have an ndk_lib prefixed name")
 	}
 
-	ndk.exportIncludes(ctx, "-isystem ")
+	ndk.exportIncludesAsSystem(ctx)
 
 	libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
 	libExt := flags.Toolchain.ShlibSuffix()
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index f92c50d..dc6c43a 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -85,9 +85,11 @@
 	flags Flags, deps PathDeps, objs Objects) android.Path {
 	// TODO(ccross): verify shared library dependencies
 	if len(p.properties.Srcs) > 0 {
-		p.libraryDecorator.exportIncludes(ctx, "-I")
-		p.libraryDecorator.reexportFlags(deps.ReexportedFlags)
-		p.libraryDecorator.reexportDeps(deps.ReexportedFlagsDeps)
+		p.libraryDecorator.exportIncludes(ctx)
+		p.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
+		p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
+		p.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
+		p.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
 
 		builderFlags := flagsToBuilderFlags(flags)
 
diff --git a/cc/sabi.go b/cc/sabi.go
index 451176f..ae7b31d 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -28,8 +28,8 @@
 )
 
 type SAbiProperties struct {
-	CreateSAbiDumps        bool `blueprint:"mutated"`
-	ReexportedIncludeFlags []string
+	CreateSAbiDumps    bool     `blueprint:"mutated"`
+	ReexportedIncludes []string `blueprint:"mutated"`
 }
 
 type sabi struct {
diff --git a/cc/util.go b/cc/util.go
index 3862728..2e1bb25 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -29,10 +29,6 @@
 	return android.JoinWithPrefix(dirs.Strings(), "-I")
 }
 
-func includeFilesToFlags(files android.Paths) string {
-	return android.JoinWithPrefix(files.Strings(), "-include ")
-}
-
 func ldDirsToFlags(dirs []string) string {
 	return android.JoinWithPrefix(dirs, "-L")
 }
diff --git a/cc/vendor_public_library.go b/cc/vendor_public_library.go
index 5738d25..f0de267 100644
--- a/cc/vendor_public_library.go
+++ b/cc/vendor_public_library.go
@@ -125,6 +125,7 @@
 	if !Bool(stub.Properties.Unversioned) {
 		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
 		flags.LdFlags = append(flags.LdFlags, linkerScriptFlag)
+		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
 	}
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
 }
diff --git a/cmd/zipsync/zipsync.go b/cmd/zipsync/zipsync.go
index ea755f5..a6023d3 100644
--- a/cmd/zipsync/zipsync.go
+++ b/cmd/zipsync/zipsync.go
@@ -30,6 +30,7 @@
 	outputDir  = flag.String("d", "", "output dir")
 	outputFile = flag.String("l", "", "output list file")
 	filter     = flag.String("f", "", "optional filter pattern")
+	zipPrefix  = flag.String("zip-prefix", "", "optional prefix within the zip file to extract, stripping the prefix")
 )
 
 func must(err error) {
@@ -77,6 +78,10 @@
 	var files []string
 	seen := make(map[string]string)
 
+	if *zipPrefix != "" {
+		*zipPrefix = filepath.Clean(*zipPrefix) + "/"
+	}
+
 	for _, input := range inputs {
 		reader, err := zip.OpenReader(input)
 		if err != nil {
@@ -85,23 +90,30 @@
 		defer reader.Close()
 
 		for _, f := range reader.File {
+			name := f.Name
+			if *zipPrefix != "" {
+				if !strings.HasPrefix(name, *zipPrefix) {
+					continue
+				}
+				name = strings.TrimPrefix(name, *zipPrefix)
+			}
 			if *filter != "" {
-				if match, err := filepath.Match(*filter, filepath.Base(f.Name)); err != nil {
+				if match, err := filepath.Match(*filter, filepath.Base(name)); err != nil {
 					log.Fatal(err)
 				} else if !match {
 					continue
 				}
 			}
-			if filepath.IsAbs(f.Name) {
-				log.Fatalf("%q in %q is an absolute path", f.Name, input)
+			if filepath.IsAbs(name) {
+				log.Fatalf("%q in %q is an absolute path", name, input)
 			}
 
-			if prev, exists := seen[f.Name]; exists {
-				log.Fatalf("%q found in both %q and %q", f.Name, prev, input)
+			if prev, exists := seen[name]; exists {
+				log.Fatalf("%q found in both %q and %q", name, prev, input)
 			}
-			seen[f.Name] = input
+			seen[name] = input
 
-			filename := filepath.Join(*outputDir, f.Name)
+			filename := filepath.Join(*outputDir, name)
 			if f.FileInfo().IsDir() {
 				must(os.MkdirAll(filename, f.FileInfo().Mode()))
 			} else {
diff --git a/java/aapt2.go b/java/aapt2.go
index bcc8e97..a815160 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -94,32 +94,20 @@
 	return ret
 }
 
-func aapt2CompileDirs(ctx android.ModuleContext, flata android.WritablePath, dirs android.Paths, deps android.Paths) {
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        aapt2CompileRule,
-		Description: "aapt2 compile dirs",
-		Implicits:   deps,
-		Output:      flata,
-		Args: map[string]string{
-			"outDir": flata.String(),
-			// Always set --pseudo-localize, it will be stripped out later for release
-			// builds that don't want it.
-			"cFlags": "--pseudo-localize " + android.JoinWithPrefix(dirs.Strings(), "--dir "),
-		},
-	})
-}
-
 var aapt2CompileZipRule = pctx.AndroidStaticRule("aapt2CompileZip",
 	blueprint.RuleParams{
-		Command: `${config.ZipSyncCmd} -d $resZipDir $in && ` +
+		Command: `${config.ZipSyncCmd} -d $resZipDir $zipSyncFlags $in && ` +
 			`${config.Aapt2Cmd} compile -o $out $cFlags --legacy --dir $resZipDir`,
 		CommandDeps: []string{
 			"${config.Aapt2Cmd}",
 			"${config.ZipSyncCmd}",
 		},
-	}, "cFlags", "resZipDir")
+	}, "cFlags", "resZipDir", "zipSyncFlags")
 
-func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path) {
+func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path, zipPrefix string) {
+	if zipPrefix != "" {
+		zipPrefix = "--zip-prefix " + zipPrefix
+	}
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        aapt2CompileZipRule,
 		Description: "aapt2 compile zip",
@@ -128,8 +116,9 @@
 		Args: map[string]string{
 			// Always set --pseudo-localize, it will be stripped out later for release
 			// builds that don't want it.
-			"cFlags":    "--pseudo-localize",
-			"resZipDir": android.PathForModuleOut(ctx, "aapt2", "reszip", flata.Base()).String(),
+			"cFlags":       "--pseudo-localize",
+			"resZipDir":    android.PathForModuleOut(ctx, "aapt2", "reszip", flata.Base()).String(),
+			"zipSyncFlags": zipPrefix,
 		},
 	})
 }
diff --git a/java/aar.go b/java/aar.go
index 1b84a47..1e8e6d8 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -245,7 +245,7 @@
 
 	for i, zip := range resZips {
 		flata := android.PathForModuleOut(ctx, fmt.Sprintf("reszip.%d.flata", i))
-		aapt2CompileZip(ctx, flata, zip)
+		aapt2CompileZip(ctx, flata, zip, "")
 		compiledResDirs = append(compiledResDirs, android.Paths{flata})
 	}
 
@@ -556,13 +556,13 @@
 }
 
 // Unzip an AAR into its constituent files and directories.  Any files in Outputs that don't exist in the AAR will be
-// touched to create an empty file, and any directories in $expectedDirs will be created.
+// touched to create an empty file. The res directory is not extracted, as it will be extracted in its own rule.
 var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
 	blueprint.RuleParams{
-		Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` +
-			`unzip -qo -d $outDir $in && touch $out`,
+		Command: `rm -rf $outDir && mkdir -p $outDir && ` +
+			`unzip -qo -d $outDir $in && rm -rf $outDir/res && touch $out`,
 	},
-	"expectedDirs", "outDir")
+	"outDir")
 
 func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	if len(a.properties.Aars) != 1 {
@@ -580,7 +580,6 @@
 	}
 
 	extractedAARDir := android.PathForModuleOut(ctx, "aar")
-	extractedResDir := extractedAARDir.Join(ctx, "res")
 	a.classpathFile = extractedAARDir.Join(ctx, "classes.jar")
 	a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
 	a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
@@ -591,16 +590,13 @@
 		Outputs:     android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest},
 		Description: "unzip AAR",
 		Args: map[string]string{
-			"expectedDirs": extractedResDir.String(),
-			"outDir":       extractedAARDir.String(),
+			"outDir": extractedAARDir.String(),
 		},
 	})
 
 	compiledResDir := android.PathForModuleOut(ctx, "flat-res")
-	aaptCompileDeps := android.Paths{a.classpathFile}
-	aaptCompileDirs := android.Paths{extractedResDir}
 	flata := compiledResDir.Join(ctx, "gen_res.flata")
-	aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps)
+	aapt2CompileZip(ctx, flata, aar, "res")
 
 	a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
 	srcJar := android.PathForModuleGen(ctx, "R.jar")
diff --git a/java/app.go b/java/app.go
index 3c8f847..cf9354f 100644
--- a/java/app.go
+++ b/java/app.go
@@ -482,7 +482,7 @@
 	return jniLibs, certificates
 }
 
-func (a *AndroidApp) getCertString(ctx android.BaseContext) string {
+func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string {
 	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
 	if overridden {
 		return ":" + certificate
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 0ec7799..c4624d8 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1751,7 +1751,7 @@
 		jdiff := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jdiff.jar")
 		jdiffImplicits = append(jdiffImplicits, android.Paths{jdiff, d.apiXmlFile, d.lastReleasedApiXmlFile}...)
 
-		opts := " -encoding UTF-8 -source 1.8 -J-Xmx1600m -XDignore.symbol.file " +
+		opts := " -source 1.8 -J-Xmx1600m -XDignore.symbol.file " +
 			"-doclet jdiff.JDiff -docletpath " + jdiff.String() + " -quiet " +
 			"-newapi " + strings.TrimSuffix(d.apiXmlFile.Base(), d.apiXmlFile.Ext()) +
 			" -newapidir " + filepath.Dir(d.apiXmlFile.String()) +
diff --git a/java/java.go b/java/java.go
index 5544f57..fee262d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -380,8 +380,8 @@
 }
 
 type SdkLibraryDependency interface {
-	SdkHeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths
-	SdkImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths
+	SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths
+	SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths
 }
 
 type SrcDependency interface {
@@ -448,11 +448,11 @@
 	target android.Target
 }
 
-func (j *Module) shouldInstrument(ctx android.BaseContext) bool {
+func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
 	return j.properties.Instrument && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
 }
 
-func (j *Module) shouldInstrumentStatic(ctx android.BaseContext) bool {
+func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
 	return j.shouldInstrument(ctx) &&
 		(ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_STATIC") ||
 			ctx.Config().UnbundledBuild())
diff --git a/java/sdk.go b/java/sdk.go
index 506edfb..90b8fac 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -46,7 +46,7 @@
 	targetSdkVersion() string
 }
 
-func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
+func sdkVersionOrDefault(ctx android.BaseModuleContext, v string) string {
 	switch v {
 	case "", "current", "system_current", "test_current", "core_current":
 		return ctx.Config().DefaultAppTargetSdk()
@@ -57,7 +57,7 @@
 
 // Returns a sdk version as a number.  For modules targeting an unreleased SDK (meaning it does not yet have a number)
 // it returns android.FutureApiLevel (10000).
-func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
+func sdkVersionToNumber(ctx android.BaseModuleContext, v string) (int, error) {
 	switch v {
 	case "", "current", "test_current", "system_current", "core_current":
 		return ctx.Config().DefaultAppTargetSdkInt(), nil
@@ -71,7 +71,7 @@
 	}
 }
 
-func sdkVersionToNumberAsString(ctx android.BaseContext, v string) (string, error) {
+func sdkVersionToNumberAsString(ctx android.BaseModuleContext, v string) (string, error) {
 	n, err := sdkVersionToNumber(ctx, v)
 	if err != nil {
 		return "", err
@@ -79,7 +79,7 @@
 	return strconv.Itoa(n), nil
 }
 
-func decodeSdkDep(ctx android.BaseContext, sdkContext sdkContext) sdkDep {
+func decodeSdkDep(ctx android.BaseModuleContext, sdkContext sdkContext) sdkDep {
 	v := sdkContext.sdkVersion()
 	// For PDK builds, use the latest SDK version instead of "current"
 	if ctx.Config().IsPdkBuild() && (v == "" || v == "current") {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 5b65c0c..e383533 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -591,7 +591,7 @@
 	mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
 }
 
-func (module *SdkLibrary) PrebuiltJars(ctx android.BaseContext, sdkVersion string) android.Paths {
+func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
 	var api, v string
 	if sdkVersion == "" {
 		api = "system"
@@ -615,7 +615,7 @@
 }
 
 // to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths {
+func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
 	// This module is just a wrapper for the stubs.
 	if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
 		return module.PrebuiltJars(ctx, sdkVersion)
@@ -631,7 +631,7 @@
 }
 
 // to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths {
+func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
 	// This module is just a wrapper for the stubs.
 	if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
 		return module.PrebuiltJars(ctx, sdkVersion)
@@ -840,13 +840,13 @@
 }
 
 // to satisfy SdkLibraryDependency interface
-func (module *sdkLibraryImport) SdkHeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths {
+func (module *sdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
 	// This module is just a wrapper for the prebuilt stubs.
 	return module.stubsPath
 }
 
 // to satisfy SdkLibraryDependency interface
-func (module *sdkLibraryImport) SdkImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths {
+func (module *sdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
 	// This module is just a wrapper for the stubs.
 	return module.stubsPath
 }
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 3f2709e..86061c6 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -123,6 +123,8 @@
 		Sysprop          struct {
 			Platform *bool
 		}
+		Header_libs []string
+		Shared_libs []string
 	}{}
 
 	ccProps.Name = proptools.StringPtr(m.CcModuleName())
@@ -130,6 +132,8 @@
 	ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
 	ccProps.Product_specific = proptools.BoolPtr(productSpecific)
 	ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
+	ccProps.Header_libs = []string{"libbase_headers"}
+	ccProps.Shared_libs = []string{"liblog"}
 
 	ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &m.commonProperties, &ccProps)
 }