Merge "Use empty string for core image variant"
diff --git a/android/apex.go b/android/apex.go
index 44387cd..3da4828 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -179,7 +179,7 @@
 		m.checkApexAvailableProperty(mctx)
 		sort.Strings(m.apexVariations)
 		variations := []string{}
-		availableForPlatform := mctx.Module().(ApexModule).AvailableFor(availableToPlatform)
+		availableForPlatform := mctx.Module().(ApexModule).AvailableFor(availableToPlatform) || mctx.Host()
 		if availableForPlatform {
 			variations = append(variations, "") // Original variation for platform
 		}
diff --git a/android/module.go b/android/module.go
index b4f8f1a..b858564 100644
--- a/android/module.go
+++ b/android/module.go
@@ -302,9 +302,6 @@
 	// If a module does not specify the `visibility` property then it uses the
 	// `default_visibility` property of the `package` module in the module's package.
 	//
-	// If a module does not specify the `visibility` property then it uses the
-	// `default_visibility` property of the `package` module in the module's package.
-	//
 	// If the `default_visibility` property is not set for the module's package then
 	// it will use the `default_visibility` of its closest ancestor package for which
 	// a `default_visibility` property is specified.
diff --git a/android/sdk.go b/android/sdk.go
index 533bd0e..7956434 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"sort"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -218,18 +219,24 @@
 // The basic implementation should look something like this, where ModuleType is
 // the name of the module type being supported.
 //
-//    var ModuleTypeSdkMemberType = newModuleTypeSdkMemberType()
-//
-//    func newModuleTypeSdkMemberType() android.SdkMemberType {
-//    	return &moduleTypeSdkMemberType{}
+//    type moduleTypeSdkMemberType struct {
+//        android.SdkMemberTypeBase
 //    }
 //
-//    type moduleTypeSdkMemberType struct {
+//    func init() {
+//        android.RegisterSdkMemberType(&moduleTypeSdkMemberType{
+//            SdkMemberTypeBase: android.SdkMemberTypeBase{
+//                PropertyName: "module_types",
+//            },
+//        }
 //    }
 //
 //    ...methods...
 //
 type SdkMemberType interface {
+	// The name of the member type property on an sdk module.
+	SdkPropertyName() string
+
 	// Add dependencies from the SDK module to all the variants the member
 	// contributes to the SDK. The exact set of variants required is determined
 	// by the SDK and its properties. The dependencies must be added with the
@@ -254,3 +261,66 @@
 	// IsInstance(Module) method returned true.
 	BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember)
 }
+
+type SdkMemberTypeBase struct {
+	PropertyName string
+}
+
+func (b *SdkMemberTypeBase) SdkPropertyName() string {
+	return b.PropertyName
+}
+
+// Encapsulates the information about registered SdkMemberTypes.
+type SdkMemberTypesRegistry struct {
+	// The list of types sorted by property name.
+	list []SdkMemberType
+
+	// The key that uniquely identifies this registry instance.
+	key OnceKey
+}
+
+func (r *SdkMemberTypesRegistry) RegisteredTypes() []SdkMemberType {
+	return r.list
+}
+
+func (r *SdkMemberTypesRegistry) UniqueOnceKey() OnceKey {
+	// Use the pointer to the registry as the unique key.
+	return NewCustomOnceKey(r)
+}
+
+// The set of registered SdkMemberTypes.
+var SdkMemberTypes = &SdkMemberTypesRegistry{}
+
+// Register an SdkMemberType object to allow them to be used in the sdk and sdk_snapshot module
+// types.
+func RegisterSdkMemberType(memberType SdkMemberType) {
+	oldList := SdkMemberTypes.list
+
+	// Copy the slice just in case this is being read while being modified, e.g. when testing.
+	list := make([]SdkMemberType, 0, len(oldList)+1)
+	list = append(list, oldList...)
+	list = append(list, memberType)
+
+	// Sort the member types by their property name to ensure that registry order has no effect
+	// on behavior.
+	sort.Slice(list, func(i1, i2 int) bool {
+		t1 := list[i1]
+		t2 := list[i2]
+
+		return t1.SdkPropertyName() < t2.SdkPropertyName()
+	})
+
+	// Generate a key that identifies the slice of SdkMemberTypes by joining the property names
+	// from all the SdkMemberType .
+	var properties []string
+	for _, t := range list {
+		properties = append(properties, t.SdkPropertyName())
+	}
+	key := NewOnceKey(strings.Join(properties, "|"))
+
+	// Create a new registry so the pointer uniquely identifies the set of registered types.
+	SdkMemberTypes = &SdkMemberTypesRegistry{
+		list: list,
+		key:  key,
+	}
+}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 35622f0..a231a90 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -63,7 +63,11 @@
 		}
 
 		fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
-		fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+		if fi.moduleDir != "" {
+			fmt.Fprintln(w, "LOCAL_PATH :=", fi.moduleDir)
+		} else {
+			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+		}
 		fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
 		// /apex/<apex_name>/{lib|framework|...}
 		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
diff --git a/apex/apex.go b/apex/apex.go
index be86d80..3d7b45d 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -459,20 +459,25 @@
 	// list of symlinks that will be created in installDir that point to this apexFile
 	symlinks      []string
 	transitiveDep bool
+	moduleDir     string
 }
 
-func newApexFile(builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
-	return apexFile{
+func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
+	ret := apexFile{
 		builtFile:  builtFile,
 		moduleName: moduleName,
 		installDir: installDir,
 		class:      class,
 		module:     module,
 	}
+	if module != nil {
+		ret.moduleDir = ctx.OtherModuleDir(module)
+	}
+	return ret
 }
 
 func (af *apexFile) Ok() bool {
-	return af.builtFile != nil || af.builtFile.String() == ""
+	return af.builtFile != nil && af.builtFile.String() != ""
 }
 
 type apexBundle struct {
@@ -789,7 +794,7 @@
 }
 
 // TODO(jiyong) move apexFileFor* close to the apexFile type definition
-func apexFileForNativeLibrary(ccMod *cc.Module, config android.Config, handleSpecialLibs bool) apexFile {
+func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile {
 	// Decide the APEX-local directory by the multilib of the library
 	// In the future, we may query this to the module.
 	var dirInApex string
@@ -803,7 +808,7 @@
 	if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
 		dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
 	}
-	if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), config) {
+	if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) {
 		// Special case for Bionic libs and other libs installed with them. This is
 		// to prevent those libs from being included in the search path
 		// /apex/com.android.runtime/${LIB}. This exclusion is required because
@@ -818,26 +823,26 @@
 	}
 
 	fileToCopy := ccMod.OutputFile().Path()
-	return newApexFile(fileToCopy, ccMod.Name(), dirInApex, nativeSharedLib, ccMod)
+	return newApexFile(ctx, fileToCopy, ccMod.Name(), dirInApex, nativeSharedLib, ccMod)
 }
 
-func apexFileForExecutable(cc *cc.Module) apexFile {
+func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile {
 	dirInApex := filepath.Join("bin", cc.RelativeInstallPath())
 	if cc.Target().NativeBridge == android.NativeBridgeEnabled {
 		dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
 	}
 	fileToCopy := cc.OutputFile().Path()
-	af := newApexFile(fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
+	af := newApexFile(ctx, fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
 	af.symlinks = cc.Symlinks()
 	return af
 }
 
-func apexFileForPyBinary(py *python.Module) apexFile {
+func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.Module) apexFile {
 	dirInApex := "bin"
 	fileToCopy := py.HostToolPath().Path()
-	return newApexFile(fileToCopy, py.Name(), dirInApex, pyBinary, py)
+	return newApexFile(ctx, fileToCopy, py.Name(), dirInApex, pyBinary, py)
 }
-func apexFileForGoBinary(ctx android.ModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile {
+func apexFileForGoBinary(ctx android.BaseModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile {
 	dirInApex := "bin"
 	s, err := filepath.Rel(android.PathForOutput(ctx).String(), gb.InstallPath())
 	if err != nil {
@@ -848,24 +853,24 @@
 	// NB: Since go binaries are static we don't need the module for anything here, which is
 	// good since the go tool is a blueprint.Module not an android.Module like we would
 	// normally use.
-	return newApexFile(fileToCopy, depName, dirInApex, goBinary, nil)
+	return newApexFile(ctx, fileToCopy, depName, dirInApex, goBinary, nil)
 }
 
-func apexFileForShBinary(sh *android.ShBinary) apexFile {
+func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) apexFile {
 	dirInApex := filepath.Join("bin", sh.SubDir())
 	fileToCopy := sh.OutputFile()
-	af := newApexFile(fileToCopy, sh.Name(), dirInApex, shBinary, sh)
+	af := newApexFile(ctx, fileToCopy, sh.Name(), dirInApex, shBinary, sh)
 	af.symlinks = sh.Symlinks()
 	return af
 }
 
-func apexFileForJavaLibrary(java *java.Library) apexFile {
+func apexFileForJavaLibrary(ctx android.BaseModuleContext, java *java.Library) apexFile {
 	dirInApex := "javalib"
 	fileToCopy := java.DexJarFile()
-	return newApexFile(fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
+	return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
 }
 
-func apexFileForPrebuiltJavaLibrary(java *java.Import) apexFile {
+func apexFileForPrebuiltJavaLibrary(ctx android.BaseModuleContext, java *java.Import) apexFile {
 	dirInApex := "javalib"
 	// The output is only one, but for some reason, ImplementationJars returns Paths, not Path
 	implJars := java.ImplementationJars()
@@ -874,16 +879,16 @@
 			strings.Join(implJars.Strings(), ", ")))
 	}
 	fileToCopy := implJars[0]
-	return newApexFile(fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
+	return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
 }
 
-func apexFileForPrebuiltEtc(prebuilt android.PrebuiltEtcModule, depName string) apexFile {
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt android.PrebuiltEtcModule, depName string) apexFile {
 	dirInApex := filepath.Join("etc", prebuilt.SubDir())
 	fileToCopy := prebuilt.OutputFile()
-	return newApexFile(fileToCopy, depName, dirInApex, etc, prebuilt)
+	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
 }
 
-func apexFileForAndroidApp(aapp interface {
+func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface {
 	android.Module
 	Privileged() bool
 	OutputFile() android.Path
@@ -894,7 +899,7 @@
 	}
 	dirInApex := filepath.Join(appDir, pkgName)
 	fileToCopy := aapp.OutputFile()
-	return newApexFile(fileToCopy, aapp.Name(), dirInApex, app, aapp)
+	return newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
 }
 
 // Context "decorator", overriding the InstallBypassMake method to always reply `true`.
@@ -982,19 +987,19 @@
 					if cc.HasStubsVariants() {
 						provideNativeLibs = append(provideNativeLibs, cc.OutputFile().Path().Base())
 					}
-					filesInfo = append(filesInfo, apexFileForNativeLibrary(cc, ctx.Config(), handleSpecialLibs))
+					filesInfo = append(filesInfo, apexFileForNativeLibrary(ctx, cc, handleSpecialLibs))
 					return true // track transitive dependencies
 				} else {
 					ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
 				}
 			case executableTag:
 				if cc, ok := child.(*cc.Module); ok {
-					filesInfo = append(filesInfo, apexFileForExecutable(cc))
+					filesInfo = append(filesInfo, apexFileForExecutable(ctx, cc))
 					return true // track transitive dependencies
 				} else if sh, ok := child.(*android.ShBinary); ok {
-					filesInfo = append(filesInfo, apexFileForShBinary(sh))
+					filesInfo = append(filesInfo, apexFileForShBinary(ctx, sh))
 				} else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
-					filesInfo = append(filesInfo, apexFileForPyBinary(py))
+					filesInfo = append(filesInfo, apexFileForPyBinary(ctx, py))
 				} else if gb, ok := child.(bootstrap.GoBinaryTool); ok && a.Host() {
 					filesInfo = append(filesInfo, apexFileForGoBinary(ctx, depName, gb))
 				} else {
@@ -1002,7 +1007,7 @@
 				}
 			case javaLibTag:
 				if javaLib, ok := child.(*java.Library); ok {
-					af := apexFileForJavaLibrary(javaLib)
+					af := apexFileForJavaLibrary(ctx, javaLib)
 					if !af.Ok() {
 						ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
 					} else {
@@ -1010,7 +1015,7 @@
 						return true // track transitive dependencies
 					}
 				} else if javaLib, ok := child.(*java.Import); ok {
-					af := apexFileForPrebuiltJavaLibrary(javaLib)
+					af := apexFileForPrebuiltJavaLibrary(ctx, javaLib)
 					if !af.Ok() {
 						ctx.PropertyErrorf("java_libs", "%q does not have a jar output", depName)
 					} else {
@@ -1022,16 +1027,16 @@
 			case androidAppTag:
 				pkgName := ctx.DeviceConfig().OverridePackageNameFor(depName)
 				if ap, ok := child.(*java.AndroidApp); ok {
-					filesInfo = append(filesInfo, apexFileForAndroidApp(ap, pkgName))
+					filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
 					return true // track transitive dependencies
 				} else if ap, ok := child.(*java.AndroidAppImport); ok {
-					filesInfo = append(filesInfo, apexFileForAndroidApp(ap, pkgName))
+					filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
 				} else {
 					ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
 				}
 			case prebuiltTag:
 				if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
-					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(prebuilt, depName))
+					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
 				} else {
 					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
 				}
@@ -1047,7 +1052,7 @@
 						return true
 					} else {
 						// Single-output test module (where `test_per_src: false`).
-						af := apexFileForExecutable(ccTest)
+						af := apexFileForExecutable(ctx, ccTest)
 						af.class = nativeTest
 						filesInfo = append(filesInfo, af)
 					}
@@ -1103,14 +1108,14 @@
 							// Don't track further
 							return false
 						}
-						af := apexFileForNativeLibrary(cc, ctx.Config(), handleSpecialLibs)
+						af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
 						af.transitiveDep = true
 						filesInfo = append(filesInfo, af)
 						return true // track transitive dependencies
 					}
 				} else if cc.IsTestPerSrcDepTag(depTag) {
 					if cc, ok := child.(*cc.Module); ok {
-						af := apexFileForExecutable(cc)
+						af := apexFileForExecutable(ctx, cc)
 						// Handle modules created as `test_per_src` variations of a single test module:
 						// use the name of the generated test binary (`fileToCopy`) instead of the name
 						// of the original test module (`depName`, shared by all `test_per_src`
@@ -1139,7 +1144,7 @@
 			dirInApex := filepath.Join("javalib", arch.String())
 			for _, f := range files {
 				localModule := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
-				af := newApexFile(f, localModule, dirInApex, etc, nil)
+				af := newApexFile(ctx, f, localModule, dirInApex, etc, nil)
 				filesInfo = append(filesInfo, af)
 			}
 		}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 6cf4337..4f0ab3a 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3055,6 +3055,29 @@
 	ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String())
 }
 
+func TestRejectNonInstallableJavaLibrary(t *testing.T) {
+	testApexError(t, `"myjar" is not configured to be compiled into dex`, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			java_libs: ["myjar"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_library {
+			name: "myjar",
+			srcs: ["foo/bar/MyClass.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+	`)
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/apex/builder.go b/apex/builder.go
index cbbf5f8..a90918d 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -511,7 +511,7 @@
 	if a.installable() {
 		// For flattened APEX, do nothing but make sure that APEX manifest and apex_pubkey are also copied along
 		// with other ordinary files.
-		a.filesInfo = append(a.filesInfo, newApexFile(a.manifestPbOut, "apex_manifest.pb."+a.Name()+a.suffix, ".", etc, nil))
+		a.filesInfo = append(a.filesInfo, newApexFile(ctx, a.manifestPbOut, "apex_manifest.pb."+a.Name()+a.suffix, ".", etc, nil))
 
 		// rename to apex_pubkey
 		copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
@@ -520,7 +520,7 @@
 			Input:  a.public_key_file,
 			Output: copiedPubkey,
 		})
-		a.filesInfo = append(a.filesInfo, newApexFile(copiedPubkey, "apex_pubkey."+a.Name()+a.suffix, ".", etc, nil))
+		a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey."+a.Name()+a.suffix, ".", etc, nil))
 
 		if a.properties.ApexType == flattenedApex {
 			apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 6b09c12..9319070 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -24,17 +24,28 @@
 
 // This file contains support for using cc library modules within an sdk.
 
-var SharedLibrarySdkMemberType = &librarySdkMemberType{
-	prebuiltModuleType: "cc_prebuilt_library_shared",
-	linkTypes:          []string{"shared"},
-}
+func init() {
+	// Register sdk member types.
+	android.RegisterSdkMemberType(&librarySdkMemberType{
+		SdkMemberTypeBase: android.SdkMemberTypeBase{
+			PropertyName: "native_shared_libs",
+		},
+		prebuiltModuleType: "cc_prebuilt_library_shared",
+		linkTypes:          []string{"shared"},
+	})
 
-var StaticLibrarySdkMemberType = &librarySdkMemberType{
-	prebuiltModuleType: "cc_prebuilt_library_static",
-	linkTypes:          []string{"static"},
+	android.RegisterSdkMemberType(&librarySdkMemberType{
+		SdkMemberTypeBase: android.SdkMemberTypeBase{
+			PropertyName: "native_static_libs",
+		},
+		prebuiltModuleType: "cc_prebuilt_library_static",
+		linkTypes:          []string{"static"},
+	})
 }
 
 type librarySdkMemberType struct {
+	android.SdkMemberTypeBase
+
 	prebuiltModuleType string
 
 	// The set of link types supported, set of "static", "shared".
diff --git a/java/app.go b/java/app.go
index c772e47..7595e36 100755
--- a/java/app.go
+++ b/java/app.go
@@ -632,6 +632,17 @@
 
 	a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config,
 		a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config)
+	if a.overridableAppProperties.Package_name != nil {
+		fixedConfig := android.PathForModuleOut(ctx, "test_config_fixer", "AndroidTest.xml")
+		rule := android.NewRuleBuilder()
+		rule.Command().BuiltTool(ctx, "test_config_fixer").
+			FlagWithArg("--manifest ", a.manifestPath.String()).
+			FlagWithArg("--package-name ", *a.overridableAppProperties.Package_name).
+			Input(a.testConfig).
+			Output(fixedConfig)
+		rule.Build(pctx, ctx, "fix_test_config", "fix test config")
+		a.testConfig = fixedConfig
+	}
 	a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
 }
 
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 76cdaea..92f9246 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -40,6 +40,13 @@
 	android.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
 
 	android.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
+
+	// Register sdk member type.
+	android.RegisterSdkMemberType(&droidStubsSdkMemberType{
+		SdkMemberTypeBase: android.SdkMemberTypeBase{
+			PropertyName: "stubs_sources",
+		},
+	})
 }
 
 var (
@@ -1974,9 +1981,8 @@
 	return module
 }
 
-var DroidStubsSdkMemberType = &droidStubsSdkMemberType{}
-
 type droidStubsSdkMemberType struct {
+	android.SdkMemberTypeBase
 }
 
 func (mt *droidStubsSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
diff --git a/java/java.go b/java/java.go
index f58e5ba..d8db5f8 100644
--- a/java/java.go
+++ b/java/java.go
@@ -52,6 +52,23 @@
 
 	android.RegisterSingletonType("logtags", LogtagsSingleton)
 	android.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
+
+	// Register sdk member types.
+	android.RegisterSdkMemberType(&headerLibrarySdkMemberType{
+		librarySdkMemberType{
+			android.SdkMemberTypeBase{
+				PropertyName: "java_header_libs",
+			},
+		},
+	})
+
+	android.RegisterSdkMemberType(&implLibrarySdkMemberType{
+		librarySdkMemberType{
+			android.SdkMemberTypeBase{
+				PropertyName: "java_libs",
+			},
+		},
+	})
 }
 
 func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
@@ -1721,6 +1738,7 @@
 }
 
 type librarySdkMemberType struct {
+	android.SdkMemberTypeBase
 }
 
 func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
@@ -1764,8 +1782,6 @@
 	module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
 }
 
-var HeaderLibrarySdkMemberType = &headerLibrarySdkMemberType{}
-
 type headerLibrarySdkMemberType struct {
 	librarySdkMemberType
 }
@@ -1781,8 +1797,6 @@
 	})
 }
 
-var ImplLibrarySdkMemberType = &implLibrarySdkMemberType{}
-
 type implLibrarySdkMemberType struct {
 	librarySdkMemberType
 }
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 8c59cbc..4aaff9a 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -85,3 +85,39 @@
         },
     }
 }
+
+python_binary_host {
+    name: "test_config_fixer",
+    main: "test_config_fixer.py",
+    srcs: [
+        "test_config_fixer.py",
+        "manifest.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+}
+
+python_test_host {
+    name: "test_config_fixer_test",
+    main: "test_config_fixer_test.py",
+    srcs: [
+        "test_config_fixer_test.py",
+        "test_config_fixer.py",
+        "manifest.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+    test_suites: ["general-tests"],
+}
\ No newline at end of file
diff --git a/scripts/manifest.py b/scripts/manifest.py
index 4c75f8b..04f7405 100755
--- a/scripts/manifest.py
+++ b/scripts/manifest.py
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-"""A tool for inserting values from the build system into a manifest."""
+"""A tool for inserting values from the build system into a manifest or a test config."""
 
 from __future__ import print_function
 from xml.dom import minidom
@@ -65,6 +65,15 @@
                        ns.value)
 
 
+def parse_test_config(doc):
+  """ Get the configuration element. """
+
+  test_config = doc.documentElement
+  if test_config.tagName != 'configuration':
+    raise RuntimeError('expected configuration tag at root')
+  return test_config
+
+
 def as_int(s):
   try:
     i = int(s)
diff --git a/scripts/test_config_fixer.py b/scripts/test_config_fixer.py
new file mode 100644
index 0000000..7bb4b52
--- /dev/null
+++ b/scripts/test_config_fixer.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""A tool for modifying values in a test config."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+from xml.dom import minidom
+
+
+from manifest import get_children_with_tag
+from manifest import parse_manifest
+from manifest import parse_test_config
+from manifest import write_xml
+
+
+def parse_args():
+  """Parse commandline arguments."""
+
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--manifest', default='', dest='manifest',
+                      help=('AndroidManifest.xml that contains the original package name'))
+  parser.add_argument('--package-name', default='', dest='package_name',
+                      help=('overwrite package fields in the test config'))
+  parser.add_argument('input', help='input test config file')
+  parser.add_argument('output', help='output test config file')
+  return parser.parse_args()
+
+
+def overwrite_package_name(test_config_doc, manifest_doc, package_name):
+
+  manifest = parse_manifest(manifest_doc)
+  original_package = manifest.getAttribute('package')
+  print('package: ' + original_package)
+
+  test_config = parse_test_config(test_config_doc)
+  tests = get_children_with_tag(test_config, 'test')
+
+  for test in tests:
+    options = get_children_with_tag(test, 'option')
+    for option in options:
+      if option.getAttribute('name') == "package" and option.getAttribute('value') == original_package:
+        option.setAttribute('value', package_name)
+
+def main():
+  """Program entry point."""
+  try:
+    args = parse_args()
+
+    doc = minidom.parse(args.input)
+
+    if args.package_name:
+      if not args.manifest:
+        raise RuntimeError('--manifest flag required for --package-name')
+      manifest_doc = minidom.parse(args.manifest)
+      overwrite_package_name(doc, manifest_doc, args.package_name)
+
+    with open(args.output, 'wb') as f:
+      write_xml(f, doc)
+
+  # pylint: disable=broad-except
+  except Exception as err:
+    print('error: ' + str(err), file=sys.stderr)
+    sys.exit(-1)
+
+if __name__ == '__main__':
+  main()
diff --git a/scripts/test_config_fixer_test.py b/scripts/test_config_fixer_test.py
new file mode 100644
index 0000000..b90582e
--- /dev/null
+++ b/scripts/test_config_fixer_test.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Unit tests for test_config_fixer.py."""
+
+import StringIO
+import sys
+import unittest
+from xml.dom import minidom
+
+import test_config_fixer
+
+sys.dont_write_bytecode = True
+
+
+class OverwritePackageNameTest(unittest.TestCase):
+  """ Unit tests for overwrite_package_name function """
+
+  manifest = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android"\n'
+      '    package="com.android.foo">\n'
+      '    <application>\n'
+      '    </application>\n'
+      '</manifest>\n')
+
+  test_config = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<configuration description="Runs some tests.">\n'
+      '    <option name="test-suite-tag" value="apct"/>\n'
+      '    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">\n'
+      '        <option name="package" value="%s"/>\n'
+      '    </target_preparer>\n'
+      '    <test class="com.android.tradefed.testtype.AndroidJUnitTest">\n'
+      '        <option name="package" value="%s"/>\n'
+      '        <option name="runtime-hint" value="20s"/>\n'
+      '    </test>\n'
+      '    <test class="com.android.tradefed.testtype.AndroidJUnitTest">\n'
+      '        <option name="package" value="%s"/>\n'
+      '        <option name="runtime-hint" value="15s"/>\n'
+      '    </test>\n'
+      '</configuration>\n')
+
+  def test_all(self):
+    doc = minidom.parseString(self.test_config % ("com.android.foo", "com.android.foo", "com.android.bar"))
+    manifest = minidom.parseString(self.manifest)
+
+    test_config_fixer.overwrite_package_name(doc, manifest, "com.soong.foo")
+    output = StringIO.StringIO()
+    test_config_fixer.write_xml(output, doc)
+
+    # Only the matching package name in a test node should be updated.
+    expected = self.test_config % ("com.android.foo", "com.soong.foo", "com.android.bar")
+    self.assertEqual(expected, output.getvalue())
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/sdk/sdk.go b/sdk/sdk.go
index cd9aafa..62bc06f 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"io"
+	"reflect"
 	"strconv"
 
 	"github.com/google/blueprint"
@@ -26,8 +27,6 @@
 	// This package doesn't depend on the apex package, but import it to make its mutators to be
 	// registered before mutators in this package. See RegisterPostDepsMutators for more details.
 	_ "android/soong/apex"
-	"android/soong/cc"
-	"android/soong/java"
 )
 
 func init() {
@@ -38,20 +37,19 @@
 	android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
 	android.PreDepsMutators(RegisterPreDepsMutators)
 	android.PostDepsMutators(RegisterPostDepsMutators)
-
-	// Populate the dependency tags for each member list property.  This needs to
-	// be done here to break an initialization cycle.
-	for _, memberListProperty := range sdkMemberListProperties {
-		memberListProperty.dependencyTag = &sdkMemberDependencyTag{
-			memberListProperty: memberListProperty,
-		}
-	}
 }
 
 type sdk struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
 
+	// The dynamically generated information about the registered SdkMemberType
+	dynamicSdkMemberTypes *dynamicSdkMemberTypes
+
+	// The dynamically created instance of the properties struct containing the sdk member
+	// list properties, e.g. java_libs.
+	dynamicMemberTypeListProperties interface{}
+
 	properties sdkProperties
 
 	snapshotFile android.OptionalPath
@@ -61,92 +59,141 @@
 }
 
 type sdkProperties struct {
-	// For module types from the cc package
-
-	// The list of shared native libraries in this SDK
-	Native_shared_libs []string
-
-	// The list of static native libraries in this SDK
-	Native_static_libs []string
-
-	// For module types from the java package
-
-	// The list of java header libraries in this SDK
-	//
-	// This should be used for java libraries that are provided separately at runtime,
-	// e.g. through an APEX.
-	Java_header_libs []string
-
-	// The list of java implementation libraries in this SDK
-	Java_libs []string
-
-	// The list of stub sources in this SDK
-	Stubs_sources []string
-
 	Snapshot bool `blueprint:"mutated"`
 }
 
 type sdkMemberDependencyTag struct {
 	blueprint.BaseDependencyTag
-	memberListProperty *sdkMemberListProperty
+	memberType android.SdkMemberType
 }
 
 // Contains information about the sdk properties that list sdk members, e.g.
 // Java_header_libs.
 type sdkMemberListProperty struct {
-	// the name of the property as used in a .bp file
-	name string
-
 	// getter for the list of member names
-	getter func(properties *sdkProperties) []string
+	getter func(properties interface{}) []string
 
 	// the type of member referenced in the list
 	memberType android.SdkMemberType
 
-	// the dependency tag used for items in this list.
+	// the dependency tag used for items in this list that can be used to determine the memberType
+	// for a resolved dependency.
 	dependencyTag *sdkMemberDependencyTag
 }
 
-// Information about how to handle each member list property.
+func (p *sdkMemberListProperty) propertyName() string {
+	return p.memberType.SdkPropertyName()
+}
+
+// Cache of dynamically generated dynamicSdkMemberTypes objects. The key is the pointer
+// to a slice of SdkMemberType instances held in android.SdkMemberTypes.
+var dynamicSdkMemberTypesMap android.OncePer
+
+// A dynamically generated set of member list properties and associated structure type.
+type dynamicSdkMemberTypes struct {
+	// The dynamically generated structure type.
+	//
+	// Contains one []string exported field for each android.SdkMemberTypes. The name of the field
+	// is the exported form of the value returned by SdkMemberType.SdkPropertyName().
+	propertiesStructType reflect.Type
+
+	// Information about each of the member type specific list properties.
+	memberListProperties []*sdkMemberListProperty
+}
+
+func (d *dynamicSdkMemberTypes) createMemberListProperties() interface{} {
+	return reflect.New(d.propertiesStructType).Interface()
+}
+
+func getDynamicSdkMemberTypes(registry *android.SdkMemberTypesRegistry) *dynamicSdkMemberTypes {
+
+	// Get a key that uniquely identifies the registry contents.
+	key := registry.UniqueOnceKey()
+
+	// Get the registered types.
+	registeredTypes := registry.RegisteredTypes()
+
+	// Get the cached value, creating new instance if necessary.
+	return dynamicSdkMemberTypesMap.Once(key, func() interface{} {
+		return createDynamicSdkMemberTypes(registeredTypes)
+	}).(*dynamicSdkMemberTypes)
+}
+
+// Create the dynamicSdkMemberTypes from the list of registered member types.
 //
-// It is organized first by package and then by name within the package.
-// Packages are in alphabetical order and properties are in alphabetical order
-// within each package.
-var sdkMemberListProperties = []*sdkMemberListProperty{
-	// Members from cc package.
-	{
-		name:       "native_shared_libs",
-		getter:     func(properties *sdkProperties) []string { return properties.Native_shared_libs },
-		memberType: cc.SharedLibrarySdkMemberType,
-	},
-	{
-		name:       "native_static_libs",
-		getter:     func(properties *sdkProperties) []string { return properties.Native_static_libs },
-		memberType: cc.StaticLibrarySdkMemberType,
-	},
-	// Members from java package.
-	{
-		name:       "java_header_libs",
-		getter:     func(properties *sdkProperties) []string { return properties.Java_header_libs },
-		memberType: java.HeaderLibrarySdkMemberType,
-	},
-	{
-		name:       "java_libs",
-		getter:     func(properties *sdkProperties) []string { return properties.Java_libs },
-		memberType: java.ImplLibrarySdkMemberType,
-	},
-	{
-		name:       "stubs_sources",
-		getter:     func(properties *sdkProperties) []string { return properties.Stubs_sources },
-		memberType: java.DroidStubsSdkMemberType,
-	},
+// A struct is created which contains one exported field per member type corresponding to
+// the SdkMemberType.SdkPropertyName() value.
+//
+// A list of sdkMemberListProperty instances is created, one per member type that provides:
+// * a reference to the member type.
+// * a getter for the corresponding field in the properties struct.
+// * a dependency tag that identifies the member type of a resolved dependency.
+//
+func createDynamicSdkMemberTypes(sdkMemberTypes []android.SdkMemberType) *dynamicSdkMemberTypes {
+	var listProperties []*sdkMemberListProperty
+	var fields []reflect.StructField
+
+	// Iterate over the member types creating StructField and sdkMemberListProperty objects.
+	for f, memberType := range sdkMemberTypes {
+		p := memberType.SdkPropertyName()
+
+		// Create a dynamic exported field for the member type's property.
+		fields = append(fields, reflect.StructField{
+			Name: proptools.FieldNameForProperty(p),
+			Type: reflect.TypeOf([]string{}),
+		})
+
+		// Copy the field index for use in the getter func as using the loop variable directly will
+		// cause all funcs to use the last value.
+		fieldIndex := f
+
+		// Create an sdkMemberListProperty for the member type.
+		memberListProperty := &sdkMemberListProperty{
+			getter: func(properties interface{}) []string {
+				// The properties is expected to be of the following form (where
+				// <Module_types> is the name of an SdkMemberType.SdkPropertyName().
+				//     properties *struct {<Module_types> []string, ....}
+				//
+				// Although it accesses the field by index the following reflection code is equivalent to:
+				//    *properties.<Module_types>
+				//
+				list := reflect.ValueOf(properties).Elem().Field(fieldIndex).Interface().([]string)
+				return list
+			},
+
+			memberType: memberType,
+
+			dependencyTag: &sdkMemberDependencyTag{
+				memberType: memberType,
+			},
+		}
+
+		listProperties = append(listProperties, memberListProperty)
+	}
+
+	// Create a dynamic struct from the collated fields.
+	propertiesStructType := reflect.StructOf(fields)
+
+	return &dynamicSdkMemberTypes{
+		memberListProperties: listProperties,
+		propertiesStructType: propertiesStructType,
+	}
 }
 
 // sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
 // which Mainline modules like APEX can choose to build with.
 func ModuleFactory() android.Module {
 	s := &sdk{}
-	s.AddProperties(&s.properties)
+
+	// Get the dynamic sdk member type data for the currently registered sdk member types.
+	s.dynamicSdkMemberTypes = getDynamicSdkMemberTypes(android.SdkMemberTypes)
+
+	// Create an instance of the dynamically created struct that contains all the
+	// properties for the member type specific list properties.
+	s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties()
+
+	s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties)
+
 	android.InitAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(s)
 	android.AddLoadHook(s, func(ctx android.LoadHookContext) {
@@ -235,9 +282,9 @@
 
 // Step 1: create dependencies from an SDK module to its members.
 func memberMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(*sdk); ok {
-		for _, memberListProperty := range sdkMemberListProperties {
-			names := memberListProperty.getter(&m.properties)
+	if s, ok := mctx.Module().(*sdk); ok {
+		for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+			names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
 			tag := memberListProperty.dependencyTag
 			memberListProperty.memberType.AddDependencies(mctx, tag, names)
 		}
diff --git a/sdk/update.go b/sdk/update.go
index 52d21ed..d31fa30 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -105,21 +105,20 @@
 // Collect all the members.
 //
 // The members are first grouped by type and then grouped by name. The order of
-// the types is the order they are referenced in sdkMemberListProperties. The
+// the types is the order they are referenced in android.SdkMemberTypes. The
 // names are in order in which the dependencies were added.
-func collectMembers(ctx android.ModuleContext) []*sdkMember {
+func (s *sdk) collectMembers(ctx android.ModuleContext) []*sdkMember {
 	byType := make(map[android.SdkMemberType][]*sdkMember)
 	byName := make(map[string]*sdkMember)
 
 	ctx.VisitDirectDeps(func(m android.Module) {
 		tag := ctx.OtherModuleDependencyTag(m)
 		if memberTag, ok := tag.(*sdkMemberDependencyTag); ok {
-			memberListProperty := memberTag.memberListProperty
-			memberType := memberListProperty.memberType
+			memberType := memberTag.memberType
 
 			// Make sure that the resolved module is allowed in the member list property.
 			if !memberType.IsInstance(m) {
-				ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(m), memberListProperty.name)
+				ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(m), memberType.SdkPropertyName())
 			}
 
 			name := ctx.OtherModuleName(m)
@@ -136,7 +135,7 @@
 	})
 
 	var members []*sdkMember
-	for _, memberListProperty := range sdkMemberListProperties {
+	for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
 		membersOfType := byType[memberListProperty.memberType]
 		members = append(members, membersOfType...)
 	}
@@ -191,7 +190,7 @@
 	}
 	s.builderForTests = builder
 
-	for _, member := range collectMembers(ctx) {
+	for _, member := range s.collectMembers(ctx) {
 		member.memberType.BuildSnapshot(ctx, builder, member)
 	}
 
@@ -220,10 +219,10 @@
 	}
 
 	addHostDeviceSupportedProperties(&s.ModuleBase, snapshotModule)
-	for _, memberListProperty := range sdkMemberListProperties {
-		names := memberListProperty.getter(&s.properties)
+	for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+		names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
 		if len(names) > 0 {
-			snapshotModule.AddProperty(memberListProperty.name, builder.versionedSdkMemberNames(names))
+			snapshotModule.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names))
 		}
 	}
 	bpFile.AddModule(snapshotModule)
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 307475a..ac09ce1 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -151,6 +151,45 @@
 		"KATI_PACKAGE_MK_DIR="+config.KatiPackageMkDir())
 
 	runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
+
+	cleanCopyHeaders(ctx, config)
+}
+
+func cleanCopyHeaders(ctx Context, config Config) {
+	ctx.BeginTrace("clean", "clean copy headers")
+	defer ctx.EndTrace()
+
+	data, err := ioutil.ReadFile(filepath.Join(config.ProductOut(), ".copied_headers_list"))
+	if err != nil {
+		if os.IsNotExist(err) {
+			return
+		}
+		ctx.Fatalf("Failed to read copied headers list: %v", err)
+	}
+
+	headers := strings.Fields(string(data))
+	if len(headers) < 1 {
+		ctx.Fatal("Failed to parse copied headers list: %q", string(data))
+	}
+	headerDir := headers[0]
+	headers = headers[1:]
+
+	filepath.Walk(headerDir,
+		func(path string, info os.FileInfo, err error) error {
+			if err != nil {
+				return nil
+			}
+			if info.IsDir() {
+				return nil
+			}
+			if !inList(path, headers) {
+				ctx.Printf("Removing obsolete header %q", path)
+				if err := os.Remove(path); err != nil {
+					ctx.Fatalf("Failed to remove obsolete header %q: %v", path, err)
+				}
+			}
+			return nil
+		})
 }
 
 func runKatiPackage(ctx Context, config Config) {
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index f347a11..90ff706 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -119,9 +119,6 @@
 	"pgrep": LinuxOnlyPrebuilt,
 	"pkill": LinuxOnlyPrebuilt,
 	"ps":    LinuxOnlyPrebuilt,
-
-	// The toybox xargs is currently breaking the mac build.
-	"xargs": LinuxOnlyPrebuilt,
 }
 
 func init() {