Merge "Remove apex_available tag in cc_library_static generated from stubs-providing lib"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 63fe462..87554a2 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -212,7 +212,9 @@
 		"frameworks/proto_logging/stats":                     Bp2BuildDefaultTrueRecursively,
 
 		"hardware/interfaces":                          Bp2BuildDefaultTrue,
+		"hardware/interfaces/audio/aidl":               Bp2BuildDefaultTrue,
 		"hardware/interfaces/common/aidl":              Bp2BuildDefaultTrue,
+		"hardware/interfaces/common/fmq/aidl":          Bp2BuildDefaultTrue,
 		"hardware/interfaces/configstore/1.0":          Bp2BuildDefaultTrue,
 		"hardware/interfaces/configstore/1.1":          Bp2BuildDefaultTrue,
 		"hardware/interfaces/configstore/utils":        Bp2BuildDefaultTrue,
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index e9c97d0..40cc6a2 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -36,11 +36,6 @@
 )
 
 var (
-	writeBazelFile = pctx.AndroidStaticRule("bazelWriteFileRule", blueprint.RuleParams{
-		Command:        `sed "s/\\\\n/\n/g" ${out}.rsp >${out}`,
-		Rspfile:        "${out}.rsp",
-		RspfileContent: "${content}",
-	}, "content")
 	_                 = pctx.HostBinToolVariable("bazelBuildRunfilesTool", "build-runfiles")
 	buildRunfilesRule = pctx.AndroidStaticRule("bazelBuildRunfiles", blueprint.RuleParams{
 		Command:     "${bazelBuildRunfilesTool} ${in} ${outDir}",
@@ -210,6 +205,9 @@
 	bazelEnabledModules map[string]bool
 	// If true, modules are bazel-enabled by default, unless present in bazelDisabledModules.
 	modulesDefaultToBazel bool
+
+	targetProduct      string
+	targetBuildVariant string
 }
 
 var _ BazelContext = &bazelContext{}
@@ -437,16 +435,26 @@
 	vars := []struct {
 		name string
 		ptr  *string
+
+		// True if the environment variable needs to be tracked so that changes to the variable
+		// cause the ninja file to be regenerated, false otherwise. False should only be set for
+		// environment variables that have no effect on the generated ninja file.
+		track bool
 	}{
-		{"BAZEL_HOME", &paths.homeDir},
-		{"BAZEL_PATH", &paths.bazelPath},
-		{"BAZEL_OUTPUT_BASE", &paths.outputBase},
-		{"BAZEL_WORKSPACE", &paths.workspaceDir},
-		{"BAZEL_METRICS_DIR", &paths.metricsDir},
-		{"BAZEL_DEPS_FILE", &paths.bazelDepsFile},
+		{"BAZEL_HOME", &paths.homeDir, true},
+		{"BAZEL_PATH", &paths.bazelPath, true},
+		{"BAZEL_OUTPUT_BASE", &paths.outputBase, true},
+		{"BAZEL_WORKSPACE", &paths.workspaceDir, true},
+		{"BAZEL_METRICS_DIR", &paths.metricsDir, false},
+		{"BAZEL_DEPS_FILE", &paths.bazelDepsFile, true},
 	}
 	for _, v := range vars {
-		if s := c.Getenv(v.name); len(s) > 1 {
+		if v.track {
+			if s := c.Getenv(v.name); len(s) > 1 {
+				*v.ptr = s
+				continue
+			}
+		} else if s, ok := c.env[v.name]; ok {
 			*v.ptr = s
 		} else {
 			missing = append(missing, v.name)
@@ -455,6 +463,18 @@
 	if len(missing) > 0 {
 		return nil, fmt.Errorf("missing required env vars to use bazel: %s", missing)
 	}
+
+	targetBuildVariant := "user"
+	if c.Eng() {
+		targetBuildVariant = "eng"
+	} else if c.Debuggable() {
+		targetBuildVariant = "userdebug"
+	}
+	targetProduct := "unknown"
+	if c.HasDeviceProduct() {
+		targetProduct = c.DeviceProduct()
+	}
+
 	return &bazelContext{
 		bazelRunner:           &builtinBazelRunner{},
 		paths:                 &paths,
@@ -462,6 +482,8 @@
 		modulesDefaultToBazel: c.BuildMode == BazelDevMode,
 		bazelEnabledModules:   enabledModules,
 		bazelDisabledModules:  disabledModules,
+		targetProduct:         targetProduct,
+		targetBuildVariant:    targetBuildVariant,
 	}, nil
 }
 
@@ -558,9 +580,9 @@
 		// The actual platform values here may be overridden by configuration
 		// transitions from the buildroot.
 		fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"),
-		// This should be parameterized on the host OS, but let's restrict to linux
-		// to keep things simple for now.
-		fmt.Sprintf("--host_platform=%s", "//build/bazel/platforms:linux_x86_64"),
+
+		// We don't need to set --host_platforms because it's set in bazelrc files
+		// that the bazel shell script wrapper passes
 
 		// Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
 		"--experimental_repository_disable_download",
@@ -605,8 +627,12 @@
 #####################################################
 
 def _config_node_transition_impl(settings, attr):
+    if attr.os == "android" and attr.arch == "target":
+        target = "{PRODUCT}-{VARIANT}"
+    else:
+        target = "{PRODUCT}-{VARIANT}_%s_%s" % (attr.os, attr.arch)
     return {
-        "//command_line_option:platforms": "@//build/bazel/platforms:%s_%s" % (attr.os, attr.arch),
+        "//command_line_option:platforms": "@soong_injection//product_config_platforms/products/{PRODUCT}-{VARIANT}:%s" % target,
     }
 
 _config_node_transition = transition(
@@ -653,7 +679,12 @@
     attrs = {"deps" : attr.label_list()},
 )
 `
-	return []byte(contents)
+
+	productReplacer := strings.NewReplacer(
+		"{PRODUCT}", context.targetProduct,
+		"{VARIANT}", context.targetBuildVariant)
+
+	return []byte(productReplacer.Replace(contents))
 }
 
 func (context *bazelContext) mainBuildFileContents() []byte {
@@ -775,26 +806,24 @@
     t = type(p)
     if t == "string" or t == "int":
       return repr(p)
-    fail("unsupported value '%%s' of type '%%s'" %% (p, type(p)))
+    fail("unsupported value '%s' of type '%s'" % (p, type(p)))
 
   def encode_list(list):
-    return "[%%s]" %% ", ".join([encode_primitive(item) for item in list])
+    return "[%s]" % ", ".join([encode_primitive(item) for item in list])
 
   def encode_list_or_primitive(v):
     return encode_list(v) if type(v) == "list" else encode_primitive(v)
 
   if type(input) == "dict":
     # TODO(juu): the result is read line by line so can't use '\n' yet
-    kv_pairs = [("%%s: %%s" %% (encode_primitive(k), encode_list_or_primitive(v))) for (k, v) in input.items()]
-    return "{ %%s }" %% ", ".join(kv_pairs)
+    kv_pairs = [("%s: %s" % (encode_primitive(k), encode_list_or_primitive(v))) for (k, v) in input.items()]
+    return "{ %s }" % ", ".join(kv_pairs)
   else:
     return encode_list_or_primitive(input)
 
-# Label Map Section
-%s
+{LABEL_REGISTRATION_MAP_SECTION}
 
-# Function Def Section
-%s
+{FUNCTION_DEF_SECTION}
 
 def get_arch(target):
   # TODO(b/199363072): filegroups and file targets aren't associated with any
@@ -806,22 +835,26 @@
     # File targets do not have buildoptions. File targets aren't associated with
     #  any specific platform architecture in mixed builds, so use the host.
     return "x86_64|linux"
-  platforms = build_options(target)["//command_line_option:platforms"]
+  platforms = buildoptions["//command_line_option:platforms"]
   if len(platforms) != 1:
     # An individual configured target should have only one platform architecture.
     # Note that it's fine for there to be multiple architectures for the same label,
     # but each is its own configured target.
     fail("expected exactly 1 platform for " + str(target.label) + " but got " + str(platforms))
-  platform_name = build_options(target)["//command_line_option:platforms"][0].name
+  platform_name = platforms[0].name
   if platform_name == "host":
     return "HOST"
+  if not platform_name.startswith("{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}"):
+    fail("expected platform name of the form '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_android_<arch>' or '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
+  platform_name = platform_name.removeprefix("{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}").removeprefix("_")
+  if not platform_name:
+    return "target|android"
   elif platform_name.startswith("android_"):
-    return platform_name[len("android_"):] + "|" + platform_name[:len("android_")-1]
+    return platform_name.removeprefix("android_") + "|android"
   elif platform_name.startswith("linux_"):
-    return platform_name[len("linux_"):] + "|" + platform_name[:len("linux_")-1]
+    return platform_name.removeprefix("linux_") + "|linux"
   else:
-    fail("expected platform name of the form 'android_<arch>' or 'linux_<arch>', but was " + str(platforms))
-    return "UNKNOWN"
+    fail("expected platform name of the form '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_android_<arch>' or '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
 
 def format(target):
   id_string = str(target.label) + "|" + get_arch(target)
@@ -830,15 +863,20 @@
   if id_string.startswith("//"):
     id_string = "@" + id_string
 
-  # Main switch section
-  %s
+  {MAIN_SWITCH_SECTION}
+
   # This target was not requested via cquery, and thus must be a dependency
   # of a requested target.
   return id_string + ">>NONE"
 `
+	replacer := strings.NewReplacer(
+		"{TARGET_PRODUCT}", context.targetProduct,
+		"{TARGET_BUILD_VARIANT}", context.targetBuildVariant,
+		"{LABEL_REGISTRATION_MAP_SECTION}", labelRegistrationMapSection,
+		"{FUNCTION_DEF_SECTION}", functionDefSection,
+		"{MAIN_SWITCH_SECTION}", mainSwitchSection)
 
-	return []byte(fmt.Sprintf(formatString, labelRegistrationMapSection, functionDefSection,
-		mainSwitchSection))
+	return []byte(replacer.Replace(formatString))
 }
 
 // Returns a path containing build-related metadata required for interfacing
@@ -1089,19 +1127,8 @@
 		// because this would cause circular dependency. So, until we move aquery processing
 		// to the 'android' package, we need to handle special cases here.
 		if buildStatement.Mnemonic == "FileWrite" || buildStatement.Mnemonic == "SourceSymlinkManifest" {
-			// Pass file contents as the value of the rule's "content" argument.
-			// Escape newlines and $ in the contents (the action "writeBazelFile" restores "\\n"
-			// back to the newline, and Ninja reads $$ as $.
-			escaped := strings.ReplaceAll(strings.ReplaceAll(buildStatement.FileContents, "\n", "\\n"),
-				"$", "$$")
-			ctx.Build(pctx, BuildParams{
-				Rule:        writeBazelFile,
-				Output:      PathForBazelOut(ctx, buildStatement.OutputPaths[0]),
-				Description: fmt.Sprintf("%s %s", buildStatement.Mnemonic, buildStatement.OutputPaths[0]),
-				Args: map[string]string{
-					"content": escaped,
-				},
-			})
+			out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
+			WriteFileRuleVerbatim(ctx, out, buildStatement.FileContents)
 		} else if buildStatement.Mnemonic == "SymlinkTree" {
 			// build-runfiles arguments are the manifest file and the target directory
 			// where it creates the symlink tree according to this manifest (and then
diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go
index acebdbb..46f6488 100644
--- a/android/buildinfo_prop.go
+++ b/android/buildinfo_prop.go
@@ -61,11 +61,10 @@
 		return
 	}
 
-	rule := NewRuleBuilder(pctx, ctx)
-	cmd := rule.Command().Text("(")
+	lines := make([]string, 0)
 
 	writeString := func(str string) {
-		cmd.Text(`echo "` + str + `" && `)
+		lines = append(lines, str)
 	}
 
 	writeString("# begin build properties")
@@ -142,8 +141,7 @@
 
 	writeString("# end build properties")
 
-	cmd.Text("true) > ").Output(p.outputFilePath)
-	rule.Build("build.prop", "generating build.prop")
+	WriteFileRule(ctx, p.outputFilePath, strings.Join(lines, "\n"))
 
 	if !p.installable() {
 		p.SkipInstall()
diff --git a/android/config.go b/android/config.go
index 4ebb00f..d5ed883 100644
--- a/android/config.go
+++ b/android/config.go
@@ -769,6 +769,13 @@
 	return *c.productVariables.DeviceProduct
 }
 
+// HasDeviceProduct returns if the build has a product. A build will not
+// necessarily have a product when --skip-config is passed to soong, like it is
+// in prebuilts/build-tools/build-prebuilts.sh
+func (c *config) HasDeviceProduct() bool {
+	return c.productVariables.DeviceProduct != nil
+}
+
 func (c *config) DeviceResourceOverlays() []string {
 	return c.productVariables.DeviceResourceOverlays
 }
diff --git a/android/defs.go b/android/defs.go
index 9ae360e..6e5bb05 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -174,10 +174,15 @@
 // WriteFileRule creates a ninja rule to write contents to a file.  The contents will be escaped
 // so that the file contains exactly the contents passed to the function, plus a trailing newline.
 func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
+	WriteFileRuleVerbatim(ctx, outputFile, content+"\n")
+}
+
+// WriteFileRuleVerbatim creates a ninja rule to write contents to a file.  The contents will be
+// escaped so that the file contains exactly the contents passed to the function.
+func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
 	// This is MAX_ARG_STRLEN subtracted with some safety to account for shell escapes
 	const SHARD_SIZE = 131072 - 10000
 
-	content += "\n"
 	if len(content) > SHARD_SIZE {
 		var chunks WritablePaths
 		for i, c := range ShardString(content, SHARD_SIZE) {
diff --git a/android/license.go b/android/license.go
index ab8431a..a09422b 100644
--- a/android/license.go
+++ b/android/license.go
@@ -58,7 +58,6 @@
 type licenseModule struct {
 	ModuleBase
 	DefaultableModuleBase
-	SdkBase
 	BazelModuleBase
 
 	properties licenseProperties
@@ -137,7 +136,6 @@
 	// The visibility property needs to be checked and parsed by the visibility module.
 	setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
 
-	InitSdkAwareModule(module)
 	initAndroidModuleBase(module)
 	InitDefaultableModule(module)
 	InitBazelModule(module)
diff --git a/android/paths.go b/android/paths.go
index a6a54fa..0fc39df 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1033,9 +1033,6 @@
 // SourcePath is a Path representing a file path rooted from SrcDir
 type SourcePath struct {
 	basePath
-
-	// The sources root, i.e. Config.SrcDir()
-	srcDir string
 }
 
 func (p SourcePath) RelativeToTop() Path {
@@ -1054,7 +1051,7 @@
 // code that is embedding ninja variables in paths
 func safePathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error) {
 	p, err := validateSafePath(pathComponents...)
-	ret := SourcePath{basePath{p, ""}, "."}
+	ret := SourcePath{basePath{p, ""}}
 	if err != nil {
 		return ret, err
 	}
@@ -1071,7 +1068,7 @@
 // pathForSource creates a SourcePath from pathComponents, but does not check that it exists.
 func pathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error) {
 	p, err := validatePath(pathComponents...)
-	ret := SourcePath{basePath{p, ""}, "."}
+	ret := SourcePath{basePath{p, ""}}
 	if err != nil {
 		return ret, err
 	}
@@ -1174,7 +1171,10 @@
 }
 
 func (p SourcePath) String() string {
-	return filepath.Join(p.srcDir, p.path)
+	if p.path == "" {
+		return "."
+	}
+	return p.path
 }
 
 // Join creates a new SourcePath with paths... joined with the current path. The
@@ -1207,7 +1207,7 @@
 		// No need to put the error message into the returned path since it has been reported already.
 		return OptionalPath{}
 	}
-	dir := filepath.Join(p.srcDir, p.path, relDir)
+	dir := filepath.Join(p.path, relDir)
 	// Use Glob so that we are run again if the directory is added.
 	if pathtools.IsGlob(dir) {
 		ReportPathErrorf(ctx, "Path may not contain a glob: %s", dir)
@@ -1220,8 +1220,7 @@
 	if len(paths) == 0 {
 		return InvalidOptionalPath(dir + " does not exist")
 	}
-	relPath := Rel(ctx, p.srcDir, paths[0])
-	return OptionalPathForPath(PathForSource(ctx, relPath))
+	return OptionalPathForPath(PathForSource(ctx, paths[0]))
 }
 
 // OutputPath is a Path representing an intermediates file path rooted from the build directory
diff --git a/android/sdk.go b/android/sdk.go
index bd2f5d1..8b23d63 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -23,57 +23,6 @@
 	"github.com/google/blueprint/proptools"
 )
 
-// sdkAwareWithoutModule is provided simply to improve code navigation with the IDE.
-type sdkAwareWithoutModule interface {
-	// SdkMemberComponentName will return the name to use for a component of this module based on the
-	// base name of this module.
-	//
-	// The baseName is the name returned by ModuleBase.BaseModuleName(), i.e. the name specified in
-	// the name property in the .bp file so will not include the prebuilt_ prefix.
-	//
-	// The componentNameCreator is a func for creating the name of a component from the base name of
-	// the module, e.g. it could just append ".component" to the name passed in.
-	//
-	// This is intended to be called by prebuilt modules that create component models. It is because
-	// prebuilt module base names come in a variety of different forms:
-	// * unversioned - this is the same as the source module.
-	// * internal to an sdk - this is the unversioned name prefixed by the base name of the sdk
-	//   module.
-	// * versioned - this is the same as the internal with the addition of an "@<version>" suffix.
-	//
-	// While this can be called from a source module in that case it will behave the same way as the
-	// unversioned name and return the result of calling the componentNameCreator func on the supplied
-	// base name.
-	//
-	// e.g. Assuming the componentNameCreator func simply appends ".component" to the name passed in
-	// then this will work as follows:
-	// * An unversioned name of "foo" will return "foo.component".
-	// * An internal to the sdk name of "sdk_foo" will return "sdk_foo.component".
-	// * A versioned name of "sdk_foo@current" will return "sdk_foo.component@current".
-	//
-	// Note that in the latter case the ".component" suffix is added before the version. Adding it
-	// after would change the version.
-	SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string
-
-	sdkBase() *SdkBase
-	MakeMemberOf(sdk SdkRef)
-	IsInAnySdk() bool
-
-	// IsVersioned determines whether the module is versioned, i.e. has a name of the form
-	// <name>@<version>
-	IsVersioned() bool
-
-	ContainingSdk() SdkRef
-	MemberName() string
-}
-
-// SdkAware is the interface that must be supported by any module to become a member of SDK or to be
-// built with SDK
-type SdkAware interface {
-	Module
-	sdkAwareWithoutModule
-}
-
 // minApiLevelForSdkSnapshot provides access to the min_sdk_version for MinApiLevelForSdkSnapshot
 type minApiLevelForSdkSnapshot interface {
 	MinSdkVersion(ctx EarlyModuleContext) SdkSpec
@@ -94,138 +43,6 @@
 	return minApiLevel
 }
 
-// SdkRef refers to a version of an SDK
-type SdkRef struct {
-	Name    string
-	Version string
-}
-
-// Unversioned determines if the SdkRef is referencing to the unversioned SDK module
-func (s SdkRef) Unversioned() bool {
-	return s.Version == ""
-}
-
-// String returns string representation of this SdkRef for debugging purpose
-func (s SdkRef) String() string {
-	if s.Name == "" {
-		return "(No Sdk)"
-	}
-	if s.Unversioned() {
-		return s.Name
-	}
-	return s.Name + string(SdkVersionSeparator) + s.Version
-}
-
-// SdkVersionSeparator is a character used to separate an sdk name and its version
-const SdkVersionSeparator = '@'
-
-// ParseSdkRef parses a `name@version` style string into a corresponding SdkRef struct
-func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {
-	tokens := strings.Split(str, string(SdkVersionSeparator))
-	if len(tokens) < 1 || len(tokens) > 2 {
-		ctx.PropertyErrorf(property, "%q does not follow name@version syntax", str)
-		return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"}
-	}
-
-	name := tokens[0]
-
-	var version string
-	if len(tokens) == 2 {
-		version = tokens[1]
-	}
-
-	return SdkRef{Name: name, Version: version}
-}
-
-type SdkRefs []SdkRef
-
-// Contains tells if the given SdkRef is in this list of SdkRef's
-func (refs SdkRefs) Contains(s SdkRef) bool {
-	for _, r := range refs {
-		if r == s {
-			return true
-		}
-	}
-	return false
-}
-
-type sdkProperties struct {
-	// The SDK that this module is a member of. nil if it is not a member of any SDK
-	ContainingSdk *SdkRef `blueprint:"mutated"`
-
-	// Name of the module that this sdk member is representing
-	Sdk_member_name *string
-}
-
-// SdkBase is a struct that is expected to be included in module types to implement the SdkAware
-// interface. InitSdkAwareModule should be called to initialize this struct.
-type SdkBase struct {
-	properties sdkProperties
-	module     SdkAware
-}
-
-func (s *SdkBase) sdkBase() *SdkBase {
-	return s
-}
-
-func (s *SdkBase) SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string {
-	if s.MemberName() == "" {
-		return componentNameCreator(baseName)
-	} else {
-		index := strings.LastIndex(baseName, "@")
-		unversionedName := baseName[:index]
-		unversionedComponentName := componentNameCreator(unversionedName)
-		versionSuffix := baseName[index:]
-		return unversionedComponentName + versionSuffix
-	}
-}
-
-// MakeMemberOf sets this module to be a member of a specific SDK
-func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
-	s.properties.ContainingSdk = &sdk
-}
-
-// IsInAnySdk returns true if this module is a member of any SDK
-func (s *SdkBase) IsInAnySdk() bool {
-	return s.properties.ContainingSdk != nil
-}
-
-// IsVersioned returns true if this module is versioned.
-func (s *SdkBase) IsVersioned() bool {
-	return strings.Contains(s.module.Name(), "@")
-}
-
-// ContainingSdk returns the SDK that this module is a member of
-func (s *SdkBase) ContainingSdk() SdkRef {
-	if s.properties.ContainingSdk != nil {
-		return *s.properties.ContainingSdk
-	}
-	return SdkRef{Name: "", Version: ""}
-}
-
-// MemberName returns the name of the module that this SDK member is overriding
-func (s *SdkBase) MemberName() string {
-	return proptools.String(s.properties.Sdk_member_name)
-}
-
-// InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including
-// SdkBase.
-func InitSdkAwareModule(m SdkAware) {
-	base := m.sdkBase()
-	base.module = m
-	m.AddProperties(&base.properties)
-}
-
-// IsModuleInVersionedSdk returns true if the module is an versioned sdk.
-func IsModuleInVersionedSdk(module Module) bool {
-	if s, ok := module.(SdkAware); ok {
-		if !s.ContainingSdk().Unversioned() {
-			return true
-		}
-	}
-	return false
-}
-
 // SnapshotBuilder provides support for generating the build rules which will build the snapshot.
 type SnapshotBuilder interface {
 	// CopyToSnapshot generates a rule that will copy the src to the dest (which is a snapshot
@@ -593,7 +410,7 @@
 	Name() string
 
 	// Variants returns all the variants of this module depended upon by the SDK.
-	Variants() []SdkAware
+	Variants() []Module
 }
 
 // SdkMemberDependencyTag is the interface that a tag must implement in order to allow the
@@ -725,7 +542,7 @@
 	// The sdk module code generates the snapshot as follows:
 	//
 	// * A properties struct of type SdkMemberProperties is created for each variant and
-	//   populated with information from the variant by calling PopulateFromVariant(SdkAware)
+	//   populated with information from the variant by calling PopulateFromVariant(Module)
 	//   on the struct.
 	//
 	// * An additional properties struct is created into which the common properties will be
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index c1e92b8..9f5440d 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -20,7 +20,9 @@
 import (
 	"fmt"
 	"path/filepath"
+	"reflect"
 	"strings"
+	"sync"
 	"text/scanner"
 
 	"github.com/google/blueprint"
@@ -31,12 +33,18 @@
 )
 
 func init() {
-	RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory)
-	RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
-	RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
-	RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
+	RegisterSoongConfigModuleBuildComponents(InitRegistrationContext)
 }
 
+func RegisterSoongConfigModuleBuildComponents(ctx RegistrationContext) {
+	ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory)
+	ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
+	ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
+	ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
+}
+
+var PrepareForTestWithSoongConfigModuleBuildComponents = FixtureRegisterWithContext(RegisterSoongConfigModuleBuildComponents)
+
 type soongConfigModuleTypeImport struct {
 	ModuleBase
 	properties soongConfigModuleTypeImportProperties
@@ -416,13 +424,43 @@
 // configModuleFactory takes an existing soongConfigModuleFactory and a
 // ModuleType to create a new ModuleFactory that uses a custom loadhook.
 func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfig.ModuleType, bp2build bool) blueprint.ModuleFactory {
-	conditionalFactoryProps := soongconfig.CreateProperties(factory, moduleType)
-	if !conditionalFactoryProps.IsValid() {
-		return factory
+	// Defer creation of conditional properties struct until the first call from the factory
+	// method. That avoids having to make a special call to the factory to create the properties
+	// structs from which the conditional properties struct is created. This is needed in order to
+	// allow singleton modules to be customized by soong_config_module_type as the
+	// SingletonModuleFactoryAdaptor factory registers a load hook for the singleton module
+	// everytime that it is called. Calling the factory twice causes a build failure as the load
+	// hook is called twice, the first time it updates the singleton module to indicate that it has
+	// been registered as a module, and the second time it fails because it thinks it has been
+	// registered again and a singleton module can only be registered once.
+	//
+	// This is an issue for singleton modules because:
+	// * Load hooks are registered on the module object and are only called when the module object
+	//   is created by Blueprint while processing the Android.bp file.
+	// * The module factory for a singleton module returns the same module object each time it is
+	//   called, and registers its load hook on that same module object.
+	// * When the module factory is called by Blueprint it then calls all the load hooks that have
+	//   been registered for every call to that module factory.
+	//
+	// It is not an issue for normal modules because they return a new module object each time the
+	// factory is called and so any load hooks registered on module objects which are discarded will
+	// not be run.
+	once := &sync.Once{}
+	conditionalFactoryProps := reflect.Value{}
+	getConditionalFactoryProps := func(props []interface{}) reflect.Value {
+		once.Do(func() {
+			conditionalFactoryProps = soongconfig.CreateProperties(props, moduleType)
+		})
+		return conditionalFactoryProps
 	}
 
 	return func() (blueprint.Module, []interface{}) {
 		module, props := factory()
+		conditionalFactoryProps := getConditionalFactoryProps(props)
+		if !conditionalFactoryProps.IsValid() {
+			return module, props
+		}
+
 		conditionalProps := proptools.CloneEmptyProperties(conditionalFactoryProps)
 		props = append(props, conditionalProps.Interface())
 
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index ceb8e45..cab3e2d 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -15,12 +15,10 @@
 package android
 
 import (
+	"fmt"
 	"testing"
 )
 
-type soongConfigTestDefaultsModuleProperties struct {
-}
-
 type soongConfigTestDefaultsModule struct {
 	ModuleBase
 	DefaultsModuleBase
@@ -53,6 +51,11 @@
 
 func (t soongConfigTestModule) GenerateAndroidBuildActions(ModuleContext) {}
 
+var prepareForSoongConfigTestModule = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+	ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
+	ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
+})
+
 func TestSoongConfigModule(t *testing.T) {
 	configBp := `
 		soong_config_module_type {
@@ -309,14 +312,8 @@
 				result := GroupFixturePreparers(
 					tc.preparer,
 					PrepareForTestWithDefaults,
-					FixtureRegisterWithContext(func(ctx RegistrationContext) {
-						ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory)
-						ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
-						ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
-						ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
-						ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
-						ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
-					}),
+					PrepareForTestWithSoongConfigModuleBuildComponents,
+					prepareForSoongConfigTestModule,
 					fs.AddToFixture(),
 					FixtureWithRootAndroidBp(bp),
 				).RunTest(t)
@@ -371,14 +368,8 @@
 	GroupFixturePreparers(
 		fixtureForVendorVars(map[string]map[string]string{"acme": {"feature1": "1"}}),
 		PrepareForTestWithDefaults,
-		FixtureRegisterWithContext(func(ctx RegistrationContext) {
-			ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory)
-			ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
-			ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
-			ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
-			ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
-			ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
-		}),
+		PrepareForTestWithSoongConfigModuleBuildComponents,
+		prepareForSoongConfigTestModule,
 		FixtureWithRootAndroidBp(bp),
 	).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
 		// TODO(b/171232169): improve the error message for non-existent properties
@@ -411,14 +402,8 @@
 	GroupFixturePreparers(
 		fixtureForVendorVars(map[string]map[string]string{"acme": {"feature1": "1"}}),
 		PrepareForTestWithDefaults,
-		FixtureRegisterWithContext(func(ctx RegistrationContext) {
-			ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory)
-			ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
-			ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
-			ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
-			ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
-			ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
-		}),
+		PrepareForTestWithSoongConfigModuleBuildComponents,
+		prepareForSoongConfigTestModule,
 		FixtureWithRootAndroidBp(bp),
 	).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
 		// TODO(b/171232169): improve the error message for non-existent properties
@@ -426,10 +411,95 @@
 	})).RunTest(t)
 }
 
-func testConfigWithVendorVars(buildDir, bp string, fs map[string][]byte, vendorVars map[string]map[string]string) Config {
-	config := TestConfig(buildDir, nil, bp, fs)
+type soongConfigTestSingletonModule struct {
+	SingletonModuleBase
+	props soongConfigTestSingletonModuleProperties
+}
 
-	config.TestProductVariables.VendorVars = vendorVars
+type soongConfigTestSingletonModuleProperties struct {
+	Fragments []struct {
+		Apex   string
+		Module string
+	}
+}
 
-	return config
+func soongConfigTestSingletonModuleFactory() SingletonModule {
+	m := &soongConfigTestSingletonModule{}
+	m.AddProperties(&m.props)
+	InitAndroidModule(m)
+	return m
+}
+
+func (t *soongConfigTestSingletonModule) GenerateAndroidBuildActions(ModuleContext) {}
+
+func (t *soongConfigTestSingletonModule) GenerateSingletonBuildActions(SingletonContext) {}
+
+var prepareForSoongConfigTestSingletonModule = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+	ctx.RegisterSingletonModuleType("test_singleton", soongConfigTestSingletonModuleFactory)
+})
+
+func TestSoongConfigModuleSingletonModule(t *testing.T) {
+	bp := `
+		soong_config_module_type {
+			name: "acme_test_singleton",
+			module_type: "test_singleton",
+			config_namespace: "acme",
+			bool_variables: ["coyote"],
+			properties: ["fragments"],
+		}
+
+		acme_test_singleton {
+			name: "wiley",
+			fragments: [
+				{
+					apex: "com.android.acme",
+					module: "road-runner",
+				},
+			],
+			soong_config_variables: {
+				coyote: {
+					fragments: [
+						{
+							apex: "com.android.acme",
+							module: "wiley",
+						},
+					],
+				},
+			},
+		}
+	`
+
+	for _, test := range []struct {
+		coyote            bool
+		expectedFragments string
+	}{
+		{
+			coyote:            false,
+			expectedFragments: "[{Apex:com.android.acme Module:road-runner}]",
+		},
+		{
+			coyote:            true,
+			expectedFragments: "[{Apex:com.android.acme Module:road-runner} {Apex:com.android.acme Module:wiley}]",
+		},
+	} {
+		t.Run(fmt.Sprintf("coyote:%t", test.coyote), func(t *testing.T) {
+			result := GroupFixturePreparers(
+				PrepareForTestWithSoongConfigModuleBuildComponents,
+				prepareForSoongConfigTestSingletonModule,
+				FixtureWithRootAndroidBp(bp),
+				FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+					variables.VendorVars = map[string]map[string]string{
+						"acme": {
+							"coyote": fmt.Sprintf("%t", test.coyote),
+						},
+					}
+				}),
+			).RunTest(t)
+
+			// Make sure that the singleton was created.
+			result.SingletonForTests("test_singleton")
+			m := result.ModuleForTests("wiley", "").module.(*soongConfigTestSingletonModule)
+			AssertStringEquals(t, "fragments", test.expectedFragments, fmt.Sprintf("%+v", m.props.Fragments))
+		})
+	}
 }
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 1519f60..ed4888d 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -22,7 +22,6 @@
 	"strings"
 	"sync"
 
-	"github.com/google/blueprint"
 	"github.com/google/blueprint/parser"
 	"github.com/google/blueprint/proptools"
 
@@ -363,10 +362,9 @@
 //	        },
 //	    },
 //	}
-func CreateProperties(factory blueprint.ModuleFactory, moduleType *ModuleType) reflect.Value {
+func CreateProperties(factoryProps []interface{}, moduleType *ModuleType) reflect.Value {
 	var fields []reflect.StructField
 
-	_, factoryProps := factory()
 	affectablePropertiesType := createAffectablePropertiesType(moduleType.affectableProperties, factoryProps)
 	if affectablePropertiesType == nil {
 		return reflect.Value{}
diff --git a/apex/apex.go b/apex/apex.go
index a07576a..b9a3c8f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -396,7 +396,6 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 	android.OverridableModuleBase
-	android.SdkBase
 	android.BazelModuleBase
 	multitree.ExportableModuleBase
 
@@ -2640,7 +2639,6 @@
 
 	android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
-	android.InitSdkAwareModule(module)
 	android.InitOverridableModule(module, &module.overridableProperties.Overrides)
 	android.InitBazelModule(module)
 	multitree.InitExportableModule(module)
diff --git a/apex/builder.go b/apex/builder.go
index 82a523c..3b9cac0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -179,13 +179,6 @@
 		Description: "app bundle",
 	}, "abi", "config")
 
-	emitApexContentRule = pctx.StaticRule("emitApexContentRule", blueprint.RuleParams{
-		Command:        `rm -f ${out} && touch ${out} && (. ${out}.emit_commands)`,
-		Rspfile:        "${out}.emit_commands",
-		RspfileContent: "${emit_commands}",
-		Description:    "Emit APEX image content",
-	}, "emit_commands")
-
 	diffApexContentRule = pctx.StaticRule("diffApexContentRule", blueprint.RuleParams{
 		Command: `diff --unchanged-group-format='' \` +
 			`--changed-group-format='%<' \` +
@@ -546,29 +539,20 @@
 	// to be using this at this moment. Furthermore, this looks very similar to what
 	// buildInstalledFilesFile does. At least, move this to somewhere else so that this doesn't
 	// hurt readability.
-	// TODO(jiyong): use RuleBuilder
 	if a.overridableProperties.Allowed_files != nil {
 		// Build content.txt
-		var emitCommands []string
+		var contentLines []string
 		imageContentFile := android.PathForModuleOut(ctx, "content.txt")
-		emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String())
+		contentLines = append(contentLines, "./apex_manifest.pb")
 		minSdkVersion := a.minSdkVersion(ctx)
 		if minSdkVersion.EqualTo(android.SdkVersion_Android10) {
-			emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String())
+			contentLines = append(contentLines, "./apex_manifest.json")
 		}
 		for _, fi := range a.filesInfo {
-			emitCommands = append(emitCommands, "echo './"+fi.path()+"' >> "+imageContentFile.String())
+			contentLines = append(contentLines, "./"+fi.path())
 		}
-		emitCommands = append(emitCommands, "sort -o "+imageContentFile.String()+" "+imageContentFile.String())
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        emitApexContentRule,
-			Implicits:   implicitInputs,
-			Output:      imageContentFile,
-			Description: "emit apex image content",
-			Args: map[string]string{
-				"emit_commands": strings.Join(emitCommands, " && "),
-			},
-		})
+		sort.Strings(contentLines)
+		android.WriteFileRule(ctx, imageContentFile, strings.Join(contentLines, "\n"))
 		implicitInputs = append(implicitInputs, imageContentFile)
 
 		// Compare content.txt against allowed_files.
diff --git a/bazel/properties.go b/bazel/properties.go
index f9cabf2..76450dc 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -674,6 +674,11 @@
 	// specific select statements where an empty list for a non-default select
 	// key has a meaning.
 	EmitEmptyList bool
+
+	// If a property has struct tag "variant_prepend", this value should
+	// be set to True, so that when bp2build generates BUILD.bazel, variant
+	// properties(select ...) come before general properties.
+	Prepend bool
 }
 
 type configurableLabelLists map[ConfigurationAxis]labelListSelectValues
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 72d16fa..6edd78a 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -8,6 +8,7 @@
     srcs: [
         "androidbp_to_build_templates.go",
         "bp2build.go",
+        "bp2build_product_config.go",
         "build_conversion.go",
         "bzl_conversion.go",
         "configurability.go",
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index ff82694..df7cced 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -68,6 +68,7 @@
 					"exports":        `[":static_lib_dep"]`,
 					"javacopts":      `["-source 1.7 -target 1.7"]`,
 				}),
+			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
 }
 
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index a75a84e..5dc9612 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -45,7 +45,14 @@
 	bp2buildFiles := CreateBazelFiles(ctx.Config(), nil, res.buildFileToTargets, ctx.mode)
 	writeFiles(ctx, bp2buildDir, bp2buildFiles)
 
+	productConfigFiles, err := CreateProductConfigFiles(ctx)
+	if err != nil {
+		fmt.Printf("ERROR: %s", err.Error())
+		os.Exit(1)
+	}
+
 	soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName)
+	writeFiles(ctx, soongInjectionDir, productConfigFiles)
 	writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(ctx.Config(), res.metrics))
 
 	return &res.metrics
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
new file mode 100644
index 0000000..e343a05
--- /dev/null
+++ b/bp2build/bp2build_product_config.go
@@ -0,0 +1,124 @@
+package bp2build
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+func CreateProductConfigFiles(
+	ctx *CodegenContext) ([]BazelFile, error) {
+	cfg := &ctx.config
+	targetProduct := "unknown"
+	if cfg.HasDeviceProduct() {
+		targetProduct = cfg.DeviceProduct()
+	}
+	targetBuildVariant := "user"
+	if cfg.Eng() {
+		targetBuildVariant = "eng"
+	} else if cfg.Debuggable() {
+		targetBuildVariant = "userdebug"
+	}
+
+	productVariablesFileName := cfg.ProductVariablesFileName
+	if !strings.HasPrefix(productVariablesFileName, "/") {
+		productVariablesFileName = filepath.Join(ctx.topDir, productVariablesFileName)
+	}
+	bytes, err := os.ReadFile(productVariablesFileName)
+	if err != nil {
+		return nil, err
+	}
+
+	// TODO(b/249685973): the name is product_config_platforms because product_config
+	// was already used for other files. Deduplicate them.
+	currentProductFolder := fmt.Sprintf("product_config_platforms/products/%s-%s", targetProduct, targetBuildVariant)
+
+	productReplacer := strings.NewReplacer(
+		"{PRODUCT}", targetProduct,
+		"{VARIANT}", targetBuildVariant,
+		"{PRODUCT_FOLDER}", currentProductFolder)
+
+	result := []BazelFile{
+		newFile(
+			currentProductFolder,
+			"soong.variables.bzl",
+			`variables = json.decode("""`+strings.ReplaceAll(string(bytes), "\\", "\\\\")+`""")`),
+		newFile(
+			currentProductFolder,
+			"BUILD",
+			productReplacer.Replace(`
+package(default_visibility=[
+    "@soong_injection//product_config_platforms:__subpackages__",
+    "@//build/bazel/product_config:__subpackages__",
+])
+load(":soong.variables.bzl", _soong_variables = "variables")
+load("@//build/bazel/product_config:utils.bzl", "android_product")
+
+android_product(
+    name = "{PRODUCT}-{VARIANT}",
+    soong_variables = _soong_variables,
+)
+`)),
+		newFile(
+			"product_config_platforms",
+			"BUILD.bazel",
+			productReplacer.Replace(`
+package(default_visibility = [
+	"@//build/bazel/product_config:__subpackages__",
+	"@soong_injection//product_config_platforms:__subpackages__",
+])
+
+# TODO(b/249685973): Remove this. It was only added for a platform_mappings file,
+# which can possibly be replaced with autogenerating the platform_mappings file,
+# or removing that file entirely.
+alias(
+	name = "current_android_platform",
+	# TODO: When we start generating the platforms for more than just the
+	# currently lunched, product, turn this into a select with an arm for each product.
+	actual = "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}",
+)
+
+alias(
+	name = "product_vars",
+	actual = select({
+		# TODO: When we start generating the platforms for more than just the
+		# currently lunched, product, this select should have an arm for each product.
+		"@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_constraint_value": "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_product_vars",
+	}),
+)
+`)),
+		newFile(
+			"product_config_platforms",
+			"common.bazelrc",
+			productReplacer.Replace(`
+build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
+
+build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
+build:linux_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
+build:linux_bionic_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64
+`)),
+		newFile(
+			"product_config_platforms",
+			"linux.bazelrc",
+			productReplacer.Replace(`
+build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
+`)),
+		newFile(
+			"product_config_platforms",
+			"darwin.bazelrc",
+			productReplacer.Replace(`
+build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
+`)),
+		newFile(
+			"product_config_platforms",
+			"platform_mappings",
+			productReplacer.Replace(`
+flags:
+  --cpu=k8
+    @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
+`)),
+	}
+
+	return result, nil
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 5ab54e3..6c6631a 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -140,6 +140,7 @@
 	mode               CodegenMode
 	additionalDeps     []string
 	unconvertedDepMode unconvertedDepsMode
+	topDir             string
 }
 
 func (ctx *CodegenContext) Mode() CodegenMode {
@@ -208,7 +209,7 @@
 
 // NewCodegenContext creates a wrapper context that conforms to PathContext for
 // writing BUILD files in the output directory.
-func NewCodegenContext(config android.Config, context *android.Context, mode CodegenMode) *CodegenContext {
+func NewCodegenContext(config android.Config, context *android.Context, mode CodegenMode, topDir string) *CodegenContext {
 	var unconvertedDeps unconvertedDepsMode
 	if config.IsEnvTrue("BP2BUILD_ERROR_UNCONVERTED") {
 		unconvertedDeps = errorModulesUnconvertedDeps
@@ -218,6 +219,7 @@
 		config:             config,
 		mode:               mode,
 		unconvertedDepMode: unconvertedDeps,
+		topDir:             topDir,
 	}
 }
 
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 8433f52..d312169 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -209,7 +209,7 @@
 			_, errs = ctx.PrepareBuildActions(config)
 			android.FailIfErrored(t, errs)
 
-			codegenCtx := NewCodegenContext(config, ctx.Context, QueryView)
+			codegenCtx := NewCodegenContext(config, ctx.Context, QueryView, "")
 			bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
 			android.FailIfErrored(t, err)
 			if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
@@ -530,7 +530,7 @@
 				return
 			}
 
-			codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
+			codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 			bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
 			android.FailIfErrored(t, err)
 
@@ -903,7 +903,7 @@
 		_, errs = ctx.ResolveDependencies(config)
 		android.FailIfErrored(t, errs)
 
-		codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
+		codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 		bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
 		android.FailIfErrored(t, err)
 		if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
@@ -1156,7 +1156,7 @@
 			_, errs = ctx.ResolveDependencies(config)
 			android.FailIfErrored(t, errs)
 
-			codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
+			codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 			bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
 			android.FailIfErrored(t, err)
 			if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
@@ -1263,7 +1263,7 @@
 		_, errs = ctx.ResolveDependencies(config)
 		android.FailIfErrored(t, errs)
 
-		codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
+		codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 
 		// For each directory, test that the expected number of generated targets is correct.
 		for dir, expectedCount := range testCase.expectedCount {
@@ -1398,7 +1398,7 @@
 			if testCase.Dir != "" {
 				checkDir = testCase.Dir
 			}
-			codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
+			codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 			bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
 			android.FailIfErrored(t, err)
 			bazelTargets.sort()
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 32500a0..072f5b3 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -186,6 +186,8 @@
 	})
 }
 
+// header_libs has "variant_prepend" tag. In bp2build output,
+// variant info(select) should go before general info.
 func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
 		Description:                "cc_library_headers test with os-specific header_libs props",
@@ -247,14 +249,14 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
-				"deps": `[":base-lib"] + select({
+				"deps": `select({
         "//build/bazel/platforms/os:android": [":android-lib"],
         "//build/bazel/platforms/os:darwin": [":darwin-lib"],
         "//build/bazel/platforms/os:linux_bionic": [":linux_bionic-lib"],
         "//build/bazel/platforms/os:linux_glibc": [":linux-lib"],
         "//build/bazel/platforms/os:windows": [":windows-lib"],
         "//conditions:default": [],
-    })`,
+    }) + [":base-lib"]`,
 			}),
 		},
 	})
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 5a1260f..767f4ad 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1003,6 +1003,8 @@
 	})
 }
 
+// generated_headers has "variant_prepend" tag. In bp2build output,
+// variant info(select) should go before general info.
 func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
 		Description: "cc_library_static arch srcs/exclude_srcs with generated files",
@@ -1066,13 +1068,13 @@
         "//build/bazel/platforms/os:android": [":generated_src_android"],
         "//conditions:default": [],
     })`,
-				"hdrs": `["//dep:generated_hdr_other_pkg"] + select({
-        "//build/bazel/platforms/arch:x86": ["//dep:generated_hdr_other_pkg_x86"],
-        "//conditions:default": [],
-    }) + select({
+				"hdrs": `select({
         "//build/bazel/platforms/os:android": ["//dep:generated_hdr_other_pkg_android"],
         "//conditions:default": [],
-    })`,
+    }) + select({
+        "//build/bazel/platforms/arch:x86": ["//dep:generated_hdr_other_pkg_x86"],
+        "//conditions:default": [],
+    }) + ["//dep:generated_hdr_other_pkg"]`,
 				"local_includes":           `["."]`,
 				"export_absolute_includes": `["dep"]`,
 			}),
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index c630965..987c903 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -106,8 +106,9 @@
 
 	return value, []selects{ret}
 }
-func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects) {
+func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects, bool) {
 	value := reflect.ValueOf(list.Value.Includes)
+	prepend := list.Prepend
 	var ret []selects
 	for _, axis := range list.SortedConfigurationAxes() {
 		configToLabels := list.ConfigurableValues[axis]
@@ -133,7 +134,7 @@
 		}
 	}
 
-	return value, ret
+	return value, ret, prepend
 }
 
 func labelListSelectValue(selectKey string, list bazel.LabelList, emitEmptyList bool) (bool, reflect.Value) {
@@ -173,7 +174,7 @@
 		value, configurableAttrs, prepend = getStringListValues(list)
 		defaultSelectValue = &emptyBazelList
 	case bazel.LabelListAttribute:
-		value, configurableAttrs = getLabelListValues(list)
+		value, configurableAttrs, prepend = getLabelListValues(list)
 		emitZeroValues = list.EmitEmptyList
 		defaultSelectValue = &emptyBazelList
 		if list.ForceSpecifyEmptyList && (!value.IsNil() || list.HasConfigurableValues()) {
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index e37fa62..93a6174 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -585,6 +585,7 @@
 					"manifest":       `"manifest/AndroidManifest.xml"`,
 					"resource_files": `[]`,
 				}),
+			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
 }
 
@@ -628,6 +629,7 @@
 					"manifest":       `"manifest/AndroidManifest.xml"`,
 					"resource_files": `[]`,
 				}),
+			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
 }
 
@@ -665,6 +667,7 @@
 					"manifest":       `"manifest/AndroidManifest.xml"`,
 					"resource_files": `[]`,
 				}),
+			MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
 		}})
 }
 
@@ -685,6 +688,7 @@
         "c.kt",
     ]`,
 			}),
+			MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
 		},
 	})
 }
@@ -707,6 +711,7 @@
     ]`,
 				"common_srcs": `["c.kt"]`,
 			}),
+			MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
 		},
 	})
 }
diff --git a/bp2build/performance_test.go b/bp2build/performance_test.go
index 272ebf5..5f80b83 100644
--- a/bp2build/performance_test.go
+++ b/bp2build/performance_test.go
@@ -106,7 +106,7 @@
 	ctx := android.NewTestContext(config)
 
 	registerCustomModuleForBp2buildConversion(ctx)
-	codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
+	codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 	return testConfig{
 		config,
 		ctx,
diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
index 7029b93..dcd1f85 100644
--- a/bp2build/soong_config_module_type_conversion_test.go
+++ b/bp2build/soong_config_module_type_conversion_test.go
@@ -29,10 +29,7 @@
 func registerSoongConfigModuleTypes(ctx android.RegistrationContext) {
 	cc.RegisterCCBuildComponents(ctx)
 
-	ctx.RegisterModuleType("soong_config_module_type_import", android.SoongConfigModuleTypeImportFactory)
-	ctx.RegisterModuleType("soong_config_module_type", android.SoongConfigModuleTypeFactory)
-	ctx.RegisterModuleType("soong_config_string_variable", android.SoongConfigStringVariableDummyFactory)
-	ctx.RegisterModuleType("soong_config_bool_variable", android.SoongConfigBoolVariableDummyFactory)
+	android.RegisterSoongConfigModuleBuildComponents(ctx)
 
 	ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
 }
diff --git a/bp2build/testing.go b/bp2build/testing.go
index c059add..1f9874c 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -200,7 +200,7 @@
 		return
 	}
 
-	codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
+	codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
 	res, errs := GenerateBazelTargets(codegenCtx, false)
 	if bazelResult.CollateErrs(errs) {
 		return
diff --git a/cc/bp2build.go b/cc/bp2build.go
index a7ee5d1..d331d89 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -804,6 +804,12 @@
 		(&linkerAttrs).wholeArchiveDeps.Add(bp2buildCcSysprop(ctx, module.Name(), module.Properties.Min_sdk_version, compilerAttrs.syspropSrcs))
 	}
 
+	linkerAttrs.wholeArchiveDeps.Prepend = true
+	linkerAttrs.deps.Prepend = true
+	compilerAttrs.localIncludes.Prepend = true
+	compilerAttrs.absoluteIncludes.Prepend = true
+	compilerAttrs.hdrs.Prepend = true
+
 	features := compilerAttrs.features.Clone().Append(linkerAttrs.features).Append(bp2buildSanitizerFeatures(ctx, module))
 	features.DeduplicateAxesFromBase()
 
diff --git a/cc/cc.go b/cc/cc.go
index 1611b7d..cb425c3 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -818,7 +818,6 @@
 type Module struct {
 	fuzz.FuzzModule
 
-	android.SdkBase
 	android.BazelModuleBase
 
 	VendorProperties VendorProperties
@@ -1199,7 +1198,6 @@
 		android.InitBazelModule(c)
 	}
 	android.InitApexModule(c)
-	android.InitSdkAwareModule(c)
 	android.InitDefaultableModule(c)
 
 	return c
@@ -3539,7 +3537,7 @@
 	if lib := c.library; lib != nil {
 		// Stub libs and prebuilt libs in a versioned SDK are not
 		// installable to APEX even though they are shared libs.
-		return lib.shared() && !lib.buildStubs() && c.ContainingSdk().Unversioned()
+		return lib.shared() && !lib.buildStubs()
 	} else if _, ok := c.linker.(testPerSrc); ok {
 		return true
 	}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 3da7651..7113d87 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -209,12 +209,6 @@
 		return false
 	}
 
-	// Discard versioned members of SDK snapshots, because they will conflict with
-	// unversioned ones.
-	if sdkMember, ok := dependency.(android.SdkAware); ok && !sdkMember.ContainingSdk().Unversioned() {
-		return false
-	}
-
 	return true
 }
 
diff --git a/cc/library.go b/cc/library.go
index e8e9acf..787de44 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -85,10 +85,19 @@
 	// set suffix of the name of the output
 	Suffix *string `android:"arch_variant"`
 
+	// Properties for ABI compatibility checker.
+	Header_abi_checker headerAbiCheckerProperties
+
 	Target struct {
 		Vendor, Product struct {
 			// set suffix of the name of the output
 			Suffix *string `android:"arch_variant"`
+
+			Header_abi_checker headerAbiCheckerProperties
+		}
+
+		Platform struct {
+			Header_abi_checker headerAbiCheckerProperties
 		}
 	}
 
@@ -99,32 +108,6 @@
 	// from PRODUCT_PACKAGES.
 	Overrides []string
 
-	// Properties for ABI compatibility checker
-	Header_abi_checker struct {
-		// Enable ABI checks (even if this is not an LLNDK/VNDK lib)
-		Enabled *bool
-
-		// Path to a symbol file that specifies the symbols to be included in the generated
-		// ABI dump file
-		Symbol_file *string `android:"path"`
-
-		// Symbol versions that should be ignored from the symbol file
-		Exclude_symbol_versions []string
-
-		// Symbol tags that should be ignored from the symbol file
-		Exclude_symbol_tags []string
-
-		// Run checks on all APIs (in addition to the ones referred by
-		// one of exported ELF symbols.)
-		Check_all_apis *bool
-
-		// Extra flags passed to header-abi-diff
-		Diff_flags []string
-
-		// Opt-in reference dump directories
-		Ref_dump_dirs []string
-	}
-
 	// Inject boringssl hash into the shared library.  This is only intended for use by external/boringssl.
 	Inject_bssl_hash *bool `android:"arch_variant"`
 
@@ -1208,12 +1191,20 @@
 	return flags
 }
 
-func (library *libraryDecorator) headerAbiCheckerEnabled() bool {
-	return Bool(library.Properties.Header_abi_checker.Enabled)
-}
-
-func (library *libraryDecorator) headerAbiCheckerExplicitlyDisabled() bool {
-	return !BoolDefault(library.Properties.Header_abi_checker.Enabled, true)
+func (library *libraryDecorator) getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties {
+	m := ctx.Module().(*Module)
+	variantProps := &library.Properties.Target.Platform.Header_abi_checker
+	if m.InVendor() {
+		variantProps = &library.Properties.Target.Vendor.Header_abi_checker
+	} else if m.InProduct() {
+		variantProps = &library.Properties.Target.Product.Header_abi_checker
+	}
+	props := library.Properties.Header_abi_checker
+	err := proptools.AppendProperties(&props, variantProps, nil)
+	if err != nil {
+		ctx.ModuleErrorf("Cannot merge headerAbiCheckerProperties: %s", err.Error())
+	}
+	return props
 }
 
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
@@ -1348,9 +1339,8 @@
 	setStatic()
 	setShared()
 
-	// Check whether header_abi_checker is enabled or explicitly disabled.
-	headerAbiCheckerEnabled() bool
-	headerAbiCheckerExplicitlyDisabled() bool
+	// Gets the ABI properties for vendor, product, or platform variant
+	getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties
 
 	// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
 	androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
@@ -1882,7 +1872,8 @@
 	sourceDump := library.sAbiOutputFile.Path()
 
 	extraFlags := []string{"-target-version", sourceVersion}
-	if Bool(library.Properties.Header_abi_checker.Check_all_apis) {
+	headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
+	if Bool(headerAbiChecker.Check_all_apis) {
 		extraFlags = append(extraFlags, "-check-all-apis")
 	} else {
 		extraFlags = append(extraFlags,
@@ -1895,7 +1886,7 @@
 	if allowExtensions {
 		extraFlags = append(extraFlags, "-allow-extensions")
 	}
-	extraFlags = append(extraFlags, library.Properties.Header_abi_checker.Diff_flags...)
+	extraFlags = append(extraFlags, headerAbiChecker.Diff_flags...)
 
 	library.sAbiDiff = append(
 		library.sAbiDiff,
@@ -1943,10 +1934,11 @@
 			SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
 		}
 		exportedHeaderFlags := strings.Join(SourceAbiFlags, " ")
+		headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
 		library.sAbiOutputFile = transformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
 			android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
-			library.Properties.Header_abi_checker.Exclude_symbol_versions,
-			library.Properties.Header_abi_checker.Exclude_symbol_tags)
+			headerAbiChecker.Exclude_symbol_versions,
+			headerAbiChecker.Exclude_symbol_tags)
 
 		addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
 
@@ -1977,7 +1969,7 @@
 				fileName, isLlndk || isNdk, ctx.IsVndkExt())
 		}
 		// Check against the opt-in reference dumps.
-		for i, optInDumpDir := range library.Properties.Header_abi_checker.Ref_dump_dirs {
+		for i, optInDumpDir := range headerAbiChecker.Ref_dump_dirs {
 			optInDumpDirPath := android.PathForModuleSrc(ctx, optInDumpDir)
 			// Ref_dump_dirs are not versioned.
 			// They do not contain subdir for binder bitness because 64-bit binder has been mandatory.
@@ -2336,8 +2328,8 @@
 }
 
 func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *string {
-	if library.Properties.Header_abi_checker.Symbol_file != nil {
-		return library.Properties.Header_abi_checker.Symbol_file
+	if props := library.getHeaderAbiCheckerProperties(ctx); props.Symbol_file != nil {
+		return props.Symbol_file
 	}
 	if ctx.Module().(*Module).IsLlndk() {
 		return library.Properties.Llndk.Symbol_file
@@ -2813,7 +2805,7 @@
 		return bazelCcHeaderAbiCheckerAttributes{}
 	}
 
-	abiChecker := lib.Properties.Header_abi_checker
+	abiChecker := lib.getHeaderAbiCheckerProperties(ctx)
 
 	abiCheckerAttrs := bazelCcHeaderAbiCheckerAttributes{
 		Abi_checker_enabled:                 abiChecker.Enabled,
diff --git a/cc/object.go b/cc/object.go
index c3a198d..6cb1a30 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -78,7 +78,7 @@
 	Static_libs []string `android:"arch_variant,variant_prepend"`
 
 	// list of shared library modules should only provide headers for this module.
-	Shared_libs []string `android:"arch_variant"`
+	Shared_libs []string `android:"arch_variant,variant_prepend"`
 
 	// list of modules that should only provide headers for this module.
 	Header_libs []string `android:"arch_variant,variant_prepend"`
@@ -178,6 +178,8 @@
 				deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Static_libs))
 				deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Shared_libs))
 				deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Header_libs))
+				// static_libs, shared_libs, and header_libs have variant_prepend tag
+				deps.Prepend = true
 			}
 		}
 	}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 45af303..af83278 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -293,8 +293,6 @@
 		android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcsProperty)
 	}
 
-	// Prebuilt libraries can be used in SDKs.
-	android.InitSdkAwareModule(module)
 	return module, library
 }
 
@@ -582,7 +580,6 @@
 	module.linker = prebuilt
 	module.AddProperties(&prebuilt.properties)
 	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
-	android.InitSdkAwareModule(module)
 	return module
 }
 
diff --git a/cc/sabi.go b/cc/sabi.go
index e62ca66..4cd776a 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -26,6 +26,40 @@
 	lsdumpPathsLock sync.Mutex
 )
 
+// Properties for ABI compatibility checker in Android.bp.
+type headerAbiCheckerProperties struct {
+	// Enable ABI checks (even if this is not an LLNDK/VNDK lib)
+	Enabled *bool
+
+	// Path to a symbol file that specifies the symbols to be included in the generated
+	// ABI dump file
+	Symbol_file *string `android:"path"`
+
+	// Symbol versions that should be ignored from the symbol file
+	Exclude_symbol_versions []string
+
+	// Symbol tags that should be ignored from the symbol file
+	Exclude_symbol_tags []string
+
+	// Run checks on all APIs (in addition to the ones referred by
+	// one of exported ELF symbols.)
+	Check_all_apis *bool
+
+	// Extra flags passed to header-abi-diff
+	Diff_flags []string
+
+	// Opt-in reference dump directories
+	Ref_dump_dirs []string
+}
+
+func (props *headerAbiCheckerProperties) enabled() bool {
+	return Bool(props.Enabled)
+}
+
+func (props *headerAbiCheckerProperties) explicitlyDisabled() bool {
+	return !BoolDefault(props.Enabled, true)
+}
+
 type SAbiProperties struct {
 	// Whether ABI dump should be created for this module.
 	// Set by `sabiDepsMutator` if this module is a shared library that needs ABI check, or a static
@@ -67,7 +101,8 @@
 // Returns an empty string if ABI check is disabled for this library.
 func classifySourceAbiDump(ctx android.BaseModuleContext) string {
 	m := ctx.Module().(*Module)
-	if m.library.headerAbiCheckerExplicitlyDisabled() {
+	headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx)
+	if headerAbiChecker.explicitlyDisabled() {
 		return ""
 	}
 	// Return NDK if the library is both NDK and LLNDK.
@@ -92,7 +127,16 @@
 			}
 		}
 	}
-	if m.library.headerAbiCheckerEnabled() || m.library.hasStubsVariants() {
+	if m.library.hasStubsVariants() && !m.InProduct() && !m.InVendor() {
+		return "PLATFORM"
+	}
+	if headerAbiChecker.enabled() {
+		if m.InProduct() {
+			return "PRODUCT"
+		}
+		if m.InVendor() {
+			return "VENDOR"
+		}
 		return "PLATFORM"
 	}
 	return ""
diff --git a/cc/test.go b/cc/test.go
index 2a4861c..16ef0ef 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -415,8 +415,16 @@
 	testInstallBase := getTestInstallBase(useVendor)
 	configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx))
 
-	test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
-		test.Properties.Test_config_template, test.testDecorator.InstallerProperties.Test_suites, configs, test.Properties.Auto_gen_config, testInstallBase)
+	test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:         test.Properties.Test_config,
+		TestConfigTemplateProp: test.Properties.Test_config_template,
+		TestSuites:             test.testDecorator.InstallerProperties.Test_suites,
+		Config:                 configs,
+		AutoGenConfig:          test.Properties.Auto_gen_config,
+		TestInstallBase:        testInstallBase,
+		DeviceTemplate:         "${NativeTestConfigTemplate}",
+		HostTemplate:           "${NativeHostTestConfigTemplate}",
+	})
 
 	test.extraTestConfigs = android.PathsForModuleSrc(ctx, test.Properties.Test_options.Extra_test_configs)
 
@@ -630,8 +638,15 @@
 	if Bool(benchmark.Properties.Require_root) {
 		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
 	}
-	benchmark.testConfig = tradefed.AutoGenNativeBenchmarkTestConfig(ctx, benchmark.Properties.Test_config,
-		benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites, configs, benchmark.Properties.Auto_gen_config)
+	benchmark.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:         benchmark.Properties.Test_config,
+		TestConfigTemplateProp: benchmark.Properties.Test_config_template,
+		TestSuites:             benchmark.Properties.Test_suites,
+		Config:                 configs,
+		AutoGenConfig:          benchmark.Properties.Auto_gen_config,
+		DeviceTemplate:         "${NativeBenchmarkTestConfigTemplate}",
+		HostTemplate:           "${NativeBenchmarkTestConfigTemplate}",
+	})
 
 	benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName())
 	benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 744a10c..baa7380 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -134,7 +134,7 @@
 func runQueryView(queryviewDir, queryviewMarker string, ctx *android.Context) {
 	ctx.EventHandler.Begin("queryview")
 	defer ctx.EventHandler.End("queryview")
-	codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.QueryView)
+	codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.QueryView, topDir)
 	err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir))
 	maybeQuit(err, "")
 	touch(shared.JoinPath(topDir, queryviewMarker))
@@ -169,7 +169,7 @@
 	ninjaDeps = append(ninjaDeps, writeBuildGlobsNinjaFile(ctx)...)
 
 	// Run codegen to generate BUILD files
-	codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.ApiBp2build)
+	codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.ApiBp2build, topDir)
 	absoluteApiBp2buildDir := shared.JoinPath(topDir, cmdlineArgs.BazelApiBp2buildDir)
 	err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir)
 	maybeQuit(err, "")
@@ -277,7 +277,7 @@
 	switch ctx.Config().BuildMode {
 	case android.GenerateModuleGraph:
 		stopBefore = bootstrap.StopBeforeWriteNinja
-	case android.GenerateQueryView | android.GenerateDocFile:
+	case android.GenerateQueryView, android.GenerateDocFile:
 		stopBefore = bootstrap.StopBeforePrepareBuildActions
 	default:
 		stopBefore = bootstrap.DoEverything
@@ -586,7 +586,7 @@
 
 		// Run the code-generation phase to convert BazelTargetModules to BUILD files
 		// and print conversion codegenMetrics to the user.
-		codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.Bp2Build)
+		codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.Bp2Build, topDir)
 		ctx.EventHandler.Do("codegen", func() {
 			codegenMetrics = bp2build.Codegen(codegenContext)
 		})
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 713ccbe..8c99988 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -58,7 +58,7 @@
 	stdio func() terminal.StdioInterface
 
 	// run the command
-	run func(ctx build.Context, config build.Config, args []string, logsDir string)
+	run func(ctx build.Context, config build.Config, args []string)
 }
 
 // list of supported commands (flags) supported by soong ui
@@ -91,6 +91,15 @@
 		config:      buildActionConfig,
 		stdio:       stdio,
 		run:         runMake,
+	}, {
+		flag:        "--upload-metrics-only",
+		description: "upload metrics without building anything",
+		config:      uploadOnlyConfig,
+		stdio:       stdio,
+		// Upload-only mode mostly skips to the metrics-uploading phase of soong_ui.
+		// However, this invocation marks the true "end of the build", and thus we
+		// need to update the total runtime of the build to include this upload step.
+		run: updateTotalRealTime,
 	},
 }
 
@@ -182,18 +191,49 @@
 	}}
 
 	config := c.config(buildCtx, args...)
+	config.SetLogsPrefix(c.logsPrefix)
+	logsDir := config.LogsDir()
+	buildStarted = config.BuildStartedTimeOrDefault(buildStarted)
 
+	buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
+	soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
+	rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
+	bp2buildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"bp2build_metrics.pb")
+	metricsFiles := []string{
+		buildErrorFile,           // build error strings
+		rbeMetricsFile,           // high level metrics related to remote build execution.
+		bp2buildMetricsFile,      // high level metrics related to bp2build.
+		soongMetricsFile,         // high level metrics related to this build system.
+		config.BazelMetricsDir(), // directory that contains a set of bazel metrics.
+	}
+
+	os.MkdirAll(logsDir, 0777)
+
+	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
+
+	trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
+
+	c.run(buildCtx, config, args)
+
+	defer met.Dump(soongMetricsFile)
+	if !config.SkipMetricsUpload() {
+		defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, metricsFiles...)
+	}
+
+}
+
+func logAndSymlinkSetup(buildCtx build.Context, config build.Config) {
+	log := buildCtx.ContextImpl.Logger
+	logsPrefix := config.GetLogsPrefix()
 	build.SetupOutDir(buildCtx, config)
-
-	// Set up files to be outputted in the log directory.
 	logsDir := config.LogsDir()
 
 	// Common list of metric file definition.
-	buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
-	rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
-	soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
-	bp2buildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"bp2build_metrics.pb")
-	soongBuildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_build_metrics.pb")
+	buildErrorFile := filepath.Join(logsDir, logsPrefix+"build_error")
+	rbeMetricsFile := filepath.Join(logsDir, logsPrefix+"rbe_metrics.pb")
+	soongMetricsFile := filepath.Join(logsDir, logsPrefix+"soong_metrics")
+	bp2buildMetricsFile := filepath.Join(logsDir, logsPrefix+"bp2build_metrics.pb")
+	soongBuildMetricsFile := filepath.Join(logsDir, logsPrefix+"soong_build_metrics.pb")
 
 	//Delete the stale metrics files
 	staleFileSlice := []string{buildErrorFile, rbeMetricsFile, soongMetricsFile, bp2buildMetricsFile, soongBuildMetricsFile}
@@ -203,14 +243,12 @@
 
 	build.PrintOutDirWarning(buildCtx, config)
 
-	os.MkdirAll(logsDir, 0777)
-	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
-	trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
-	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
-	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
+	stat := buildCtx.Status
+	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, logsPrefix+"verbose.log")))
+	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, logsPrefix+"error.log")))
 	stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
 	stat.AddOutput(status.NewCriticalPath(log))
-	stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
+	stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, logsPrefix+"build_progress.pb")))
 
 	buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
 	buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
@@ -218,27 +256,7 @@
 
 	setMaxFiles(buildCtx)
 
-	{
-		// The order of the function calls is important. The last defer function call
-		// is the first one that is executed to save the rbe metrics to a protobuf
-		// file. The soong metrics file is then next. Bazel profiles are written
-		// before the uploadMetrics is invoked. The written files are then uploaded
-		// if the uploading of the metrics is enabled.
-		files := []string{
-			buildErrorFile,           // build error strings
-			rbeMetricsFile,           // high level metrics related to remote build execution.
-			soongBuildMetricsFile,    // high level metrics related to soong build(except bp2build).
-			bp2buildMetricsFile,      // high level metrics related to bp2build.
-			soongMetricsFile,         // high level metrics related to this build system.
-			config.BazelMetricsDir(), // directory that contains a set of bazel metrics.
-		}
-
-		if !config.SkipMetricsUpload() {
-			defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, files...)
-		}
-		defer met.Dump(soongMetricsFile)
-		defer build.CheckProdCreds(buildCtx, config)
-	}
+	defer build.CheckProdCreds(buildCtx, config)
 
 	// Read the time at the starting point.
 	if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
@@ -253,7 +271,7 @@
 		}
 
 		if executable, err := os.Executable(); err == nil {
-			trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
+			buildCtx.ContextImpl.Tracer.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
 		}
 	}
 
@@ -266,8 +284,6 @@
 	f := build.NewSourceFinder(buildCtx, config)
 	defer f.Shutdown()
 	build.FindSources(buildCtx, config, f)
-
-	c.run(buildCtx, config, args, logsDir)
 }
 
 func fixBadDanglingLink(ctx build.Context, name string) {
@@ -284,7 +300,8 @@
 	}
 }
 
-func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
+func dumpVar(ctx build.Context, config build.Config, args []string) {
+	logAndSymlinkSetup(ctx, config)
 	flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
 	flags.SetOutput(ctx.Writer)
 
@@ -336,7 +353,9 @@
 	}
 }
 
-func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
+func dumpVars(ctx build.Context, config build.Config, args []string) {
+	logAndSymlinkSetup(ctx, config)
+
 	flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
 	flags.SetOutput(ctx.Writer)
 
@@ -421,6 +440,14 @@
 	return build.NewConfig(ctx)
 }
 
+// uploadOnlyConfig explicitly requires no arguments.
+func uploadOnlyConfig(ctx build.Context, args ...string) build.Config {
+	if len(args) > 0 {
+		fmt.Printf("--upload-only does not require arguments.")
+	}
+	return build.UploadOnlyConfig(ctx)
+}
+
 func buildActionConfig(ctx build.Context, args ...string) build.Config {
 	flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
 	flags.SetOutput(ctx.Writer)
@@ -514,7 +541,9 @@
 	return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
 }
 
-func runMake(ctx build.Context, config build.Config, _ []string, logsDir string) {
+func runMake(ctx build.Context, config build.Config, _ []string) {
+	logAndSymlinkSetup(ctx, config)
+	logsDir := config.LogsDir()
 	if config.IsVerbose() {
 		writer := ctx.Writer
 		fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
@@ -659,3 +688,19 @@
 		ctx.Println("Failed to increase file limit:", err)
 	}
 }
+
+func updateTotalRealTime(ctx build.Context, config build.Config, args []string) {
+	soongMetricsFile := filepath.Join(config.LogsDir(), "soong_metrics")
+
+	//read file into proto
+	data, err := os.ReadFile(soongMetricsFile)
+	if err != nil {
+		ctx.Fatal(err)
+	}
+	met := ctx.ContextImpl.Metrics
+
+	err = met.UpdateTotalRealTime(data)
+	if err != nil {
+		ctx.Fatal(err)
+	}
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index d01608f..c73c4a4 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -69,10 +69,11 @@
 	// TODO(jiyong): allow apex_key to be specified here
 	Avb_private_key *string `android:"path"`
 
-	// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
+	// Signing algorithm for avbtool. Default is SHA256_RSA4096.
 	Avb_algorithm *string
 
-	// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
+	// Hash algorithm used for avbtool (for descriptors). This is passed as hash_algorithm to
+	// avbtool. Default used by avbtool is sha1.
 	Avb_hash_algorithm *string
 
 	// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
diff --git a/java/aar.go b/java/aar.go
index ccd68cd..f4a2ff2 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1054,12 +1054,15 @@
 		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
 	}
 
+	name := a.Name()
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "android_library",
+		Bzl_load_location: "@rules_android//rules:rules.bzl",
+	}
+
 	ctx.CreateBazelTargetModule(
-		bazel.BazelTargetModuleProperties{
-			Rule_class:        "android_library",
-			Bzl_load_location: "@rules_android//rules:rules.bzl",
-		},
-		android.CommonAttributes{Name: a.Name()},
+		props,
+		android.CommonAttributes{Name: name},
 		&bazelAndroidLibrary{
 			&javaLibraryAttributes{
 				javaCommonAttributes: commonAttrs,
@@ -1069,4 +1072,16 @@
 			a.convertAaptAttrsWithBp2Build(ctx),
 		},
 	)
+
+	neverlink := true
+	ctx.CreateBazelTargetModule(
+		props,
+		android.CommonAttributes{Name: name + "-neverlink"},
+		&bazelAndroidLibrary{
+			javaLibraryAttributes: &javaLibraryAttributes{
+				Neverlink: bazel.BoolAttribute{Value: &neverlink},
+				Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+			},
+		},
+	)
 }
diff --git a/java/androidmk.go b/java/androidmk.go
index 42b4ef1..a4dac80 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -200,11 +200,6 @@
 		dexpreoptEntries := prebuilt.dexpreopter.AndroidMkEntriesForApex()
 		return append(dexpreoptEntries, android.AndroidMkEntries{Disabled: true})
 	}
-	if !prebuilt.ContainingSdk().Unversioned() {
-		return []android.AndroidMkEntries{android.AndroidMkEntries{
-			Disabled: true,
-		}}
-	}
 	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
diff --git a/java/app.go b/java/app.go
index df6698d..3c5760b 100755
--- a/java/app.go
+++ b/java/app.go
@@ -315,10 +315,6 @@
 		}
 	}
 
-	if Bool(a.appProperties.Enforce_default_target_sdk_version) {
-		a.SetEnforceDefaultTargetSdkVersion(true)
-	}
-
 	a.checkPlatformAPI(ctx)
 	a.checkSdkVersions(ctx)
 }
@@ -639,6 +635,11 @@
 		a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath)
 	}
 
+	// For apps targeting latest target_sdk_version
+	if Bool(a.appProperties.Enforce_default_target_sdk_version) {
+		a.SetEnforceDefaultTargetSdkVersion(true)
+	}
+
 	// Process all building blocks, from AAPT to certificates.
 	a.aaptBuildActions(ctx)
 
diff --git a/java/app_test.go b/java/app_test.go
index bc971e3..cd88864 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -3203,7 +3203,7 @@
 			updatable:                      true,
 		},
 		{
-			name:                           "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
+			name:                           "Enforce Target SDK Version: Android.bp has current targetSdkVersion",
 			enforceDefaultTargetSdkVersion: true,
 			platform_sdk_final:             false,
 			targetSdkVersionInBp:           "current",
@@ -3259,6 +3259,76 @@
 	}
 }
 
+func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) {
+	platform_sdk_codename := "Tiramisu"
+	platform_sdk_version := 33
+	testCases := []struct {
+		name                           string
+		enforceDefaultTargetSdkVersion bool
+		expectedError                  string
+		platform_sdk_final             bool
+		targetSdkVersionInBp           string
+		targetSdkVersionExpected       string
+	}{
+		{
+			name:                           "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion",
+			enforceDefaultTargetSdkVersion: false,
+			targetSdkVersionInBp:           "29",
+			targetSdkVersionExpected:       "29",
+		},
+		{
+			name:                           "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
+			enforceDefaultTargetSdkVersion: true,
+			platform_sdk_final:             true,
+			targetSdkVersionInBp:           "current",
+			targetSdkVersionExpected:       "33",
+		},
+		{
+			name:                           "Enforce Target SDK Version: Android.bp has current targetSdkVersion",
+			enforceDefaultTargetSdkVersion: true,
+			platform_sdk_final:             false,
+			targetSdkVersionInBp:           "current",
+			targetSdkVersionExpected:       "10000",
+		},
+	}
+	for _, testCase := range testCases {
+		errExpected := testCase.expectedError != ""
+		bp := fmt.Sprintf(`
+			android_test {
+				name: "foo",
+				enforce_default_target_sdk_version: %t,
+				min_sdk_version: "29",
+				target_sdk_version: "%v",
+			}
+		`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp)
+
+		fixture := android.GroupFixturePreparers(
+			PrepareForTestWithJavaDefaultModules,
+			android.PrepareForTestWithAllowMissingDependencies,
+			android.PrepareForTestWithAndroidMk,
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				// explicitly set following platform variables to make the test deterministic
+				variables.Platform_sdk_final = &testCase.platform_sdk_final
+				variables.Platform_sdk_version = &platform_sdk_version
+				variables.Platform_sdk_codename = &platform_sdk_codename
+				variables.Unbundled_build_apps = []string{"sampleModule"}
+			}),
+		)
+
+		errorHandler := android.FixtureExpectsNoErrors
+		if errExpected {
+			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
+		}
+		result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
+
+		if !errExpected {
+			foo := result.ModuleForTests("foo", "android_common")
+			manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+			android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion  "+testCase.targetSdkVersionExpected)
+		}
+	}
+}
+
 func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		PrepareForTestWithJavaDefaultModules,
diff --git a/java/base.go b/java/base.go
index 55d77dc..84fda37 100644
--- a/java/base.go
+++ b/java/base.go
@@ -395,7 +395,6 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 	android.ApexModuleBase
-	android.SdkBase
 	android.BazelModuleBase
 
 	// Functionality common to Module and Import.
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 3a28c59..101d3ca 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -229,7 +229,6 @@
 type BootclasspathFragmentModule struct {
 	android.ModuleBase
 	android.ApexModuleBase
-	android.SdkBase
 	ClasspathFragmentBase
 
 	// True if this fragment is for testing purposes.
@@ -279,7 +278,6 @@
 	m := &BootclasspathFragmentModule{}
 	m.AddProperties(&m.properties, &m.sourceOnlyProperties)
 	android.InitApexModule(m)
-	android.InitSdkAwareModule(m)
 	initClasspathFragment(m, BOOTCLASSPATH)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 
@@ -332,19 +330,6 @@
 		return
 	}
 
-	// TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property.
-	if android.IsModuleInVersionedSdk(m) {
-		// The module is a versioned prebuilt so ignore it. This is done for a couple of reasons:
-		// 1. There is no way to use this at the moment so ignoring it is safe.
-		// 2. Attempting to initialize the contents property from the configuration will end up having
-		//    the versioned prebuilt depending on the unversioned prebuilt. That will cause problems
-		//    as the unversioned prebuilt could end up with an APEX variant created for the source
-		//    APEX which will prevent it from having an APEX variant for the prebuilt APEX which in
-		//    turn will prevent it from accessing the dex implementation jar from that which will
-		//    break hidden API processing, amongst others.
-		return
-	}
-
 	// Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
 	// too early in the Soong processing for that to work.
 	global := dexpreopt.GetGlobalConfig(ctx)
@@ -383,19 +368,6 @@
 func (b *BootclasspathFragmentModule) bootclasspathImageNameContentsConsistencyCheck(ctx android.BaseModuleContext) {
 	imageName := proptools.String(b.properties.Image_name)
 	if imageName == "art" {
-		// TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property.
-		if android.IsModuleInVersionedSdk(b) {
-			// The module is a versioned prebuilt so ignore it. This is done for a couple of reasons:
-			// 1. There is no way to use this at the moment so ignoring it is safe.
-			// 2. Attempting to initialize the contents property from the configuration will end up having
-			//    the versioned prebuilt depending on the unversioned prebuilt. That will cause problems
-			//    as the unversioned prebuilt could end up with an APEX variant created for the source
-			//    APEX which will prevent it from having an APEX variant for the prebuilt APEX which in
-			//    turn will prevent it from accessing the dex implementation jar from that which will
-			//    break hidden API processing, amongst others.
-			return
-		}
-
 		// Get the configuration for the art apex jars.
 		modules := b.getImageConfig(ctx).modules
 		configuredJars := modules.CopyOfJars()
@@ -575,57 +547,48 @@
 	// prebuilt which will not use the image config.
 	imageConfig := b.getImageConfig(ctx)
 
-	// A versioned prebuilt_bootclasspath_fragment cannot and does not need to perform hidden API
-	// processing. It cannot do it because it is not part of a prebuilt_apex and so has no access to
-	// the correct dex implementation jar. It does not need to because the platform-bootclasspath
-	// always references the latest bootclasspath_fragments.
-	if !android.IsModuleInVersionedSdk(ctx.Module()) {
-		// Perform hidden API processing.
-		hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
+	// Perform hidden API processing.
+	hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
 
-		var bootImageFiles bootImageOutputs
-		if imageConfig != nil {
-			// Delegate the production of the boot image files to a module type specific method.
-			common := ctx.Module().(commonBootclasspathFragment)
-			bootImageFiles = common.produceBootImageFiles(ctx, imageConfig)
+	var bootImageFiles bootImageOutputs
+	if imageConfig != nil {
+		// Delegate the production of the boot image files to a module type specific method.
+		common := ctx.Module().(commonBootclasspathFragment)
+		bootImageFiles = common.produceBootImageFiles(ctx, imageConfig)
 
-			if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
-				// Zip the boot image files up, if available. This will generate the zip file in a
-				// predefined location.
-				buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch)
+		if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
+			// Zip the boot image files up, if available. This will generate the zip file in a
+			// predefined location.
+			buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch)
 
-				// Copy the dex jars of this fragment's content modules to their predefined locations.
-				copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
-			}
-
-			for _, variant := range bootImageFiles.variants {
-				archType := variant.config.target.Arch.ArchType
-				arch := archType.String()
-				for _, install := range variant.deviceInstalls {
-					// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
-					installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
-					installBase := filepath.Base(install.To)
-					installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
-
-					b.bootImageDeviceInstalls = append(b.bootImageDeviceInstalls, dexpreopterInstall{
-						name:                arch + "-" + installBase,
-						moduleName:          b.Name(),
-						outputPathOnHost:    install.From,
-						installDirOnDevice:  installPath,
-						installFileOnDevice: installBase,
-					})
-				}
-			}
+			// Copy the dex jars of this fragment's content modules to their predefined locations.
+			copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
 		}
 
-		// A prebuilt fragment cannot contribute to an apex.
-		if !android.IsModulePrebuilt(ctx.Module()) {
-			// Provide the apex content info.
-			b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles)
+		for _, variant := range bootImageFiles.variants {
+			archType := variant.config.target.Arch.ArchType
+			arch := archType.String()
+			for _, install := range variant.deviceInstalls {
+				// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
+				installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
+				installBase := filepath.Base(install.To)
+				installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
+
+				b.bootImageDeviceInstalls = append(b.bootImageDeviceInstalls, dexpreopterInstall{
+					name:                arch + "-" + installBase,
+					moduleName:          b.Name(),
+					outputPathOnHost:    install.From,
+					installDirOnDevice:  installPath,
+					installFileOnDevice: installBase,
+				})
+			}
 		}
-	} else {
-		// Versioned fragments are not needed by make.
-		b.HideFromMake()
+	}
+
+	// A prebuilt fragment cannot contribute to an apex.
+	if !android.IsModulePrebuilt(ctx.Module()) {
+		// Provide the apex content info.
+		b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles)
 	}
 
 	// In order for information about bootclasspath_fragment modules to be added to module-info.json
@@ -719,7 +682,7 @@
 		jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
 	} else if android.InList("test_framework-apexd", possibleUpdatableModules) {
 		jars = jars.Append("com.android.apex.test_package", "test_framework-apexd")
-	} else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
+	} else if global.ApexBootJars.Len() != 0 {
 		unknown = android.RemoveListFromList(unknown, b.properties.Coverage.Contents)
 		_, unknown = android.RemoveFromList("core-icu4j", unknown)
 		// This module only exists in car products.
@@ -961,11 +924,6 @@
 		return bootImageOutputs{}
 	}
 
-	// Bootclasspath fragment modules that are versioned do not produce a boot image.
-	if android.IsModuleInVersionedSdk(ctx.Module()) {
-		return bootImageOutputs{}
-	}
-
 	// Build a profile for the image config and then use that to build the boot image.
 	profile := bootImageProfileRule(ctx, imageConfig)
 
@@ -1393,7 +1351,6 @@
 	// array.
 	android.InitPrebuiltModule(m, &[]string{"placeholder"})
 	android.InitApexModule(m)
-	android.InitSdkAwareModule(m)
 	android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
 
 	// Initialize the contents property from the image_name.
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index bfd5cf8..4fb1d76 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -301,3 +301,76 @@
         "core-generated-annotation-stubs",
     ],
 }
+
+// Used when compiling higher-level code against art.module.public.api.stubs.
+// This abstraction should come from the inner tree linking against the stubs
+// and not from an "sdk", since parts of this abstraction do not belong to an
+// official API (e.g. stub-annotations).
+//
+// This is only intended for use within core libraries and must not be used
+// from outside.
+java_system_modules {
+    name: "art-module-public-api-stubs-system-modules",
+    visibility: [
+        "//art/build/sdk",
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
+        "//external/wycheproof",
+    ],
+    libs: [
+        "art.module.public.api.stubs",
+        // This one is not on device but it's needed when javac compiles code
+        // containing lambdas.
+        "core-lambda-stubs-for-system-modules",
+        // This one is not on device but it's needed when javac compiles code
+        // containing @Generated annotations produced by some code generation
+        // tools.
+        // See http://b/123891440.
+        "core-generated-annotation-stubs",
+
+        // Ensure that core libraries that depend on the public API can access
+        // the UnsupportedAppUsage, CorePlatformApi and IntraCoreApi
+        // annotations.
+        "art.module.api.annotations.for.system.modules",
+
+        // Make nullability annotations available when compiling public stubs.
+        // They are provided as a separate library because while the
+        // annotations are not themselves part of the public API provided by
+        // this module they are used in the stubs.
+        "stub-annotations",
+    ],
+}
+
+// Used when compiling higher-level code against art.module.public.api.stubs.module_lib.
+//
+// This is only intended for use within core libraries and must not be used
+// from outside.
+java_system_modules {
+    name: "art-module-lib-api-stubs-system-modules",
+    visibility: [
+        "//art/build/sdk",
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
+    ],
+    libs: [
+        "art.module.public.api.stubs.module_lib",
+    ],
+}
+
+// Used when compiling against art.module.intra.core.api.stubs.
+java_system_modules {
+    name: "art-module-intra-core-api-stubs-system-modules",
+    visibility: [
+        "//art/build/sdk",
+        "//external/bouncycastle",
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
+    ],
+    libs: [
+        // The intra core API stubs library.
+        "art.module.intra.core.api.stubs",
+
+        // Additional classes needed by javac but which are not present in the stubs.
+        "art-module-intra-core-api-stubs-system-modules-lib",
+    ],
+}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 2ad2969..066f0d6 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -48,7 +48,6 @@
 // Droidstubs
 type Droidstubs struct {
 	Javadoc
-	android.SdkBase
 
 	properties              DroidstubsProperties
 	apiFile                 android.Path
@@ -179,7 +178,6 @@
 		&module.Javadoc.properties)
 
 	InitDroiddocModule(module, android.HostAndDeviceSupported)
-	android.InitSdkAwareModule(module)
 	return module
 }
 
@@ -927,7 +925,6 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 	prebuilt android.Prebuilt
-	android.SdkBase
 
 	properties PrebuiltStubsSourcesProperties
 
@@ -1007,7 +1004,6 @@
 	module.AddProperties(&module.properties)
 
 	android.InitPrebuiltModule(module, &module.properties.Srcs)
-	android.InitSdkAwareModule(module)
 	InitDroiddocModule(module, android.HostAndDeviceSupported)
 	return module
 }
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 5474ae1..593d772 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -1352,14 +1352,6 @@
 		return true
 	}
 
-	// A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
-	// is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
-	// versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
-	// failures missing boot dex jars need to be deferred.
-	if android.IsModuleInVersionedSdk(ctx.Module()) {
-		return true
-	}
-
 	// This is called for both platform_bootclasspath and bootclasspath_fragment modules.
 	//
 	// A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
diff --git a/java/java.go b/java/java.go
index 275abbe..3b0ad8d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -876,7 +876,6 @@
 	module.initModuleAndImport(module)
 
 	android.InitApexModule(module)
-	android.InitSdkAwareModule(module)
 	android.InitBazelModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 	return module
@@ -899,7 +898,6 @@
 	module.Module.properties.Installable = proptools.BoolPtr(true)
 
 	android.InitApexModule(module)
-	android.InitSdkAwareModule(module)
 	android.InitBazelModule(module)
 	InitJavaModule(module, android.HostSupported)
 	return module
@@ -915,6 +913,10 @@
 
 	// a list of extra test configuration files that should be installed with the module.
 	Extra_test_configs []string `android:"path,arch_variant"`
+
+	// Extra <option> tags to add to the auto generated test xml file. The "key"
+	// is optional in each of these.
+	Tradefed_options []tradefed.Option
 }
 
 type testProperties struct {
@@ -1192,9 +1194,18 @@
 		defaultUnitTest := !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
 		j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
 	}
-
-	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
-		j.testProperties.Test_suites, configs, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
+	j.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:          j.testProperties.Test_config,
+		TestConfigTemplateProp:  j.testProperties.Test_config_template,
+		TestSuites:              j.testProperties.Test_suites,
+		Config:                  configs,
+		OptionsForAutogenerated: j.testProperties.Test_options.Tradefed_options,
+		AutoGenConfig:           j.testProperties.Auto_gen_config,
+		UnitTest:                j.testProperties.Test_options.Unit_test,
+		DeviceTemplate:          "${JavaTestConfigTemplate}",
+		HostTemplate:            "${JavaHostTestConfigTemplate}",
+		HostUnitTestTemplate:    "${JavaHostUnitTestConfigTemplate}",
+	})
 
 	j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
 
@@ -1239,8 +1250,13 @@
 }
 
 func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
-		j.prebuiltTestProperties.Test_suites, nil, nil, nil)
+	j.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:       j.prebuiltTestProperties.Test_config,
+		TestSuites:           j.prebuiltTestProperties.Test_suites,
+		DeviceTemplate:       "${JavaTestConfigTemplate}",
+		HostTemplate:         "${JavaHostTestConfigTemplate}",
+		HostUnitTestTemplate: "${JavaHostUnitTestConfigTemplate}",
+	})
 
 	j.Import.GenerateAndroidBuildActions(ctx)
 }
@@ -1322,7 +1338,6 @@
 	module.Module.dexpreopter.isTest = true
 	module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
 
-	android.InitSdkAwareModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 	return module
 }
@@ -1361,7 +1376,6 @@
 
 	android.InitPrebuiltModule(module, &module.properties.Jars)
 	android.InitApexModule(module)
-	android.InitSdkAwareModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 	return module
 }
@@ -1784,7 +1798,6 @@
 	android.ApexModuleBase
 	android.BazelModuleBase
 	prebuilt android.Prebuilt
-	android.SdkBase
 
 	// Functionality common to Module and Import.
 	embeddableInModuleAndImport
@@ -2158,7 +2171,6 @@
 
 	android.InitPrebuiltModule(module, &module.properties.Jars)
 	android.InitApexModule(module)
-	android.InitSdkAwareModule(module)
 	android.InitBazelModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 	return module
@@ -2663,7 +2675,7 @@
 	if m.properties.Libs != nil {
 
 		// TODO 244210934 ALIX Check if this else statement breaks presubmits get rid of it if it doesn't
-		if strings.HasPrefix(ctx.ModuleType(), "java_binary") || strings.HasPrefix(ctx.ModuleType(), "java_library") {
+		if strings.HasPrefix(ctx.ModuleType(), "java_binary") || strings.HasPrefix(ctx.ModuleType(), "java_library") || ctx.ModuleType() == "android_library" {
 			for _, d := range m.properties.Libs {
 				neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d)
 				neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink"
@@ -2738,14 +2750,6 @@
 			Rule_class:        "java_library",
 			Bzl_load_location: "//build/bazel/rules/java:library.bzl",
 		}
-
-		ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
-		neverlinkProp := true
-		neverLinkAttrs := &javaLibraryAttributes{
-			Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
-			Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
-		}
-		ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs)
 	} else {
 		attrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs))
 
@@ -2753,10 +2757,16 @@
 			Rule_class:        "kt_jvm_library",
 			Bzl_load_location: "@rules_kotlin//kotlin:jvm_library.bzl",
 		}
-		// TODO (b/244210934): create neverlink-duplicate target once kt_jvm_library supports neverlink attribute
-		ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
 	}
 
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+	neverlinkProp := true
+	neverLinkAttrs := &javaLibraryAttributes{
+		Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+		Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
+	}
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs)
+
 }
 
 type javaBinaryHostAttributes struct {
diff --git a/java/java_test.go b/java/java_test.go
index dff1fd0..085f627 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1945,3 +1945,27 @@
 		}
 	}
 }
+
+func TestTradefedOptions(t *testing.T) {
+	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
+java_test_host {
+	name: "foo",
+	test_options: {
+		tradefed_options: [
+			{
+				name: "exclude-path",
+				value: "org/apache"
+			}
+		]
+	}
+}
+`)
+
+	buildOS := result.Config.BuildOS.String()
+	args := result.ModuleForTests("foo", buildOS+"_common").
+		Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args
+	expected := proptools.NinjaAndShellEscape("<option name=\"exclude-path\" value=\"org/apache\" />")
+	if args["extraConfigs"] != expected {
+		t.Errorf("Expected args[\"extraConfigs\"] to equal %q, was %q", expected, args["extraConfigs"])
+	}
+}
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 519a702..061f4d0 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -1,5 +1,10 @@
 # Treat LintError as fatal to catch invocation errors
 --fatal_check LintError
+# ObsoleteLintCustomCheck is a warning by default, but lint ignores the
+# checks from the subject jar if this issue is raised.
+# This should be an error for AOSP. If we create a check, we expect it
+# to run, otherwise we want an error.
+--fatal_check ObsoleteLintCustomCheck
 
 # Checks which do not apply to the platform (implementation
 # in lint assumes that it's running on app code)
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 655021f..d417291 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -15,12 +15,11 @@
 package java
 
 import (
+	"fmt"
 	"path/filepath"
 
 	"android/soong/android"
 	"github.com/google/blueprint"
-
-	"fmt"
 )
 
 func init() {
@@ -55,7 +54,6 @@
 
 type platformCompatConfig struct {
 	android.ModuleBase
-	android.SdkBase
 
 	properties     platformCompatConfigProperties
 	installDirPath android.InstallPath
@@ -127,7 +125,6 @@
 func PlatformCompatConfigFactory() android.Module {
 	module := &platformCompatConfig{}
 	module.AddProperties(&module.properties)
-	android.InitSdkAwareModule(module)
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	return module
 }
@@ -178,7 +175,6 @@
 // A prebuilt version of the platform compat config module.
 type prebuiltCompatConfigModule struct {
 	android.ModuleBase
-	android.SdkBase
 	prebuilt android.Prebuilt
 
 	properties prebuiltCompatConfigProperties
@@ -213,7 +209,6 @@
 	m := &prebuiltCompatConfigModule{}
 	m.AddProperties(&m.properties)
 	android.InitSingleSourcePrebuiltModule(m, &m.properties, "Metadata")
-	android.InitSdkAwareModule(m)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
 }
@@ -223,18 +218,6 @@
 	metadata android.Path
 }
 
-// isModulePreferredByCompatConfig checks to see whether the module is preferred for use by
-// platform compat config.
-func isModulePreferredByCompatConfig(module android.Module) bool {
-	// A versioned prebuilt_platform_compat_config, i.e. foo-platform-compat-config@current should be
-	// ignored.
-	if android.IsModuleInVersionedSdk(module) {
-		return false
-	}
-
-	return android.IsModulePreferred(module)
-}
-
 func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 
 	var compatConfigMetadata android.Paths
@@ -244,7 +227,7 @@
 			return
 		}
 		if c, ok := module.(platformCompatConfigMetadataProvider); ok {
-			if !isModulePreferredByCompatConfig(module) {
+			if !android.IsModulePreferred(module) {
 				return
 			}
 			metadata := c.compatConfigMetadata()
diff --git a/java/robolectric.go b/java/robolectric.go
index 6e8d591..68f27b8 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -131,9 +131,14 @@
 	r.forceOSType = ctx.Config().BuildOS
 	r.forceArchType = ctx.Config().BuildArch
 
-	r.testConfig = tradefed.AutoGenRobolectricTestConfig(ctx, r.testProperties.Test_config,
-		r.testProperties.Test_config_template, r.testProperties.Test_suites,
-		r.testProperties.Auto_gen_config)
+	r.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:         r.testProperties.Test_config,
+		TestConfigTemplateProp: r.testProperties.Test_config_template,
+		TestSuites:             r.testProperties.Test_suites,
+		AutoGenConfig:          r.testProperties.Auto_gen_config,
+		DeviceTemplate:         "${RobolectricTestConfigTemplate}",
+		HostTemplate:           "${RobolectricTestConfigTemplate}",
+	})
 	r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data)
 
 	roboTestConfig := android.PathForModuleGen(ctx, "robolectric").
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 56e5550..3b64bf7 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -752,7 +752,7 @@
 // commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
 // embeds the commonToSdkLibraryAndImport struct.
 type commonSdkLibraryAndImportModule interface {
-	android.SdkAware
+	android.Module
 
 	BaseModuleName() string
 }
@@ -831,18 +831,14 @@
 // Name of the java_library module that compiles the stubs source.
 func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
 	baseName := c.module.BaseModuleName()
-	return c.module.SdkMemberComponentName(baseName, func(name string) string {
-		return c.namingScheme.stubsLibraryModuleName(apiScope, name)
-	})
+	return c.namingScheme.stubsLibraryModuleName(apiScope, baseName)
 }
 
 // Name of the droidstubs module that generates the stubs source and may also
 // generate/check the API.
 func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
 	baseName := c.module.BaseModuleName()
-	return c.module.SdkMemberComponentName(baseName, func(name string) string {
-		return c.namingScheme.stubsSourceModuleName(apiScope, name)
-	})
+	return c.namingScheme.stubsSourceModuleName(apiScope, baseName)
 }
 
 // The component names for different outputs of the java_sdk_library.
@@ -2052,7 +2048,6 @@
 
 	module.InitSdkLibraryProperties()
 	android.InitApexModule(module)
-	android.InitSdkAwareModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 
 	// Initialize the map from scope to scope specific properties.
@@ -2130,7 +2125,6 @@
 	android.DefaultableModuleBase
 	prebuilt android.Prebuilt
 	android.ApexModuleBase
-	android.SdkBase
 
 	hiddenAPI
 	dexpreopter
@@ -2212,7 +2206,6 @@
 
 	android.InitPrebuiltModule(module, &[]string{""})
 	android.InitApexModule(module)
-	android.InitSdkAwareModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 
 	module.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
diff --git a/java/system_modules.go b/java/system_modules.go
index fec8eba..0efa1a4 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -114,7 +114,6 @@
 	module.AddProperties(&module.properties)
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
-	android.InitSdkAwareModule(module)
 	return module
 }
 
@@ -130,7 +129,6 @@
 type SystemModules struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
-	android.SdkBase
 
 	properties SystemModulesProperties
 
@@ -215,7 +213,6 @@
 	android.InitPrebuiltModule(module, &module.properties.Libs)
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
-	android.InitSdkAwareModule(module)
 	return module
 }
 
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index a2cd261..17d301b 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -83,7 +83,6 @@
 type SystemServerClasspathModule struct {
 	android.ModuleBase
 	android.ApexModuleBase
-	android.SdkBase
 
 	ClasspathFragmentBase
 
@@ -113,7 +112,6 @@
 	m := &SystemServerClasspathModule{}
 	m.AddProperties(&m.properties)
 	android.InitApexModule(m)
-	android.InitSdkAwareModule(m)
 	initClasspathFragment(m, SYSTEMSERVERCLASSPATH)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
@@ -160,7 +158,7 @@
 	// This is an exception to support end-to-end test for ApexdUnitTests, until such support exists.
 	if android.InList("test_service-apexd", possibleUpdatableModules) {
 		jars = jars.Append("com.android.apex.test_package", "test_service-apexd")
-	} else if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
+	} else if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 {
 		// For non test apexes, make sure that all contents are actually declared in make.
 		ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_SYSTEM_SERVER_JARS", unknown)
 	}
@@ -331,7 +329,6 @@
 	// array.
 	android.InitPrebuiltModule(m, &[]string{"placeholder"})
 	android.InitApexModule(m)
-	android.InitSdkAwareModule(m)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
 }
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 705eac3..77394d9 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -1872,6 +1872,18 @@
 	if len(nodes) == 0 {
 		return []starlarkNode{}
 	} else if len(nodes) == 1 {
+		// Replace the nodeLocator with one that just returns the location of
+		// the $(eval) node. Otherwise, statements inside an $(eval) will show as
+		// being on line 1 of the file, because they're on line 1 of
+		// strings.NewReader(args.Dump())
+		oldNodeLocator := ctx.script.nodeLocator
+		ctx.script.nodeLocator = func(pos mkparser.Pos) int {
+			return oldNodeLocator(node.Pos())
+		}
+		defer func() {
+			ctx.script.nodeLocator = oldNodeLocator
+		}()
+
 		switch n := nodes[0].(type) {
 		case *mkparser.Assignment:
 			if n.Name.Const() {
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 65a3be7..7e68026 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -1567,6 +1567,9 @@
 
 $(foreach x,$(MY_LIST_VAR), \
   $(eval include foo/$(x).mk))
+
+# Check that we get as least close to correct line numbers for errors on statements inside evals
+$(eval $(call inherit-product,$(A_VAR)))
 `,
 		expected: `load("//build/make/core:product_config.rbc", "rblf")
 load("//foo:font.star", _font_init = "init")
@@ -1592,6 +1595,8 @@
     if not _varmod_init:
       rblf.mkerror("product.mk", "Cannot find %s" % ("foo/%s.mk" % x))
     _varmod_init(g, handle)
+  # Check that we get as least close to correct line numbers for errors on statements inside evals
+  rblf.mk2rbc_error("product.mk:17", "inherit-product/include argument is too complex")
 `,
 	},
 	{
diff --git a/python/test.go b/python/test.go
index b9b3465..fc5c211 100644
--- a/python/test.go
+++ b/python/test.go
@@ -67,9 +67,14 @@
 }
 
 func (test *testDecorator) install(ctx android.ModuleContext, file android.Path) {
-	test.testConfig = tradefed.AutoGenPythonBinaryHostTestConfig(ctx, test.testProperties.Test_config,
-		test.testProperties.Test_config_template, test.binaryDecorator.binaryProperties.Test_suites,
-		test.binaryDecorator.binaryProperties.Auto_gen_config)
+	test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:         test.testProperties.Test_config,
+		TestConfigTemplateProp: test.testProperties.Test_config_template,
+		TestSuites:             test.binaryDecorator.binaryProperties.Test_suites,
+		AutoGenConfig:          test.binaryDecorator.binaryProperties.Auto_gen_config,
+		DeviceTemplate:         "${PythonBinaryHostTestConfigTemplate}",
+		HostTemplate:           "${PythonBinaryHostTestConfigTemplate}",
+	})
 
 	test.binaryDecorator.pythonInstaller.dir = "nativetest"
 	test.binaryDecorator.pythonInstaller.dir64 = "nativetest64"
diff --git a/rust/benchmark.go b/rust/benchmark.go
index 0e84243..c0f1e24 100644
--- a/rust/benchmark.go
+++ b/rust/benchmark.go
@@ -112,12 +112,14 @@
 }
 
 func (benchmark *benchmarkDecorator) install(ctx ModuleContext) {
-	benchmark.testConfig = tradefed.AutoGenRustBenchmarkConfig(ctx,
-		benchmark.Properties.Test_config,
-		benchmark.Properties.Test_config_template,
-		benchmark.Properties.Test_suites,
-		nil,
-		benchmark.Properties.Auto_gen_config)
+	benchmark.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:         benchmark.Properties.Test_config,
+		TestConfigTemplateProp: benchmark.Properties.Test_config_template,
+		TestSuites:             benchmark.Properties.Test_suites,
+		AutoGenConfig:          benchmark.Properties.Auto_gen_config,
+		DeviceTemplate:         "${RustDeviceBenchmarkConfigTemplate}",
+		HostTemplate:           "${RustHostBenchmarkConfigTemplate}",
+	})
 
 	// default relative install path is module name
 	if !Bool(benchmark.Properties.No_named_install_directory) {
diff --git a/rust/test.go b/rust/test.go
index 0cc3bca..4f922b4 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -130,13 +130,16 @@
 		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
 	}
 
-	test.testConfig = tradefed.AutoGenRustTestConfig(ctx,
-		test.Properties.Test_config,
-		test.Properties.Test_config_template,
-		test.Properties.Test_suites,
-		configs,
-		test.Properties.Auto_gen_config,
-		testInstallBase)
+	test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:         test.Properties.Test_config,
+		TestConfigTemplateProp: test.Properties.Test_config_template,
+		TestSuites:             test.Properties.Test_suites,
+		Config:                 configs,
+		AutoGenConfig:          test.Properties.Auto_gen_config,
+		TestInstallBase:        testInstallBase,
+		DeviceTemplate:         "${RustDeviceTestConfigTemplate}",
+		HostTemplate:           "${RustHostTestConfigTemplate}",
+	})
 
 	dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
 
diff --git a/scripts/run-ckati.sh b/scripts/run-ckati.sh
new file mode 100755
index 0000000..b670c8a
--- /dev/null
+++ b/scripts/run-ckati.sh
@@ -0,0 +1,91 @@
+#! /bin/bash -eu
+
+# Run CKati step separately, tracing given Makefile variables.
+# It is expected that the regular Android null build (`m nothing`)
+# has been run so that $OUT_DIR/soong/Android-${TARGET_PRODUCT}.mk,
+# $OUT_DIR/soong/make_vars-${TARGET_PRODUCT}.mk, etc. files exist.
+#
+# The output file is in JSON format and can be processed with, say,
+# `jq`. For instance, the following invocation outputs all assignment
+# traces concisely:
+#  jq -c  '.assignments[] | (select (.operation == "assign")) | {("n"): .name, ("l"): .value_stack[0]?, ("v"): .value }' out/ckati.trace
+# generates
+#  {"n":"<var1>","l":"<file>:<line>","v":"<value1>"}
+#  ...
+
+function die() { format=$1; shift; printf "$format\n" $@; exit 1; }
+function usage() { die "Usage: %s [-o FILE] VAR ...\n(without -o the output goes to ${outfile})"  ${0##*/}; }
+
+[[ -d build/soong ]] || die "run this script from the top of the Android source tree"
+declare -r out=${OUT_DIR:-out}
+[[ -x ${out}/soong_ui ]] || die "run Android build first"
+: ${TARGET_PRODUCT:?not set, run lunch?}
+: ${TARGET_BUILD_VARIANT:?not set, run lunch?}
+declare -r androidmk=${out}/soong/Android-${TARGET_PRODUCT}.mk
+declare -r makevarsmk=${out}/soong/make_vars-${TARGET_PRODUCT}.mk
+declare -r target_device_dir=$(${out}/soong_ui --dumpvar-mode TARGET_DEVICE_DIR)
+: ${target_device_dir:?cannot find device directory for ${TARGET_PRODUCT}}
+declare -r target_device=$(${out}/soong_ui --dumpvar-mode TARGET_DEVICE)
+: ${target_device:?cannot find target device for ${TARGET_PRODUCT}}
+declare -r timestamp_file=${out}/build_date.txt
+# Files should exist, so ls should succeed:
+ls -1d "$androidmk" "$makevarsmk" "$target_device_dir" "$timestamp_file" >/dev/null
+
+outfile=${out}/ckati.trace
+while getopts "ho:" opt; do
+  case $opt in
+    h) usage ;;
+    o) outfile=$OPTARG ;;
+    ?) usage ;;
+  esac
+done
+
+if (($#>0)); then
+  declare -a tracing=(--variable_assignment_trace_filter="$*" --dump_variable_assignment_trace "$outfile")
+else
+  printf "running ckati without tracing variables\n"
+fi
+
+# Touch one input for ckati, otherwise it will just print
+# 'No need to regenerate ninja file' and exit.
+touch "$androidmk"
+prebuilts/build-tools/linux-x86/bin/ckati \
+  --gen_all_targets \
+  -i \
+  --ignore_optional_include=out/%.P \
+  --ninja \
+  --ninja_dir=out \
+  --ninja_suffix=-${TARGET_PRODUCT} \
+  --no_builtin_rules \
+  --no_ninja_prelude \
+  --regen \
+  --top_level_phony \
+  --use_find_emulator \
+  --use_ninja_phony_output \
+  --use_ninja_symlink_outputs \
+  --werror_find_emulator \
+  --werror_implicit_rules \
+  --werror_overriding_commands \
+  --werror_phony_looks_real \
+  --werror_real_to_phony \
+  --werror_suffix_rules \
+  --werror_writable \
+  --writable out/ \
+  -f build/make/core/main.mk \
+  "${tracing[@]}" \
+  ANDROID_JAVA_HOME=prebuilts/jdk/jdk17/linux-x86 \
+  ASAN_SYMBOLIZER_PATH=$PWD/prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-symbolizer \
+  BUILD_DATETIME_FILE="$timestamp_file" \
+  BUILD_HOSTNAME=$(hostname) \
+  BUILD_USERNAME="$USER" \
+  JAVA_HOME=$PWD/prebuilts/jdk/jdk17/linux-x86 \
+  KATI_PACKAGE_MK_DIR="{$out}/target/product/${target_device}/CONFIG/kati_packaging" \
+  OUT_DIR="$out" \
+  PATH="$PWD/prebuilts/build-tools/path/linux-x86:$PWD/${out}/.path" \
+  PYTHONDONTWRITEBYTECODE=1 \
+  SOONG_ANDROID_MK="$androidmk" \
+  SOONG_MAKEVARS_MK="$makevarsmk" \
+  TARGET_BUILD_VARIANT="$TARGET_BUILD_VARIANT" \
+  TARGET_DEVICE_DIR="$target_device_dir" \
+  TARGET_PRODUCT=${TARGET_PRODUCT} \
+  TMPDIR="$PWD/$out/soong/.temp"
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 92ecd5e..d81635e 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -664,7 +664,15 @@
 	android.GroupFixturePreparers(
 		prepareForSdkTestWithApex,
 		prepareForSdkTestWithJava,
-		android.FixtureAddFile("java/mybootlib.jar", nil),
+		android.FixtureMergeMockFs(android.MockFS{
+			"java/mybootlib.jar":                nil,
+			"hiddenapi/annotation-flags.csv":    nil,
+			"hiddenapi/index.csv":               nil,
+			"hiddenapi/metadata.csv":            nil,
+			"hiddenapi/signature-patterns.csv":  nil,
+			"hiddenapi/filtered-stub-flags.csv": nil,
+			"hiddenapi/filtered-flags.csv":      nil,
+		}),
 		android.FixtureWithRootAndroidBp(`
 		sdk {
 			name: "mysdk",
@@ -691,26 +699,27 @@
 			compile_dex: true,
 		}
 
-		sdk_snapshot {
-			name: "mysdk@1",
-			bootclasspath_fragments: ["mysdk_mybootclasspathfragment@1"],
-		}
-
 		prebuilt_bootclasspath_fragment {
-			name: "mysdk_mybootclasspathfragment@1",
-			sdk_member_name: "mybootclasspathfragment",
+			name: "mybootclasspathfragment",
 			prefer: false,
 			visibility: ["//visibility:public"],
 			apex_available: [
 				"myapex",
 			],
 			image_name: "art",
-			contents: ["mysdk_mybootlib@1"],
+			contents: ["mybootlib"],
+			hidden_api: {
+				annotation_flags: "hiddenapi/annotation-flags.csv",
+				metadata: "hiddenapi/metadata.csv",
+				index: "hiddenapi/index.csv",
+				signature_patterns: "hiddenapi/signature-patterns.csv",
+				filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv",
+				filtered_flags: "hiddenapi/filtered-flags.csv",
+			},
 		}
 
 		java_import {
-			name: "mysdk_mybootlib@1",
-			sdk_member_name: "mybootlib",
+			name: "mybootlib",
 			visibility: ["//visibility:public"],
 			apex_available: ["com.android.art"],
 			jars: ["java/mybootlib.jar"],
diff --git a/sdk/sdk.go b/sdk/sdk.go
index aeeedb4..4d4a2a2 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -17,7 +17,6 @@
 import (
 	"fmt"
 	"io"
-	"strconv"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -38,7 +37,6 @@
 func registerSdkBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("sdk", SdkModuleFactory)
 	ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
-	ctx.PreDepsMutators(RegisterPreDepsMutators)
 }
 
 type sdk struct {
@@ -275,14 +273,6 @@
 
 var _ android.SdkDependencyContext = (*dependencyContext)(nil)
 
-// RegisterPreDepsMutators registers pre-deps mutators to support modules implementing SdkAware
-// interface and the sdk module type. This function has been made public to be called by tests
-// outside of the sdk package
-func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
-	ctx.BottomUp("SdkMember", memberMutator).Parallel()
-	ctx.TopDown("SdkMember_deps", memberDepsMutator).Parallel()
-}
-
 type dependencyTag struct {
 	blueprint.BaseDependencyTag
 }
@@ -292,68 +282,35 @@
 
 var _ android.ExcludeFromApexContentsTag = dependencyTag{}
 
-// Step 1: create dependencies from an SDK module to its members.
-func memberMutator(mctx android.BottomUpMutatorContext) {
-	if s, ok := mctx.Module().(*sdk); ok {
-		// Add dependencies from enabled and non CommonOS variants to the sdk member variants.
-		if s.Enabled() && !s.IsCommonOSVariant() {
-			ctx := s.newDependencyContext(mctx)
-			for _, memberListProperty := range s.memberTypeListProperties() {
-				if memberListProperty.getter == nil {
-					continue
-				}
-				names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
-				if len(names) > 0 {
-					memberType := memberListProperty.memberType
+func (s *sdk) DepsMutator(mctx android.BottomUpMutatorContext) {
+	// Add dependencies from non CommonOS variants to the sdk member variants.
+	if s.IsCommonOSVariant() {
+		return
+	}
 
-					// Verify that the member type supports the specified traits.
-					supportedTraits := memberType.SupportedTraits()
-					for _, name := range names {
-						requiredTraits := ctx.RequiredTraits(name)
-						unsupportedTraits := requiredTraits.Subtract(supportedTraits)
-						if !unsupportedTraits.Empty() {
-							ctx.ModuleErrorf("sdk member %q has traits %s that are unsupported by its member type %q", name, unsupportedTraits, memberType.SdkPropertyName())
-						}
-					}
+	ctx := s.newDependencyContext(mctx)
+	for _, memberListProperty := range s.memberTypeListProperties() {
+		if memberListProperty.getter == nil {
+			continue
+		}
+		names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
+		if len(names) > 0 {
+			memberType := memberListProperty.memberType
 
-					// Add dependencies using the appropriate tag.
-					tag := memberListProperty.dependencyTag
-					memberType.AddDependencies(ctx, tag, names)
+			// Verify that the member type supports the specified traits.
+			supportedTraits := memberType.SupportedTraits()
+			for _, name := range names {
+				requiredTraits := ctx.RequiredTraits(name)
+				unsupportedTraits := requiredTraits.Subtract(supportedTraits)
+				if !unsupportedTraits.Empty() {
+					ctx.ModuleErrorf("sdk member %q has traits %s that are unsupported by its member type %q",
+						name, unsupportedTraits, memberType.SdkPropertyName())
 				}
 			}
+
+			// Add dependencies using the appropriate tag.
+			tag := memberListProperty.dependencyTag
+			memberType.AddDependencies(ctx, tag, names)
 		}
 	}
 }
-
-// Step 2: record that dependencies of SDK modules are members of the SDK modules
-func memberDepsMutator(mctx android.TopDownMutatorContext) {
-	if s, ok := mctx.Module().(*sdk); ok {
-		mySdkRef := android.ParseSdkRef(mctx, mctx.ModuleName(), "name")
-		if s.snapshot() && mySdkRef.Unversioned() {
-			mctx.PropertyErrorf("name", "sdk_snapshot should be named as <name>@<version>. "+
-				"Did you manually modify Android.bp?")
-		}
-		if !s.snapshot() && !mySdkRef.Unversioned() {
-			mctx.PropertyErrorf("name", "sdk shouldn't be named as <name>@<version>.")
-		}
-		if mySdkRef.Version != "" && mySdkRef.Version != "current" {
-			if _, err := strconv.Atoi(mySdkRef.Version); err != nil {
-				mctx.PropertyErrorf("name", "version %q is neither a number nor \"current\"", mySdkRef.Version)
-			}
-		}
-
-		mctx.VisitDirectDeps(func(child android.Module) {
-			if member, ok := child.(android.SdkAware); ok {
-				member.MakeMemberOf(mySdkRef)
-			}
-		})
-	}
-}
-
-// An interface that encapsulates all the functionality needed to manage the sdk dependencies.
-//
-// It is a mixture of apex and sdk module functionality.
-type sdkAndApexModule interface {
-	android.Module
-	android.DepIsInSameApex
-}
diff --git a/sdk/update.go b/sdk/update.go
index baa2033..f50439c 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -171,9 +171,9 @@
 				exportedComponentsInfo = ctx.OtherModuleProvider(child, android.ExportedComponentsInfoProvider).(android.ExportedComponentsInfo)
 			}
 
-			var container android.SdkAware
+			var container android.Module
 			if parent != ctx.Module() {
-				container = parent.(android.SdkAware)
+				container = parent.(android.Module)
 			}
 
 			minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, child)
@@ -182,7 +182,7 @@
 			s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{
 				sdkVariant:             s,
 				memberType:             memberType,
-				variant:                child.(android.SdkAware),
+				variant:                child.(android.Module),
 				minApiLevel:            minApiLevel,
 				container:              container,
 				export:                 export,
@@ -269,7 +269,7 @@
 	return supportedByTargetBuildRelease
 }
 
-func appendUniqueVariants(variants []android.SdkAware, newVariant android.SdkAware) []android.SdkAware {
+func appendUniqueVariants(variants []android.Module, newVariant android.Module) []android.Module {
 	for _, v := range variants {
 		if v == newVariant {
 			return variants
@@ -1246,12 +1246,12 @@
 	memberType android.SdkMemberType
 
 	// The variant that is added to the sdk.
-	variant android.SdkAware
+	variant android.Module
 
 	// The optional container of this member, i.e. the module that is depended upon by the sdk
 	// (possibly transitively) and whose dependency on this module is why it was added to the sdk.
 	// Is nil if this a direct dependency of the sdk.
-	container android.SdkAware
+	container android.Module
 
 	// True if the member should be exported, i.e. accessible, from outside the sdk.
 	export bool
@@ -1270,14 +1270,14 @@
 type sdkMember struct {
 	memberType android.SdkMemberType
 	name       string
-	variants   []android.SdkAware
+	variants   []android.Module
 }
 
 func (m *sdkMember) Name() string {
 	return m.name
 }
 
-func (m *sdkMember) Variants() []android.SdkAware {
+func (m *sdkMember) Variants() []android.Module {
 	return m.variants
 }
 
@@ -1362,24 +1362,24 @@
 // by apex variant, where one is the default/platform variant and one is the APEX variant. In that
 // case it picks the APEX variant. It picks the APEX variant because that is the behavior that would
 // be expected
-func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.SdkAware) []android.SdkAware {
+func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.Module) []android.Module {
 	moduleCtx := ctx.sdkMemberContext
 
 	// Group the variants by coordinates.
-	variantsByCoord := make(map[variantCoordinate][]android.SdkAware)
+	variantsByCoord := make(map[variantCoordinate][]android.Module)
 	for _, variant := range variants {
 		coord := getVariantCoordinate(ctx, variant)
 		variantsByCoord[coord] = append(variantsByCoord[coord], variant)
 	}
 
-	toDiscard := make(map[android.SdkAware]struct{})
+	toDiscard := make(map[android.Module]struct{})
 	for coord, list := range variantsByCoord {
 		count := len(list)
 		if count == 1 {
 			continue
 		}
 
-		variantsByApex := make(map[string]android.SdkAware)
+		variantsByApex := make(map[string]android.Module)
 		conflictDetected := false
 		for _, variant := range list {
 			apexInfo := moduleCtx.OtherModuleProvider(variant, android.ApexInfoProvider).(android.ApexInfo)
@@ -1421,7 +1421,7 @@
 	// If there are any variants to discard then remove them from the list of variants, while
 	// preserving the order.
 	if len(toDiscard) > 0 {
-		filtered := []android.SdkAware{}
+		filtered := []android.Module{}
 		for _, variant := range variants {
 			if _, ok := toDiscard[variant]; !ok {
 				filtered = append(filtered, variant)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 9627329..c921ca6 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -379,8 +379,16 @@
 		}
 		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options})
 	}
-	s.testConfig = tradefed.AutoGenShellTestConfig(ctx, s.testProperties.Test_config,
-		s.testProperties.Test_config_template, s.testProperties.Test_suites, configs, s.testProperties.Auto_gen_config, s.outputFilePath.Base())
+	s.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+		TestConfigProp:         s.testProperties.Test_config,
+		TestConfigTemplateProp: s.testProperties.Test_config_template,
+		TestSuites:             s.testProperties.Test_suites,
+		Config:                 configs,
+		AutoGenConfig:          s.testProperties.Auto_gen_config,
+		OutputFileName:         s.outputFilePath.Base(),
+		DeviceTemplate:         "${ShellTestConfigTemplate}",
+		HostTemplate:           "${ShellTestConfigTemplate}",
+	})
 
 	s.dataModules = make(map[string]android.Path)
 	ctx.VisitDirectDeps(func(dep android.Module) {
diff --git a/soong_ui.bash b/soong_ui.bash
index 49c4b78..7bddb58 100755
--- a/soong_ui.bash
+++ b/soong_ui.bash
@@ -18,34 +18,8 @@
 # that's detected in the Go code, which skips calculating the startup time.
 export TRACE_BEGIN_SOONG=$(date +%s%N)
 
-# Function to find top of the source tree (if $TOP isn't set) by walking up the
-# tree.
-function gettop
-{
-    local TOPFILE=build/soong/root.bp
-    if [ -n "${TOP-}" -a -f "${TOP-}/${TOPFILE}" ] ; then
-        # The following circumlocution ensures we remove symlinks from TOP.
-        (cd $TOP; PWD= /bin/pwd)
-    else
-        if [ -f $TOPFILE ] ; then
-            # The following circumlocution (repeated below as well) ensures
-            # that we record the true directory name and not one that is
-            # faked up with symlink names.
-            PWD= /bin/pwd
-        else
-            local HERE=$PWD
-            T=
-            while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
-                \cd ..
-                T=`PWD= /bin/pwd -P`
-            done
-            \cd $HERE
-            if [ -f "$T/$TOPFILE" ]; then
-                echo $T
-            fi
-        fi
-    fi
-}
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../make/shell_utils.sh
+require_top
 
 # Save the current PWD for use in soong_ui
 export ORIGINAL_PWD=${PWD}
diff --git a/tests/androidmk_test.sh b/tests/androidmk_test.sh
index d0d382b..b81828b 100755
--- a/tests/androidmk_test.sh
+++ b/tests/androidmk_test.sh
@@ -133,6 +133,4 @@
   echo "Succeeded"
 }
 
-test_rewrite_license_property_inside_current_directory
-
-test_rewrite_license_property_outside_current_directory
+scan_and_run_tests
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index d579429..412f84a 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -67,23 +67,26 @@
   //packages/modules/adb/apex:com.android.adbd \
   //system/timezone/apex:com.android.tzdata \
   //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex
+BAZEL_ADBD="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //packages/modules/adb/apex:com.android.adbd))"
+BAZEL_TZDATA="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //system/timezone/apex:com.android.tzdata))"
+BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))"
 
 # # Build debugfs separately, as it's not a dep of apexer, but needs to be an explicit arg.
 call_bazel build --config=bp2build --config=linux_x86_64 //external/e2fsprogs/debugfs //system/apex/tools:deapexer
-DEBUGFS_PATH="$BAZEL_OUT/linux_x86_64-opt/bin/external/e2fsprogs/debugfs/debugfs"
-DEAPEXER="$BAZEL_OUT/linux_x86_64-opt/bin/system/apex/tools/deapexer --debugfs_path=$DEBUGFS_PATH"
+DEBUGFS_PATH="$(realpath $(call_bazel cquery --config=bp2build --config=linux_x86_64 --config=ci --output=files //external/e2fsprogs/debugfs))"
+DEAPEXER="$(realpath $(call_bazel cquery --config=bp2build --config=linux_x86_64 --config=ci --output=files //system/apex/tools:deapexer))"
+DEAPEXER="$DEAPEXER --debugfs_path=$DEBUGFS_PATH"
 
 #######
 # Tests
 #######
 
 function compare_deapexer_list() {
-  local APEX_DIR=$1; shift
+  local BAZEL_APEX=$1; shift
   local APEX=$1; shift
 
   # Compare the outputs of `deapexer list`, which lists the contents of the apex filesystem image.
   local SOONG_APEX="$SOONG_OUTPUT_DIR/$APEX"
-  local BAZEL_APEX="$BAZEL_OUT/android_target-opt/bin/$APEX_DIR/$APEX"
 
   local SOONG_LIST="$OUTPUT_DIR/soong.list"
   local BAZEL_LIST="$OUTPUT_DIR/bazel.list"
@@ -108,6 +111,6 @@
   fi
 }
 
-compare_deapexer_list packages/modules/adb/apex com.android.adbd.apex
-compare_deapexer_list system/timezone/apex com.android.tzdata.apex
-compare_deapexer_list build/bazel/examples/apex/minimal build.bazel.examples.apex.minimal.apex
+compare_deapexer_list "${BAZEL_ADBD}" com.android.adbd.apex
+compare_deapexer_list "${BAZEL_TZDATA}" com.android.tzdata.apex
+compare_deapexer_list "${BAZEL_MINIMAL}" build.bazel.examples.apex.minimal.apex
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 6a47e9f..8c2ce48 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -140,9 +140,9 @@
   # NOTE: We don't actually use the extra BUILD file for anything here
   run_bazel build --config=android --config=bp2build --config=ci //foo/...
 
-  local the_answer_file="bazel-out/android_target-opt/bin/foo/convertible_soong_module/the_answer.txt"
+  local the_answer_file="$(find -L bazel-out -name the_answer.txt)"
   if [[ ! -f "${the_answer_file}" ]]; then
-    fail "Expected '${the_answer_file}' to be generated, but was missing"
+    fail "Expected the_answer.txt to be generated, but was missing"
   fi
   if ! grep 42 "${the_answer_file}"; then
     fail "Expected to find 42 in '${the_answer_file}'"
diff --git a/tests/lib.sh b/tests/lib.sh
index ae8875a..26bdc97 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -85,7 +85,7 @@
   create_mock_bazel
   copy_directory build/blueprint
   copy_directory build/soong
-  copy_directory build/make/tools/rbcrun
+  copy_directory build/make
 
   symlink_directory prebuilts/sdk
   symlink_directory prebuilts/go
@@ -107,7 +107,7 @@
   info "Running test case \e[96;1m${FUNCNAME[1]}\e[0m"
   cd "$MOCK_TOP"
 
-  tar xzf "$WARMED_UP_MOCK_TOP"
+  tar xzf "$WARMED_UP_MOCK_TOP" --warning=no-timestamp
 }
 
 # shellcheck disable=SC2120
@@ -163,4 +163,4 @@
   for f in ${test_fns[*]}; do
     $f
   done
-}
\ No newline at end of file
+}
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index 8949b42..7b3151b 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -63,5 +63,4 @@
   fi
 }
 
-test_add_irrelevant_file
-test_bazel_smoke
+scan_and_run_tests
\ No newline at end of file
diff --git a/tests/soong_test.sh b/tests/soong_test.sh
index 905d708..f7bee40 100755
--- a/tests/soong_test.sh
+++ b/tests/soong_test.sh
@@ -19,4 +19,4 @@
   run_soong clean
 }
 
-test_m_clean_works
+scan_and_run_tests
\ No newline at end of file
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index c2429ab..49b09af 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -107,15 +107,10 @@
 
 }
 
-func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, configs []Config, testInstallBase string) {
-	autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), output, template, configs, "", testInstallBase)
-}
-
-func autogenTemplateWithName(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, testInstallBase string) {
-	autogenTemplateWithNameAndOutputFile(ctx, name, output, template, configs, "", testInstallBase)
-}
-
-func autogenTemplateWithNameAndOutputFile(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string, testInstallBase string) {
+func autogenTemplate(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string, testInstallBase string) {
+	if template == "" {
+		ctx.ModuleErrorf("Empty template")
+	}
 	var configStrings []string
 	for _, config := range configs {
 		configStrings = append(configStrings, config.Config())
@@ -137,144 +132,53 @@
 	})
 }
 
-func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool, testInstallBase string) android.Path {
+// AutoGenTestConfigOptions is used so that we can supply many optional
+// arguments to the AutoGenTestConfig function.
+type AutoGenTestConfigOptions struct {
+	Name                    string
+	OutputFileName          string
+	TestConfigProp          *string
+	TestConfigTemplateProp  *string
+	TestSuites              []string
+	Config                  []Config
+	OptionsForAutogenerated []Option
+	AutoGenConfig           *bool
+	UnitTest                *bool
+	TestInstallBase         string
+	DeviceTemplate          string
+	HostTemplate            string
+	HostUnitTestTemplate    string
+}
 
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
+func AutoGenTestConfig(ctx android.ModuleContext, options AutoGenTestConfigOptions) android.Path {
+	configs := append([]Config{}, options.Config...)
+	for _, c := range options.OptionsForAutogenerated {
+		configs = append(configs, c)
+	}
+	name := options.Name
+	if name == "" {
+		name = ctx.ModuleName()
+	}
+	path, autogenPath := testConfigPath(ctx, options.TestConfigProp, options.TestSuites, options.AutoGenConfig, options.TestConfigTemplateProp)
 	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
+		templatePath := getTestConfigTemplate(ctx, options.TestConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), config, testInstallBase)
+			autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, options.OutputFileName, options.TestInstallBase)
 		} else {
 			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}", config, testInstallBase)
+				autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, options.OutputFileName, options.TestInstallBase)
 			} else {
-				autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}", config, testInstallBase)
-			}
-		}
-		return autogenPath
-	}
-	return path
-}
-
-func AutoGenShellTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool, outputFileName string) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
-	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
-		if templatePath.Valid() {
-			autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), autogenPath, templatePath.String(), config, outputFileName, "")
-		} else {
-			autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), autogenPath, "${ShellTestConfigTemplate}", config, outputFileName, "")
-		}
-		return autogenPath
-	}
-	return path
-}
-
-func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, configs []Config, autoGenConfig *bool) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
-	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
-		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), configs, "")
-		} else {
-			autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}", configs, "")
-		}
-		return autogenPath
-	}
-	return path
-}
-
-func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
-	testSuites []string, config []Config, autoGenConfig *bool, unitTest *bool) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
-	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
-		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), config, "")
-		} else {
-			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", config, "")
-			} else {
-				if Bool(unitTest) {
-					autogenTemplate(ctx, autogenPath, "${JavaHostUnitTestConfigTemplate}", config, "")
+				if Bool(options.UnitTest) {
+					autogenTemplate(ctx, name, autogenPath, options.HostUnitTestTemplate, configs, options.OutputFileName, options.TestInstallBase)
 				} else {
-					autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", config, "")
+					autogenTemplate(ctx, name, autogenPath, options.HostTemplate, configs, options.OutputFileName, options.TestInstallBase)
 				}
 			}
 		}
 		return autogenPath
 	}
-	return path
-}
-
-func AutoGenPythonBinaryHostTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
-
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
-	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
-		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), nil, "")
-		} else {
-			autogenTemplate(ctx, autogenPath, "${PythonBinaryHostTestConfigTemplate}", nil, "")
-		}
-		return autogenPath
-	}
-	return path
-}
-
-func AutoGenRustTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool, testInstallBase string) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
-	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
-		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), config, testInstallBase)
-		} else {
-			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${RustDeviceTestConfigTemplate}", config, testInstallBase)
-			} else {
-				autogenTemplate(ctx, autogenPath, "${RustHostTestConfigTemplate}", config, testInstallBase)
-			}
-		}
-		return autogenPath
-	}
-	return path
-}
-
-func AutoGenRustBenchmarkConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
-	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
-		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), config, "")
-		} else {
-			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${RustDeviceBenchmarkConfigTemplate}", config, "")
-			} else {
-				autogenTemplate(ctx, autogenPath, "${RustHostBenchmarkConfigTemplate}", config, "")
-			}
-		}
-		return autogenPath
-	}
-	return path
-}
-
-func AutoGenRobolectricTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
-	testSuites []string, autoGenConfig *bool) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
-	if autogenPath != nil {
-		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
-		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), nil, "")
-		} else {
-			autogenTemplate(ctx, autogenPath, "${RobolectricTestConfigTemplate}", nil, "")
-		}
-		return autogenPath
+	if len(options.OptionsForAutogenerated) > 0 {
+		ctx.ModuleErrorf("Extra tradefed configurations were provided for an autogenerated xml file, but the autogenerated xml file was not used.")
 	}
 	return path
 }
diff --git a/ui/build/config.go b/ui/build/config.go
index a6bba15..61f6b1c 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -63,6 +63,7 @@
 	environ       *Environment
 	distDir       string
 	buildDateTime string
+	logsPrefix    string
 
 	// From the arguments
 	parallel          int
@@ -84,6 +85,7 @@
 	skipSoongTests    bool
 	searchApiDir      bool // Scan the Android.bp files generated in out/api_surfaces
 	skipMetricsUpload bool
+	buildStartedTime  int64 // For metrics-upload-only - manually specify a build-started time
 
 	// From the product config
 	katiArgs        []string
@@ -255,6 +257,14 @@
 	return true
 }
 
+func UploadOnlyConfig(ctx Context, _ ...string) Config {
+	ret := &configImpl{
+		environ:       OsEnvironment(),
+		sandboxConfig: &SandboxConfig{},
+	}
+	return Config{ret}
+}
+
 func NewConfig(ctx Context, args ...string) Config {
 	ret := &configImpl{
 		environ:       OsEnvironment(),
@@ -266,9 +276,7 @@
 	ret.keepGoing = 1
 
 	ret.totalRAM = detectTotalRAM(ctx)
-
 	ret.parseArgs(ctx, args)
-
 	// Make sure OUT_DIR is set appropriately
 	if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
 		ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
@@ -756,6 +764,14 @@
 			ctx.Metrics.SetBuildCommand([]string{buildCmd})
 		} else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
 			c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
+		} else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
+			buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
+			val, err := strconv.ParseInt(buildTimeStr, 10, 64)
+			if err == nil {
+				c.buildStartedTime = val
+			} else {
+				ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
+			}
 		} else if len(arg) > 0 && arg[0] == '-' {
 			parseArgNum := func(def int) int {
 				if len(arg) > 2 {
@@ -1092,6 +1108,14 @@
 	c.includeTags = i
 }
 
+func (c *configImpl) GetLogsPrefix() string {
+	return c.logsPrefix
+}
+
+func (c *configImpl) SetLogsPrefix(prefix string) {
+	c.logsPrefix = prefix
+}
+
 func (c *configImpl) HighmemParallel() int {
 	if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
 		return i
@@ -1519,6 +1543,15 @@
 	return c.skipMetricsUpload
 }
 
+// Returns a Time object if one was passed via a command-line flag.
+// Otherwise returns the passed default.
+func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
+	if c.buildStartedTime == 0 {
+		return defaultTime
+	}
+	return time.UnixMilli(c.buildStartedTime)
+}
+
 func GetMetricsUploader(topDir string, env *Environment) string {
 	if p, ok := env.Get("METRICS_UPLOADER"); ok {
 		metricsUploader := filepath.Join(topDir, p)
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 370b1bc..e6543ec 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -15,16 +15,13 @@
 package build
 
 import (
-	"errors"
 	"fmt"
-	"io/fs"
 	"os"
 	"path/filepath"
 	"strconv"
 	"strings"
 
 	"android/soong/ui/metrics"
-	soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
 	"android/soong/ui/status"
 
 	"android/soong/shared"
@@ -32,8 +29,6 @@
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/bootstrap"
 	"github.com/google/blueprint/microfactory"
-
-	"google.golang.org/protobuf/proto"
 )
 
 const (
@@ -566,22 +561,6 @@
 		targets = append(targets, config.SoongNinjaFile())
 	}
 
-	// TODO(juu): Stop embedding soong_build_metrics in soong_metrics.
-	soongBuildMetricsFile := filepath.Join(config.LogsDir(), "soong_build_metrics.pb")
-	if err := os.Remove(soongBuildMetricsFile); err != nil && !os.IsNotExist(err) {
-		ctx.Verbosef("Failed to remove %s", soongBuildMetricsFile)
-	}
-	if shouldCollectBuildSoongMetrics(config) {
-		defer func() {
-			soongBuildMetrics := loadSoongBuildMetrics(ctx, soongBuildMetricsFile)
-			if soongBuildMetrics != nil {
-				logSoongBuildMetrics(ctx, soongBuildMetrics)
-				if ctx.Metrics != nil {
-					ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
-				}
-			}
-		}()
-	}
 	ninja("bootstrap", "bootstrap.ninja", targets...)
 
 	distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
@@ -614,36 +593,3 @@
 		ctx.Fatalf("failed to build %s: %s", name, err)
 	}
 }
-
-func shouldCollectBuildSoongMetrics(config Config) bool {
-	// Do not collect metrics protobuf if the soong_build binary ran as the
-	// bp2build converter or the JSON graph dump.
-	return config.SoongBuildInvocationNeeded()
-}
-
-func loadSoongBuildMetrics(ctx Context, soongBuildMetricsFile string) *soong_metrics_proto.SoongBuildMetrics {
-	buf, err := os.ReadFile(soongBuildMetricsFile)
-	if errors.Is(err, fs.ErrNotExist) {
-		// Soong may not have run during this invocation
-		ctx.Verbosef("Failed to read metrics file, %s: %s", soongBuildMetricsFile, err)
-		return nil
-	} else if err != nil {
-		ctx.Fatalf("Failed to load %s: %s", soongBuildMetricsFile, err)
-	}
-	soongBuildMetrics := &soong_metrics_proto.SoongBuildMetrics{}
-	err = proto.Unmarshal(buf, soongBuildMetrics)
-	if err != nil {
-		ctx.Fatalf("Failed to unmarshal %s: %s", soongBuildMetricsFile, err)
-	}
-	return soongBuildMetrics
-}
-
-func logSoongBuildMetrics(ctx Context, metrics *soong_metrics_proto.SoongBuildMetrics) {
-	ctx.Verbosef("soong_build metrics:")
-	ctx.Verbosef(" modules: %v", metrics.GetModules())
-	ctx.Verbosef(" variants: %v", metrics.GetVariants())
-	ctx.Verbosef(" max heap size: %v MB", metrics.GetMaxHeapSize()/1e6)
-	ctx.Verbosef(" total allocation count: %v", metrics.GetTotalAllocCount())
-	ctx.Verbosef(" total allocation size: %v MB", metrics.GetTotalAllocSize()/1e6)
-
-}
diff --git a/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go b/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
index 760b592..f8b8fd6 100644
--- a/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
+++ b/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
@@ -97,8 +97,9 @@
 	// E.g. "execution", "analysis", "launch"
 	PhaseName     *string `protobuf:"bytes,1,opt,name=phase_name,json=phaseName,proto3,oneof" json:"phase_name,omitempty"`
 	DurationNanos *int64  `protobuf:"varint,2,opt,name=duration_nanos,json=durationNanos,proto3,oneof" json:"duration_nanos,omitempty"`
-	// What percentage of the build time this phase took
-	PercentageMillis *int32 `protobuf:"varint,3,opt,name=percentage_millis,json=percentageMillis,proto3,oneof" json:"percentage_millis,omitempty"`
+	// What portion of the build time this phase took, with ten-thousandths precision.
+	// E.g., 1111 = 11.11%, 111 = 1.11%
+	PortionOfBuildTime *int32 `protobuf:"varint,3,opt,name=portion_of_build_time,json=portionOfBuildTime,proto3,oneof" json:"portion_of_build_time,omitempty"`
 }
 
 func (x *PhaseTiming) Reset() {
@@ -147,9 +148,9 @@
 	return 0
 }
 
-func (x *PhaseTiming) GetPercentageMillis() int32 {
-	if x != nil && x.PercentageMillis != nil {
-		return *x.PercentageMillis
+func (x *PhaseTiming) GetPortionOfBuildTime() int32 {
+	if x != nil && x.PortionOfBuildTime != nil {
+		return *x.PortionOfBuildTime
 	}
 	return 0
 }
@@ -168,23 +169,23 @@
 	0x52, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19,
 	0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52,
 	0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f,
-	0x74, 0x61, 0x6c, 0x22, 0xc7, 0x01, 0x0a, 0x0b, 0x50, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d,
+	0x74, 0x61, 0x6c, 0x22, 0xd1, 0x01, 0x0a, 0x0b, 0x50, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d,
 	0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
 	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x68, 0x61, 0x73, 0x65,
 	0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74,
 	0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48,
 	0x01, 0x52, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73,
-	0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x11, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67,
-	0x65, 0x5f, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02,
-	0x52, 0x10, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x4d, 0x69, 0x6c, 0x6c,
-	0x69, 0x73, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f,
-	0x6e, 0x61, 0x6d, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x70, 0x65, 0x72, 0x63,
-	0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x42, 0x2e, 0x5a,
-	0x2c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75,
-	0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f,
-	0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x15, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f,
+	0x66, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x05, 0x48, 0x02, 0x52, 0x12, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x66, 0x42,
+	0x75, 0x69, 0x6c, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f,
+	0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x64,
+	0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x42, 0x18, 0x0a,
+	0x16, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x66, 0x5f, 0x62, 0x75, 0x69,
+	0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+	0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+	0x69, 0x63, 0x73, 0x2f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+	0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/ui/metrics/bazel_metrics_proto/bazel_metrics.proto b/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
index e78a6b9..57eed4c 100644
--- a/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
+++ b/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
@@ -26,6 +26,7 @@
   // E.g. "execution", "analysis", "launch"
   optional string phase_name = 1;
   optional int64 duration_nanos = 2;
-  // What percentage of the build time this phase took
-  optional int32 percentage_millis = 3;
+  // What portion of the build time this phase took, with ten-thousandths precision.
+  // E.g., 1111 = 11.11%, 111 = 1.11%
+  optional int32 portion_of_build_time = 3;
 }
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index ce2d946..717530c 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -32,13 +32,13 @@
 // of what an event is and how the metrics system is a stack based system.
 
 import (
+	"fmt"
 	"os"
 	"runtime"
 	"strings"
 	"time"
 
 	"android/soong/shared"
-
 	"google.golang.org/protobuf/proto"
 
 	soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -223,6 +223,17 @@
 	m.metrics.BuildDateTimestamp = proto.Int64(buildTimestamp.UnixNano() / int64(time.Second))
 }
 
+func (m *Metrics) UpdateTotalRealTime(data []byte) error {
+	if err := proto.Unmarshal(data, &m.metrics); err != nil {
+		return fmt.Errorf("Failed to unmarshal proto", err)
+	}
+	startTime := *m.metrics.Total.StartTime
+	endTime := uint64(time.Now().UnixNano())
+
+	*m.metrics.Total.RealTime = *proto.Uint64(endTime - startTime)
+	return nil
+}
+
 // SetBuildCommand adds the build command specified by the user to the
 // list of collected metrics.
 func (m *Metrics) SetBuildCommand(cmd []string) {
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 90d124b..eb8fdc4 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -15,7 +15,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.28.0
-// 	protoc        v3.9.1
+// 	protoc        v3.21.7
 // source: metrics.proto
 
 package metrics_proto
@@ -325,7 +325,11 @@
 	// The metrics for calling Ninja.
 	NinjaRuns []*PerfInfo `protobuf:"bytes,20,rep,name=ninja_runs,json=ninjaRuns" json:"ninja_runs,omitempty"`
 	// The metrics for the whole build
-	Total             *PerfInfo          `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
+	Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
+	// Deprecated because instead of embedding in a MetricsBase, we keep
+	// SoongBuildMetrics in its own file
+	//
+	// Deprecated: Do not use.
 	SoongBuildMetrics *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
 	BuildConfig       *BuildConfig       `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
 	// The hostname of the machine.
@@ -533,6 +537,7 @@
 	return nil
 }
 
+// Deprecated: Do not use.
 func (x *MetricsBase) GetSoongBuildMetrics() *SoongBuildMetrics {
 	if x != nil {
 		return x.SoongBuildMetrics
@@ -1409,7 +1414,7 @@
 var file_metrics_proto_rawDesc = []byte{
 	0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
 	0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
-	0x72, 0x69, 0x63, 0x73, 0x22, 0xf6, 0x0d, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+	0x72, 0x69, 0x63, 0x73, 0x22, 0xfa, 0x0d, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
 	0x42, 0x61, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x61,
 	0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x03, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d,
@@ -1480,195 +1485,195 @@
 	0x75, 0x6e, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x15, 0x20, 0x01,
 	0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
 	0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66,
-	0x6f, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x56, 0x0a, 0x13, 0x73, 0x6f, 0x6f, 0x6e,
+	0x6f, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x5a, 0x0a, 0x13, 0x73, 0x6f, 0x6f, 0x6e,
 	0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18,
 	0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
 	0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x6f, 0x6f, 0x6e,
-	0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x11, 0x73,
-	0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
-	0x12, 0x43, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
-	0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x42, 0x75, 0x69,
-	0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d,
-	0x65, 0x12, 0x59, 0x0a, 0x14, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x72, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x27, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
-	0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
-	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, 0x0a, 0x0d,
-	0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x1a, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x12, 0x3c, 0x0a, 0x0a, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x72, 0x75, 0x6e, 0x73, 0x18,
-	0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
-	0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
-	0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x73, 0x12,
-	0x53, 0x0a, 0x12, 0x65, 0x78, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x66, 0x65,
-	0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f,
-	0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68,
-	0x65, 0x72, 0x52, 0x10, 0x65, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74,
-	0x63, 0x68, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f,
-	0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e,
-	0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f,
-	0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x30, 0x0a,
-	0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08, 0x0a,
-	0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52, 0x44,
-	0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02, 0x22,
-	0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f,
-	0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09, 0x0a,
-	0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36, 0x10,
-	0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04, 0x22, 0x99, 0x02,
-	0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a,
-	0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
-	0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f,
-	0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x52, 0x62,
-	0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x67,
-	0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65,
-	0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65, 0x6c,
-	0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
-	0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a, 0x0a,
-	0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69,
-	0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x4d,
-	0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x72,
-	0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67,
-	0x65, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73,
-	0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64,
-	0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x66, 0x6f,
-	0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d,
-	0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x22, 0x6f, 0x0a, 0x12, 0x53, 0x79, 0x73,
-	0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12,
-	0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61,
-	0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13,
-	0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65, 0x6d,
-	0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
-	0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76, 0x61,
-	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x50,
-	0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
-	0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65,
-	0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a,
-	0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09,
-	0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
-	0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d,
-	0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18,
-	0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17,
-	0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
-	0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
-	0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
-	0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-	0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22,
-	0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18,
-	0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78,
-	0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72,
-	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63,
-	0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12,
-	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65,
-	0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75,
-	0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a,
-	0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63,
-	0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65,
-	0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d,
-	0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
-	0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e,
-	0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05,
-	0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46,
-	0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70,
-	0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04,
-	0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74,
-	0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62,
-	0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b,
-	0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b,
-	0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75,
-	0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79,
-	0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65,
-	0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61,
-	0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65,
-	0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79,
-	0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65,
-	0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e,
-	0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63,
-	0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79,
-	0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
-	0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73,
-	0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-	0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66,
-	0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55,
-	0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73,
-	0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79,
-	0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
-	0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d,
-	0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75,
-	0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75,
-	0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b,
-	0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10,
-	0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43,
-	0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e,
-	0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a,
-	0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
-	0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
-	0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65,
-	0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69,
-	0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79,
-	0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73,
-	0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
-	0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69,
-	0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79,
-	0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22, 0xcc, 0x02,
-	0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72,
-	0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a,
-	0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
-	0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74,
-	0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
-	0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61,
-	0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
-	0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12,
-	0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65,
-	0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53,
-	0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
-	0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e,
-	0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69,
-	0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
-	0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
-	0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65,
-	0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78,
-	0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xdb, 0x01, 0x0a,
-	0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65,
-	0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
-	0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-	0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53,
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a,
-	0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63,
-	0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f,
-	0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75,
-	0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00,
-	0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05,
-	0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49,
-	0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d,
-	0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d,
-	0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e,
-	0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20,
-	0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45,
-	0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a,
-	0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73,
-	0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20,
-	0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44,
-	0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x28,
-	0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f,
-	0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-	0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x02, 0x18,
+	0x01, 0x52, 0x11, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x63, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f,
+	0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+	0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x62, 0x75,
+	0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73,
+	0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73,
+	0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x59, 0x0a, 0x14, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f,
+	0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x19, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
+	0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
+	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x12, 0x73, 0x79,
+	0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+	0x12, 0x23, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x3c, 0x0a, 0x0a, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x72,
+	0x75, 0x6e, 0x73, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
+	0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
+	0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x52,
+	0x75, 0x6e, 0x73, 0x12, 0x53, 0x0a, 0x12, 0x65, 0x78, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+	0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46,
+	0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x10, 0x65, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f,
+	0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d,
+	0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x1e, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+	0x65, 0x22, 0x30, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e,
+	0x74, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55,
+	0x53, 0x45, 0x52, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e,
+	0x47, 0x10, 0x02, 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55,
+	0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10,
+	0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03,
+	0x58, 0x38, 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10,
+	0x04, 0x22, 0x99, 0x02, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07,
+	0x75, 0x73, 0x65, 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75,
+	0x73, 0x65, 0x52, 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75,
+	0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66,
+	0x6f, 0x72, 0x63, 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62,
+	0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a,
+	0x61, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64,
+	0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61,
+	0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a,
+	0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07,
+	0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65,
+	0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d,
+	0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
+	0x52, 0x1b, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61,
+	0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x22, 0x6f, 0x0a,
+	0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
+	0x6e, 0x66, 0x6f, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79,
+	0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x04, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61,
+	0x6c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c,
+	0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0xca,
+	0x02, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64,
+	0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65,
+	0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a,
+	0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+	0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65,
+	0x12, 0x60, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65,
+	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x28, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+	0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52,
+	0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f,
+	0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e,
+	0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65,
+	0x78, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65,
+	0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f,
+	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65,
+	0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13,
+	0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
+	0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f,
+	0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f,
+	0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+	0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73,
+	0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12,
+	0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a,
+	0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c,
+	0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50,
+	0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a,
+	0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06,
+	0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46,
+	0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75,
+	0x74, 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e,
+	0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70,
+	0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f,
+	0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e,
+	0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69,
+	0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c,
+	0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69,
+	0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e,
+	0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69,
+	0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76,
+	0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53,
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75,
+	0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75,
+	0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
+	0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
+	0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70,
+	0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65,
+	0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c,
+	0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+	0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f,
+	0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f,
+	0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
+	0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f,
+	0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a,
+	0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f,
+	0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22,
+	0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a,
+	0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
+	0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+	0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a,
+	0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75,
+	0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04,
+	0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f,
+	0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+	0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75,
+	0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a,
+	0x73, 0x22, 0xcc, 0x02, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64,
+	0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+	0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+	0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a,
+	0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75,
+	0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41,
+	0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74,
+	0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53,
+	0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f,
+	0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48,
+	0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74,
+	0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
+	0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65,
+	0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50,
+	0x0a, 0x11, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69,
+	0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
+	0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
+	0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+	0x0f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f,
+	0x22, 0xdb, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65,
+	0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+	0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e,
+	0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a,
+	0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d,
+	0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46,
+	0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01,
+	0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d,
+	0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22, 0x91,
+	0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e,
+	0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c,
+	0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75,
+	0x69, 0x6c, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+	0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
+	0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+	0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75,
+	0x69, 0x6c, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+	0x65, 0x73, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f,
+	0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d,
+	0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 }
 
 var (
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 07a7df1..5ad13fc 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -93,7 +93,9 @@
   // The metrics for the whole build
   optional PerfInfo total = 21;
 
-  optional SoongBuildMetrics soong_build_metrics = 22;
+  // Deprecated because instead of embedding in a MetricsBase, we keep
+  // SoongBuildMetrics in its own file
+  optional SoongBuildMetrics soong_build_metrics = 22 [deprecated=true];
 
   optional BuildConfig build_config = 23;