Merge "Modify Soong to utilize from-text android.jar in build"
diff --git a/README.md b/README.md
index 85e24c6..70311cb 100644
--- a/README.md
+++ b/README.md
@@ -105,31 +105,35 @@
 
 ### Types
 
-Variables and properties are strongly typed, variables dynamically based on the
-first assignment, and properties statically by the module type.  The supported
-types are:
+Variables and properties are strongly typed. Variables are dynamically typed
+based on the first assignment, and properties are statically typed by the
+module type.  The supported types are:
 * Bool (`true` or `false`)
 * Integers (`int`)
 * Strings (`"string"`)
 * Lists of strings (`["string1", "string2"]`)
 * Maps (`{key1: "value1", key2: ["value2"]}`)
 
-Maps may values of any type, including nested maps.  Lists and maps may have
-trailing commas after the last value.
+Maps may contain values of any type, including nested maps. Lists and maps may
+have trailing commas after the last value.
 
 Strings can contain double quotes using `\"`, for example `"cat \"a b\""`.
 
 ### Operators
 
-Strings, lists of strings, and maps can be appended using the `+` operator.
-Integers can be summed up using the `+` operator. Appending a map produces the
-union of keys in both maps, appending the values of any keys that are present
-in both maps.
+The `+` operator:
+* Sums integers.
+* Concatenates strings and lists.
+* Produces the union of maps.
+
+Concatenating maps produces a map whose keys are the union of the given maps'
+keys, and whose mapped values are the union of the given maps' corresponding
+mapped values.
 
 ### Defaults modules
 
-A defaults module can be used to repeat the same properties in multiple modules.
-For example:
+A `defaults` module can be used to repeat the same properties in multiple
+modules. For example:
 
 ```
 cc_defaults {
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 33655d0..d09b92f 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -37,6 +37,8 @@
 	// all modules in this package and subpackages default to bp2build_available: false.
 	// allows modules to opt-in.
 	Bp2BuildDefaultFalseRecursively
+
+	DEFAULT_NINJA_WEIGHT = 1000
 )
 
 var (
@@ -180,6 +182,8 @@
 		"external/selinux/libselinux":            Bp2BuildDefaultTrueRecursively,
 		"external/selinux/libsepol":              Bp2BuildDefaultTrueRecursively,
 		"external/speex":                         Bp2BuildDefaultTrueRecursively,
+		"external/tinyalsa":                      Bp2BuildDefaultTrueRecursively,
+		"external/tinyalsa_new":                  Bp2BuildDefaultTrueRecursively,
 		"external/toybox":                        Bp2BuildDefaultTrueRecursively,
 		"external/zlib":                          Bp2BuildDefaultTrueRecursively,
 		"external/zopfli":                        Bp2BuildDefaultTrueRecursively,
@@ -220,6 +224,8 @@
 		"hardware/interfaces":                                     Bp2BuildDefaultTrue,
 		"hardware/interfaces/audio/aidl":                          Bp2BuildDefaultTrue,
 		"hardware/interfaces/audio/aidl/common":                   Bp2BuildDefaultTrue,
+		"hardware/interfaces/audio/aidl/default":                  Bp2BuildDefaultTrue,
+		"hardware/interfaces/audio/aidl/sounddose":                Bp2BuildDefaultTrue,
 		"hardware/interfaces/common/aidl":                         Bp2BuildDefaultTrue,
 		"hardware/interfaces/common/fmq/aidl":                     Bp2BuildDefaultTrue,
 		"hardware/interfaces/common/support":                      Bp2BuildDefaultTrue,
@@ -280,6 +286,7 @@
 		"packages/modules/adb/pairing_connection":            Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb/proto":                         Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb/tls":                           Bp2BuildDefaultTrueRecursively,
+		"packages/modules/Gki/libkver":                       Bp2BuildDefaultTrue,
 		"packages/modules/NetworkStack/common/captiveportal": Bp2BuildDefaultTrue,
 		"packages/modules/NeuralNetworks/apex":               Bp2BuildDefaultTrue,
 		"packages/providers/MediaProvider/tools/dialogs":     Bp2BuildDefaultFalse, // TODO(b/242834374)
@@ -344,10 +351,12 @@
 		"system/libhidl/transport/token/1.0/utils":               Bp2BuildDefaultTrue,
 		"system/libhwbinder":                                     Bp2BuildDefaultTrueRecursively,
 		"system/libprocinfo":                                     Bp2BuildDefaultTrue,
+		"system/libvintf":                                        Bp2BuildDefaultTrue,
 		"system/libziparchive":                                   Bp2BuildDefaultTrueRecursively,
 		"system/logging":                                         Bp2BuildDefaultTrueRecursively,
 		"system/media":                                           Bp2BuildDefaultTrue,
 		"system/media/audio":                                     Bp2BuildDefaultTrueRecursively,
+		"system/media/alsa_utils":                                Bp2BuildDefaultTrueRecursively,
 		"system/media/audio_utils":                               Bp2BuildDefaultTrueRecursively,
 		"system/memory/libion":                                   Bp2BuildDefaultTrueRecursively,
 		"system/memory/libmemunreachable":                        Bp2BuildDefaultTrueRecursively,
@@ -356,8 +365,11 @@
 		"system/timezone/apex":                                   Bp2BuildDefaultTrueRecursively,
 		"system/timezone/output_data":                            Bp2BuildDefaultTrueRecursively,
 		"system/tools/aidl/build/tests_bp2build":                 Bp2BuildDefaultTrue,
+		"system/tools/aidl/metadata":                             Bp2BuildDefaultTrue,
+		"system/tools/hidl/metadata":                             Bp2BuildDefaultTrue,
 		"system/tools/mkbootimg":                                 Bp2BuildDefaultTrueRecursively,
 		"system/tools/sysprop":                                   Bp2BuildDefaultTrue,
+		"system/tools/xsdc/utils":                                Bp2BuildDefaultTrueRecursively,
 		"system/unwinding/libunwindstack":                        Bp2BuildDefaultTrueRecursively,
 
 		"tools/apksig":   Bp2BuildDefaultTrue,
@@ -388,6 +400,8 @@
 		"external/protobuf":/* recursive = */ false,
 		"external/python/absl-py":/* recursive = */ true,
 
+		"external/compiler-rt/lib/cfi":/* recursive = */ false,
+
 		// this BUILD file is globbed by //external/icu/icu4c/source:icu4c_test_data's "data/**/*".
 		"external/icu/icu4c/source/data/unidata/norm2":/* recursive = */ false,
 
@@ -562,8 +576,8 @@
 		"car-ui-androidx-constraintlayout-solver-nodeps",
 
 		//system/libhidl
-		// needed by cc_hidl_library
-		"libhidlbase",
+		"libhidlbase", // needed by cc_hidl_library
+		"libhidl_gtest_helper",
 
 		//frameworks/native
 		"framework_native_aidl_binder",
@@ -855,6 +869,28 @@
 		// depends on android.hardware.health-V2.0-java
 		"android.hardware.health-translate-java",
 
+		//system/libvintf
+		// depends on apex-info-list-tinyxml, unconverted xsd_config Soong module type.
+		"libvintf",
+		"vintf",
+		"libassemblevintf",
+		"assemble_vintf",
+		"libvintffm",
+		"vintffm",
+		"checkvintf",
+
+		// depends on audio_policy_configuration_aidl_default, xsd_config module.
+		"libaudioserviceexampleimpl",
+		"android.hardware.audio.service-aidl.example",
+
+		// depends on //system/tools/aidl/build:aidl_metadata_json, which is an aidl_interfaces_metadata custom Soong type.
+		"aidl_metadata_in_cpp",
+		"libaidlmetadata",
+
+		// depends on //system/tools/hidl/build:hidl_metadata_json, which is an hidl_interfaces_metadata custom Soong type.
+		"hidl_metadata_in_cpp",
+		"libhidlmetadata",
+
 		// cc_test related.
 		// b/274164834 "Could not open Configuration file test.cfg"
 		"svcenc", "svcdec",
@@ -1466,4 +1502,31 @@
 	// "libssl",
 	// "libstagefright_flacdec",
 	// "libutils",
+
+	// TODO(b/273282046): Make this list customizable to support various targets.
+	// The list of modules which are expected to spend lots of build time.
+	// With `--ninja_weight_source=soong`, ninja builds these modules and deps first.
+	HugeModulesMap = map[string]int{
+		"libbt_packets":                           DEFAULT_NINJA_WEIGHT,
+		"libbt_packets_nonapex":                   DEFAULT_NINJA_WEIGHT,
+		"crosvm":                                  DEFAULT_NINJA_WEIGHT,
+		"system-api-stubs-docs-non-updatable":     DEFAULT_NINJA_WEIGHT,
+		"test-api-stubs-docs-non-updatable":       DEFAULT_NINJA_WEIGHT,
+		"module-lib-api-stubs-docs-non-updatable": DEFAULT_NINJA_WEIGHT,
+		"libdevices":                              DEFAULT_NINJA_WEIGHT,
+		"libaom":                                  DEFAULT_NINJA_WEIGHT,
+		"libart-disassembler":                     DEFAULT_NINJA_WEIGHT,
+		"libart":                                  DEFAULT_NINJA_WEIGHT,
+		"libprotobuf":                             DEFAULT_NINJA_WEIGHT,
+		"libsyn":                                  DEFAULT_NINJA_WEIGHT,
+		"api-stubs-docs-non-updatable":            DEFAULT_NINJA_WEIGHT,
+		"framework-res":                           DEFAULT_NINJA_WEIGHT,
+		"SystemUI-core":                           DEFAULT_NINJA_WEIGHT,
+		"services-non-updatable-stubs":            DEFAULT_NINJA_WEIGHT,
+		"art.module.public.api.stubs.source":      DEFAULT_NINJA_WEIGHT,
+		"art.module.intra.core.api.stubs.source":  DEFAULT_NINJA_WEIGHT,
+		"virtmgr":                                 DEFAULT_NINJA_WEIGHT,
+		"metalava":                                DEFAULT_NINJA_WEIGHT,
+		"libkeystore2":                            DEFAULT_NINJA_WEIGHT,
+	}
 )
diff --git a/android/api_levels.go b/android/api_levels.go
index 0c0b2b4..ea2afdf 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -466,7 +466,7 @@
 	// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/common/api.bzl;l=23;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
 	return config.Once(apiLevelsMapKey, func() interface{} {
 		apiLevelsMap := getApiLevelsMapReleasedVersions()
-		for i, codename := range config.PlatformVersionActiveCodenames() {
+		for i, codename := range config.PlatformVersionAllPreviewCodenames() {
 			apiLevelsMap[codename] = previewAPILevelBase + i
 		}
 
diff --git a/android/config.go b/android/config.go
index e634647..33deba5 100644
--- a/android/config.go
+++ b/android/config.go
@@ -931,6 +931,11 @@
 	return c.productVariables.Platform_version_active_codenames
 }
 
+// All unreleased codenames.
+func (c *config) PlatformVersionAllPreviewCodenames() []string {
+	return c.productVariables.Platform_version_all_preview_codenames
+}
+
 func (c *config) ProductAAPTConfig() []string {
 	return c.productVariables.AAPTConfig
 }
@@ -1187,6 +1192,10 @@
 	return append([]string(nil), c.productVariables.NamespacesToExport...)
 }
 
+func (c *config) SourceRootDirs() []string {
+	return c.productVariables.SourceRootDirs
+}
+
 func (c *config) IncludeTags() []string {
 	return c.productVariables.IncludeTags
 }
diff --git a/android/namespace.go b/android/namespace.go
index b43ffdf..f357ca7 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -225,6 +225,10 @@
 	return ns, nil
 }
 
+func (r *NameResolver) NewSkippedModule(ctx blueprint.NamespaceContext, name string, skipInfo blueprint.SkippedModuleInfo) {
+	r.rootNamespace.moduleContainer.NewSkippedModule(ctx, name, skipInfo)
+}
+
 func (r *NameResolver) AllModules() []blueprint.ModuleGroup {
 	childLists := [][]blueprint.ModuleGroup{}
 	totalCount := 0
@@ -300,7 +304,7 @@
 	for _, name := range namespace.importedNamespaceNames {
 		imp, ok := r.namespaceAt(name)
 		if !ok {
-			return fmt.Errorf("namespace %v does not exist", name)
+			return fmt.Errorf("namespace %v does not exist; Some necessary modules may have been skipped by Soong. Check if PRODUCT_SOURCE_ROOT_DIRS is pruning necessary Android.bp files.", name)
 		}
 		namespace.visibleNamespaces = append(namespace.visibleNamespaces, imp)
 	}
diff --git a/android/register.go b/android/register.go
index 9a3d3aa..1a3db9d 100644
--- a/android/register.go
+++ b/android/register.go
@@ -162,6 +162,7 @@
 	ctx := &Context{blueprint.NewContext(), config}
 	ctx.SetSrcDir(absSrcDir)
 	ctx.AddIncludeTags(config.IncludeTags()...)
+	ctx.AddSourceRootDirs(config.SourceRootDirs()...)
 	return ctx
 }
 
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 1e1fe10..5bb1e5a 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -28,9 +28,9 @@
 	// MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
 	// or from sdk_version if it is not set.
 	MinSdkVersion(ctx EarlyModuleContext) ApiLevel
-	// ReplaceMaxSdkVersionPlaceholder returns SdkSpec to replace the maxSdkVersion property of permission and
+	// ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and
 	// uses-permission tags if it is set.
-	ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) SdkSpec
+	ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel
 	// TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module,
 	// or from sdk_version if it is not set.
 	TargetSdkVersion(ctx EarlyModuleContext) ApiLevel
diff --git a/android/variable.go b/android/variable.go
index 8c5c0bc..1da5974 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -199,6 +199,7 @@
 	Platform_sdk_extension_version            *int     `json:",omitempty"`
 	Platform_base_sdk_extension_version       *int     `json:",omitempty"`
 	Platform_version_active_codenames         []string `json:",omitempty"`
+	Platform_version_all_preview_codenames    []string `json:",omitempty"`
 	Platform_vndk_version                     *string  `json:",omitempty"`
 	Platform_systemsdk_versions               []string `json:",omitempty"`
 	Platform_security_patch                   *string  `json:",omitempty"`
@@ -461,7 +462,8 @@
 
 	IgnorePrefer32OnDevice bool `json:",omitempty"`
 
-	IncludeTags []string `json:",omitempty"`
+	IncludeTags    []string `json:",omitempty"`
+	SourceRootDirs []string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
@@ -480,13 +482,14 @@
 	*v = productVariables{
 		BuildNumberFile: stringPtr("build_number.txt"),
 
-		Platform_version_name:               stringPtr("S"),
-		Platform_base_sdk_extension_version: intPtr(30),
-		Platform_sdk_version:                intPtr(30),
-		Platform_sdk_codename:               stringPtr("S"),
-		Platform_sdk_final:                  boolPtr(false),
-		Platform_version_active_codenames:   []string{"S"},
-		Platform_vndk_version:               stringPtr("S"),
+		Platform_version_name:                  stringPtr("S"),
+		Platform_base_sdk_extension_version:    intPtr(30),
+		Platform_sdk_version:                   intPtr(30),
+		Platform_sdk_codename:                  stringPtr("S"),
+		Platform_sdk_final:                     boolPtr(false),
+		Platform_version_active_codenames:      []string{"S"},
+		Platform_version_all_preview_codenames: []string{"S"},
+		Platform_vndk_version:                  stringPtr("S"),
 
 		HostArch:                   stringPtr("x86_64"),
 		HostSecondaryArch:          stringPtr("x86"),
diff --git a/apex/apex.go b/apex/apex.go
index 1f700c6..3678636 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -103,12 +103,13 @@
 	// to avoid mistakes. When set as true, no force-labelling.
 	Use_file_contexts_as_is *bool
 
-	// Path to the canned fs config file for customizing file's uid/gid/mod/capabilities. The
-	// format is /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where path_or_glob is a
-	// path or glob pattern for a file or set of files, uid/gid are numerial values of user ID
-	// and group ID, mode is octal value for the file mode, and cap is hexadecimal value for the
-	// capability. If this property is not set, or a file is missing in the file, default config
-	// is used.
+	// Path to the canned fs config file for customizing file's
+	// uid/gid/mod/capabilities. The content of this file is appended to the
+	// default config, so that the custom entries are preferred. The format is
+	// /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where
+	// path_or_glob is a path or glob pattern for a file or set of files,
+	// uid/gid are numerial values of user ID and group ID, mode is octal value
+	// for the file mode, and cap is hexadecimal value for the capability.
 	Canned_fs_config *string `android:"path"`
 
 	ApexNativeDependencies
@@ -2831,7 +2832,7 @@
 	if !baseModuleIsApex {
 		panic(fmt.Errorf("Base module is not apex module: %s", baseApexModuleName))
 	}
-	attrs, props := convertWithBp2build(a, ctx)
+	attrs, props, commonAttrs := convertWithBp2build(a, ctx)
 
 	// We just want the name, not module reference.
 	baseApexName := strings.TrimPrefix(baseApexModuleName, ":")
@@ -2905,7 +2906,9 @@
 		}
 	}
 
-	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: o.Name()}, &attrs)
+	commonAttrs.Name = o.Name()
+
+	ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -3516,6 +3519,7 @@
 	Manifest              bazel.LabelAttribute
 	Android_manifest      bazel.LabelAttribute
 	File_contexts         bazel.LabelAttribute
+	Canned_fs_config      bazel.LabelAttribute
 	Key                   bazel.LabelAttribute
 	Certificate           bazel.LabelAttribute  // used when the certificate prop is a module
 	Certificate_name      bazel.StringAttribute // used when the certificate prop is a string
@@ -3549,17 +3553,12 @@
 		return
 	}
 
-	attrs, props := convertWithBp2build(a, ctx)
-	commonAttrs := android.CommonAttributes{
-		Name: a.Name(),
-	}
-	if a.testApex {
-		commonAttrs.Testonly = proptools.BoolPtr(a.testApex)
-	}
+	attrs, props, commonAttrs := convertWithBp2build(a, ctx)
+	commonAttrs.Name = a.Name()
 	ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
 }
 
-func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties) {
+func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) {
 	var manifestLabelAttribute bazel.LabelAttribute
 	manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")))
 
@@ -3580,6 +3579,11 @@
 		fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.File_contexts))
 	}
 
+	var cannedFsConfigAttribute bazel.LabelAttribute
+	if a.properties.Canned_fs_config != nil {
+		cannedFsConfigAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.Canned_fs_config))
+	}
+
 	productVariableProps := android.ProductVariableProperties(ctx, a)
 	// TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
 	// given it's coming via config, we probably don't want to put it in here.
@@ -3666,6 +3670,7 @@
 		Manifest:              manifestLabelAttribute,
 		Android_manifest:      androidManifestLabelAttribute,
 		File_contexts:         fileContextsLabelAttribute,
+		Canned_fs_config:      cannedFsConfigAttribute,
 		Min_sdk_version:       minSdkVersion,
 		Key:                   keyLabelAttribute,
 		Certificate:           certificate,
@@ -3687,7 +3692,12 @@
 		Bzl_load_location: "//build/bazel/rules/apex:apex.bzl",
 	}
 
-	return attrs, props
+	commonAttrs := android.CommonAttributes{}
+	if a.testApex {
+		commonAttrs.Testonly = proptools.BoolPtr(true)
+	}
+
+	return attrs, props, commonAttrs
 }
 
 // The following conversions are based on this table where the rows are the compile_multilib
diff --git a/apex/apex_test.go b/apex/apex_test.go
index c9665a4..05c888a 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -10105,3 +10105,45 @@
 	android.AssertStringDoesContain(t, "missing lib to trim", libs_to_trim, "libbar")
 	android.AssertStringDoesNotContain(t, "unexpected libs in the libs to trim", libs_to_trim, "libbaz")
 }
+
+func TestCannedFsConfig(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}`)
+	mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+	generateFsRule := mod.Rule("generateFsConfig")
+	cmd := generateFsRule.RuleParams.Command
+
+	ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; ) >`)
+}
+
+func TestCannedFsConfig_HasCustomConfig(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			canned_fs_config: "my_config",
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}`)
+	mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+	generateFsRule := mod.Rule("generateFsConfig")
+	cmd := generateFsRule.RuleParams.Command
+
+	// Ensure that canned_fs_config has "cat my_config" at the end
+	ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; cat my_config ) >`)
+}
diff --git a/apex/builder.go b/apex/builder.go
index 45c5267..e3b6f8e 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -1167,7 +1167,7 @@
 	if a.properties.Canned_fs_config != nil {
 		cmd.Text("cat").Input(android.PathForModuleSrc(ctx, *a.properties.Canned_fs_config))
 	}
-	cmd.Text(") | LC_ALL=C sort ").FlagWithOutput("> ", cannedFsConfig)
+	cmd.Text(")").FlagWithOutput("> ", cannedFsConfig)
 	builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName()))
 
 	return cannedFsConfig.OutputPath
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 03fb5d4..1cc3f22 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -58,6 +58,7 @@
 	ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
 	ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
 	ctx.RegisterModuleType("apex_key", apex.ApexKeyFactory)
+	ctx.RegisterModuleType("apex_test", apex.TestApexBundleFactory)
 	ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("apex", apex.BundleFactory)
@@ -706,6 +707,125 @@
 		}})
 }
 
+func TestOverrideApexTest(t *testing.T) {
+	runOverrideApexTestCase(t, Bp2buildTestCase{
+		Description:                "override_apex",
+		ModuleTypeUnderTest:        "override_apex",
+		ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+		Filesystem:                 map[string]string{},
+		Blueprint: `
+apex_key {
+	name: "com.android.apogee.key",
+	public_key: "com.android.apogee.avbpubkey",
+	private_key: "com.android.apogee.pem",
+	bazel_module: { bp2build_available: false },
+}
+
+android_app_certificate {
+	name: "com.android.apogee.certificate",
+	certificate: "com.android.apogee",
+	bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+	name: "native_shared_lib_1",
+	bazel_module: { bp2build_available: false },
+}
+
+prebuilt_etc {
+	name: "prebuilt_1",
+	bazel_module: { bp2build_available: false },
+}
+
+filegroup {
+	name: "com.android.apogee-file_contexts",
+	srcs: [
+		"com.android.apogee-file_contexts",
+	],
+	bazel_module: { bp2build_available: false },
+}
+
+cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
+sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
+
+apex_test {
+	name: "com.android.apogee",
+	manifest: "apogee_manifest.json",
+	androidManifest: "ApogeeAndroidManifest.xml",
+	file_contexts: ":com.android.apogee-file_contexts",
+	min_sdk_version: "29",
+	key: "com.android.apogee.key",
+	certificate: ":com.android.apogee.certificate",
+	updatable: false,
+	installable: false,
+	compressible: false,
+	native_shared_libs: [
+	    "native_shared_lib_1",
+	],
+	binaries: [
+		"cc_binary_1",
+		"sh_binary_2",
+	],
+	prebuilts: [
+	    "prebuilt_1",
+	],
+	bazel_module: { bp2build_available: false },
+}
+
+apex_key {
+	name: "com.google.android.apogee.key",
+	public_key: "com.google.android.apogee.avbpubkey",
+	private_key: "com.google.android.apogee.pem",
+	bazel_module: { bp2build_available: false },
+}
+
+android_app_certificate {
+	name: "com.google.android.apogee.certificate",
+	certificate: "com.google.android.apogee",
+	bazel_module: { bp2build_available: false },
+}
+
+override_apex {
+	name: "com.google.android.apogee",
+	base: ":com.android.apogee",
+	key: "com.google.android.apogee.key",
+	certificate: ":com.google.android.apogee.certificate",
+	prebuilts: [],
+	compressible: true,
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+				"android_manifest": `"ApogeeAndroidManifest.xml"`,
+				"base_apex_name":   `"com.android.apogee"`,
+				"binaries": `[
+        ":cc_binary_1",
+        ":sh_binary_2",
+    ]`,
+				"certificate":     `":com.google.android.apogee.certificate"`,
+				"file_contexts":   `":com.android.apogee-file_contexts"`,
+				"installable":     "False",
+				"key":             `":com.google.android.apogee.key"`,
+				"manifest":        `"apogee_manifest.json"`,
+				"min_sdk_version": `"29"`,
+				"native_shared_libs_32": `select({
+        "//build/bazel/platforms/arch:arm": [":native_shared_lib_1"],
+        "//build/bazel/platforms/arch:x86": [":native_shared_lib_1"],
+        "//conditions:default": [],
+    })`,
+				"native_shared_libs_64": `select({
+        "//build/bazel/platforms/arch:arm64": [":native_shared_lib_1"],
+        "//build/bazel/platforms/arch:x86_64": [":native_shared_lib_1"],
+        "//conditions:default": [],
+    })`,
+				"testonly":     "True",
+				"prebuilts":    `[]`,
+				"updatable":    "False",
+				"compressible": "True",
+			}),
+		}})
+}
+
 func TestApexBundleSimple_manifestIsEmpty_baseApexOverrideApexInDifferentAndroidBp(t *testing.T) {
 	runOverrideApexTestCase(t, Bp2buildTestCase{
 		Description:                "override_apex - manifest of base apex is empty, base apex and override_apex is in different Android.bp",
@@ -1446,3 +1566,25 @@
 			}),
 		}})
 }
+
+func TestApexBundleSimple_customCannedFsConfig(t *testing.T) {
+	runApexTestCase(t, Bp2buildTestCase{
+		Description:                "apex - custom canned_fs_config",
+		ModuleTypeUnderTest:        "apex",
+		ModuleTypeUnderTestFactory: apex.BundleFactory,
+		Filesystem:                 map[string]string{},
+		Blueprint: `
+apex {
+	name: "com.android.apogee",
+	canned_fs_config: "custom.canned_fs_config",
+	file_contexts: "file_contexts_file",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
+				"canned_fs_config": `"custom.canned_fs_config"`,
+				"file_contexts":    `"file_contexts_file"`,
+				"manifest":         `"apex_manifest.json"`,
+			}),
+		}})
+}
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 3eec439..fdda35b 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -53,7 +53,7 @@
     "@//build/bazel/product_config:__subpackages__",
 ])
 load(":soong.variables.bzl", _soong_variables = "variables")
-load("@//build/bazel/product_config:utils.bzl", "android_product")
+load("@//build/bazel/product_config:android_product.bzl", "android_product")
 
 android_product(
     name = "{PRODUCT}-{VARIANT}",
@@ -85,6 +85,11 @@
 		# 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",
+		"@soong_injection//product_config_platforms/products/aosp_arm_for_testing:aosp_arm_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_arm_for_testing:aosp_arm_for_testing_product_vars",
+		"@soong_injection//product_config_platforms/products/aosp_arm64_for_testing:aosp_arm64_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_arm64_for_testing:aosp_arm64_for_testing_product_vars",
+		"@soong_injection//product_config_platforms/products/aosp_x86_for_testing:aosp_x86_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_x86_for_testing:aosp_x86_for_testing_product_vars",
+		"@soong_injection//product_config_platforms/products/aosp_x86_64_for_testing:aosp_x86_64_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_x86_64_for_testing:aosp_x86_64_for_testing_product_vars",
+		"@soong_injection//product_config_platforms/products/aosp_arm64_for_testing_no_compression:aosp_arm64_for_testing_no_compression_constraint_value": "@soong_injection//product_config_platforms/products/aosp_arm64_for_testing_no_compression:aosp_arm64_for_testing_no_compression_product_vars",
 	}),
 )
 `)),
@@ -122,5 +127,42 @@
 `)),
 	}
 
+	// Add some products for testing
+	for _, arch := range []string{"arm", "arm64", "x86", "x86_64"} {
+		result = append(result, newFile(
+			fmt.Sprintf("product_config_platforms/products/aosp_%s_for_testing", arch),
+			"BUILD",
+			fmt.Sprintf(`
+package(default_visibility=[
+    "@soong_injection//product_config_platforms:__subpackages__",
+    "@//build/bazel/product_config:__subpackages__",
+])
+load("@//build/bazel/tests/products:aosp_%s.variables.bzl", _soong_variables = "variables")
+load("@//build/bazel/product_config:android_product.bzl", "android_product")
+
+android_product(
+    name = "aosp_%s_for_testing",
+    soong_variables = _soong_variables,
+)
+`, arch, arch)))
+	}
+	result = append(result, newFile(
+		"product_config_platforms/products/aosp_arm64_for_testing_no_compression",
+		"BUILD",
+		`
+package(default_visibility=[
+    "@soong_injection//product_config_platforms:__subpackages__",
+    "@//build/bazel/product_config:__subpackages__",
+])
+load("@bazel_skylib//lib:dicts.bzl", "dicts")
+load("@//build/bazel/tests/products:aosp_arm64.variables.bzl", _soong_variables = "variables")
+load("@//build/bazel/product_config:android_product.bzl", "android_product")
+
+android_product(
+    name = "aosp_arm64_for_testing_no_compression",
+    soong_variables = dicts.add(_soong_variables, {"CompressedApex": False}),
+)
+`))
+
 	return result, nil
 }
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index 335910c..40f705b 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -180,3 +180,100 @@
 		}
 	}
 }
+
+func TestAfdoEnabledWithMultiArchs(t *testing.T) {
+	t.Parallel()
+	bp := `
+	cc_library_shared {
+		name: "foo",
+		srcs: ["test.c"],
+		afdo: true,
+		compile_multilib: "both",
+	}
+`
+	result := android.GroupFixturePreparers(
+		prepareForCcTest,
+		android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", "TEST"),
+		android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", "TEST"),
+	).RunTestWithBp(t, bp)
+
+	fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
+	fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
+	if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
+		t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
+	}
+
+	fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
+	fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
+	if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
+		t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
+	}
+}
+
+func TestMultipleAfdoRDeps(t *testing.T) {
+	t.Parallel()
+	bp := `
+	cc_library_shared {
+		name: "libTest",
+		srcs: ["test.c"],
+		static_libs: ["libFoo"],
+		afdo: true,
+	}
+
+	cc_library_shared {
+		name: "libBar",
+		srcs: ["bar.c"],
+		static_libs: ["libFoo"],
+		afdo: true,
+	}
+
+	cc_library_static {
+		name: "libFoo",
+		srcs: ["foo.c"],
+	}
+	`
+
+	result := android.GroupFixturePreparers(
+		prepareForCcTest,
+		android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST"),
+		android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libBar.afdo", "TEST"),
+	).RunTestWithBp(t, bp)
+
+	expectedCFlagLibTest := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libTest.afdo"
+	expectedCFlagLibBar := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libBar.afdo"
+
+	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+	libTestAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+
+	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
+	libBarAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
+
+	// Check cFlags of afdo-enabled modules and the afdo-variant of their static deps
+	cFlags := libTest.Rule("cc").Args["cFlags"]
+	if !strings.Contains(cFlags, expectedCFlagLibTest) {
+		t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
+	}
+	cFlags = libBar.Rule("cc").Args["cFlags"]
+	if !strings.Contains(cFlags, expectedCFlagLibBar) {
+		t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+	}
+
+	cFlags = libTestAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
+	if !strings.Contains(cFlags, expectedCFlagLibTest) {
+		t.Errorf("Expected 'libTestAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
+	}
+
+	cFlags = libBarAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
+	if !strings.Contains(cFlags, expectedCFlagLibBar) {
+		t.Errorf("Expected 'libBarAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+	}
+
+	// Check dependency edges of static deps
+	if !hasDirectDep(result, libTest.Module(), libTestAfdoVariantOfLibFoo.Module()) {
+		t.Errorf("libTest missing dependency on afdo variant of libFoo")
+	}
+
+	if !hasDirectDep(result, libBar.Module(), libBarAfdoVariantOfLibFoo.Module()) {
+		t.Errorf("libBar missing dependency on afdo variant of libFoo")
+	}
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 4d703e4..5b2191a 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -239,7 +239,6 @@
 		"-Wno-error=deprecated",          // in external/googletest/googletest
 		// New warnings to be fixed after clang-r475365
 		"-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
-		"-Wno-error=incompatible-function-pointer-types",     // http://b/257101299
 		"-Wno-error=enum-constexpr-conversion",               // http://b/243964282
 	}
 
@@ -249,6 +248,7 @@
 		// http://b/191699019
 		"-Wno-format-insufficient-args",
 		"-Wno-sizeof-array-div",
+		"-Wno-incompatible-function-pointer-types",
 		"-Wno-unused-but-set-variable",
 		"-Wno-unused-but-set-parameter",
 		"-Wno-unqualified-std-cast-call",
@@ -313,6 +313,8 @@
 		"device/",
 		"vendor/",
 	}
+
+	VersionScriptFlagPrefix = "-Wl,--version-script,"
 )
 
 // BazelCcToolchainVars generates bzl file content containing variables for
@@ -401,6 +403,8 @@
 	exportedVars.ExportString("ExperimentalCStdVersion", ExperimentalCStdVersion)
 	exportedVars.ExportString("ExperimentalCppStdVersion", ExperimentalCppStdVersion)
 
+	exportedVars.ExportString("VersionScriptFlagPrefix", VersionScriptFlagPrefix)
+
 	// Everything in these lists is a crime against abstraction and dependency tracking.
 	// Do not add anything to this list.
 	commonGlobalIncludes := []string{
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 052832d..6a10e14 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -212,6 +212,14 @@
 	return LibclangRuntimeLibrary(t, "asan")
 }
 
+func AddressSanitizerStaticRuntimeLibrary(t Toolchain) string {
+	return LibclangRuntimeLibrary(t, "asan.static")
+}
+
+func AddressSanitizerCXXStaticRuntimeLibrary(t Toolchain) string {
+	return LibclangRuntimeLibrary(t, "asan_cxx.static")
+}
+
 func HWAddressSanitizerRuntimeLibrary(t Toolchain) string {
 	return LibclangRuntimeLibrary(t, "hwasan")
 }
diff --git a/cc/linker.go b/cc/linker.go
index e49b97d..257fe86 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -15,11 +15,12 @@
 package cc
 
 import (
-	"android/soong/android"
-	"android/soong/cc/config"
 	"fmt"
 	"path/filepath"
 
+	"android/soong/android"
+	"android/soong/cc/config"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -542,13 +543,13 @@
 				ctx.PropertyErrorf("version_script", "Not supported on Darwin")
 			} else {
 				flags.Local.LdFlags = append(flags.Local.LdFlags,
-					"-Wl,--version-script,"+versionScript.String())
+					config.VersionScriptFlagPrefix+versionScript.String())
 				flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
 
 				if linker.sanitize.isSanitizerEnabled(cfi) {
-					cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+					cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath+"/"+cfiExportsMapFilename)
 					flags.Local.LdFlags = append(flags.Local.LdFlags,
-						"-Wl,--version-script,"+cfiExportsMap.String())
+						config.VersionScriptFlagPrefix+cfiExportsMap.String())
 					flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
 				}
 			}
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index 51ec6b8..1d15cf8 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -15,15 +15,12 @@
 package cc
 
 import (
-	"fmt"
 	"strings"
 
 	"android/soong/android"
-	"android/soong/cc/config"
 )
 
 func init() {
-	android.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
 	android.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
 	android.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
 }
@@ -34,68 +31,6 @@
 // either (with the exception of the shared STLs, which are installed to the app's directory rather
 // than to the system image).
 
-func getNdkLibDir(ctx android.ModuleContext, toolchain config.Toolchain, version string) android.SourcePath {
-	suffix := ""
-	// Most 64-bit NDK prebuilts store libraries in "lib64", except for arm64 which is not a
-	// multilib toolchain and stores the libraries in "lib".
-	if toolchain.Is64Bit() && ctx.Arch().ArchType != android.Arm64 {
-		suffix = "64"
-	}
-	return android.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib%s",
-		version, toolchain.Name(), suffix))
-}
-
-func ndkPrebuiltModuleToPath(ctx android.ModuleContext, toolchain config.Toolchain,
-	ext string, version string) android.Path {
-
-	// NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
-	// We want to translate to just NAME.EXT
-	name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
-	dir := getNdkLibDir(ctx, toolchain, version)
-	return dir.Join(ctx, name+ext)
-}
-
-type ndkPrebuiltObjectLinker struct {
-	objectLinker
-}
-
-func (*ndkPrebuiltObjectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	// NDK objects can't have any dependencies
-	return deps
-}
-
-// ndk_prebuilt_object exports a precompiled ndk object file for linking
-// operations. Soong's module name format is ndk_<NAME>.o.<sdk_version> where
-// the object is located under
-// ./prebuilts/ndk/current/platforms/android-<sdk_version>/arch-$(HOST_ARCH)/usr/lib/<NAME>.o.
-func NdkPrebuiltObjectFactory() android.Module {
-	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	module.linker = &ndkPrebuiltObjectLinker{
-		objectLinker: objectLinker{
-			baseLinker: NewBaseLinker(nil),
-		},
-	}
-	module.Properties.AlwaysSdk = true
-	module.Properties.Sdk_version = StringPtr("current")
-	module.Properties.HideFromMake = true
-	return module.Init()
-}
-
-func (c *ndkPrebuiltObjectLinker) link(ctx ModuleContext, flags Flags,
-	deps PathDeps, objs Objects) android.Path {
-	// A null build step, but it sets up the output path.
-	if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
-		ctx.ModuleErrorf("NDK prebuilt objects must have an ndk_crt prefixed name")
-	}
-
-	return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion())
-}
-
-func (*ndkPrebuiltObjectLinker) availableFor(what string) bool {
-	// ndk prebuilt objects are available to everywhere
-	return true
-}
-
 type ndkPrebuiltStlLinker struct {
 	*libraryDecorator
 }
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 5b7ba43..4470f54 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,7 +16,6 @@
 
 import (
 	"path/filepath"
-	"strings"
 
 	"android/soong/android"
 	"android/soong/bazel"
@@ -208,12 +207,13 @@
 			})
 
 			// TODO(b/220898484): Mainline module sdk prebuilts of stub libraries use a stub
-			// library as their source and must not be installed, but libclang_rt.* libraries
-			// have stubs because they are LLNDK libraries, but use an implementation library
-			// as their source and need to be installed.  This discrepancy should be resolved
-			// without the prefix hack below.
-			if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() &&
-				!strings.HasPrefix(ctx.baseModuleName(), "libclang_rt.") {
+			// library as their source and must not be installed, but other prebuilts like
+			// libclang_rt.* libraries set `stubs` property because they are LLNDK libraries,
+			// but use an implementation library as their source and need to be installed.
+			// This discrepancy should be resolved without the prefix hack below.
+			isModuleSdkPrebuilts := android.HasAnyPrefix(ctx.ModuleDir(), []string{
+				"prebuilts/runtime/mainline/", "prebuilts/module_sdk/"})
+			if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() && isModuleSdkPrebuilts {
 				ctx.Module().MakeUninstallable()
 			}
 
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index e3ec9d5..0c79e55 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -670,11 +670,15 @@
 }
 
 func TestPrebuiltStubNoinstall(t *testing.T) {
-	testFunc := func(t *testing.T, bp string) {
+	testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
 		result := android.GroupFixturePreparers(
 			prepareForPrebuiltTest,
 			android.PrepareForTestWithMakevars,
-		).RunTestWithBp(t, bp)
+			android.FixtureMergeMockFs(fs),
+		).RunTest(t)
+
+		ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
+		android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
 
 		installRules := result.InstallMakeRulesForTesting(t)
 		var installedlibRule *android.InstallMakeRule
@@ -691,50 +695,83 @@
 			return
 		}
 
-		android.AssertStringListDoesNotContain(t,
-			"installedlib has install dependency on stub",
-			installedlibRule.Deps,
-			"out/target/product/test_device/system/lib/stublib.so")
-		android.AssertStringListDoesNotContain(t,
-			"installedlib has order-only install dependency on stub",
-			installedlibRule.OrderOnlyDeps,
-			"out/target/product/test_device/system/lib/stublib.so")
+		if expectLibfooOnSystemLib {
+			android.AssertStringListContains(t,
+				"installedlib doesn't have install dependency on libfoo impl",
+				installedlibRule.OrderOnlyDeps,
+				"out/target/product/test_device/system/lib/libfoo.so")
+		} else {
+			android.AssertStringListDoesNotContain(t,
+				"installedlib has install dependency on libfoo stub",
+				installedlibRule.Deps,
+				"out/target/product/test_device/system/lib/libfoo.so")
+			android.AssertStringListDoesNotContain(t,
+				"installedlib has order-only install dependency on libfoo stub",
+				installedlibRule.OrderOnlyDeps,
+				"out/target/product/test_device/system/lib/libfoo.so")
+		}
 	}
 
-	const prebuiltStublibBp = `
+	prebuiltLibfooBp := []byte(`
 		cc_prebuilt_library {
-			name: "stublib",
+			name: "libfoo",
 			prefer: true,
-			srcs: ["foo.so"],
+			srcs: ["libfoo.so"],
 			stubs: {
 				versions: ["1"],
 			},
 		}
-	`
+	`)
 
-	const installedlibBp = `
+	installedlibBp := []byte(`
 		cc_library {
 			name: "installedlib",
-			shared_libs: ["stublib"],
+			shared_libs: ["libfoo"],
 		}
-	`
+	`)
 
-	t.Run("prebuilt without source", func(t *testing.T) {
-		testFunc(t, prebuiltStublibBp+installedlibBp)
+	t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
+		testFunc(
+			t,
+			/*expectLibfooOnSystemLib=*/ false,
+			android.MockFS{
+				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+				"Android.bp": installedlibBp,
+			},
+		)
 	})
 
-	const disabledSourceStublibBp = `
+	disabledSourceLibfooBp := []byte(`
 		cc_library {
-			name: "stublib",
+			name: "libfoo",
 			enabled: false,
 			stubs: {
 				versions: ["1"],
 			},
 		}
-	`
+	`)
 
-	t.Run("prebuilt with disabled source", func(t *testing.T) {
-		testFunc(t, disabledSourceStublibBp+prebuiltStublibBp+installedlibBp)
+	t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
+		testFunc(
+			t,
+			/*expectLibfooOnSystemLib=*/ false,
+			android.MockFS{
+				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+				"impl/Android.bp": disabledSourceLibfooBp,
+				"Android.bp":      installedlibBp,
+			},
+		)
+	})
+
+	t.Run("prebuilt impl (with `stubs` property set): install", func(t *testing.T) {
+		testFunc(
+			t,
+			/*expectLibfooOnSystemLib=*/ true,
+			android.MockFS{
+				"impl/Android.bp": prebuiltLibfooBp,
+				"Android.bp":      installedlibBp,
+			},
+		)
 	})
 }
 
diff --git a/cc/sanitize.go b/cc/sanitize.go
index c899cc4..f19659c 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -62,14 +62,18 @@
 		"-fast-isel=false",
 	}
 
-	cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
-		"-fsanitize-ignorelist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
+	cfiBlocklistPath     = "external/compiler-rt/lib/cfi"
+	cfiBlocklistFilename = "cfi_blocklist.txt"
+	cfiCflags            = []string{"-flto", "-fsanitize-cfi-cross-dso",
+		"-fsanitize-ignorelist=" + cfiBlocklistPath + "/" + cfiBlocklistFilename}
 	// -flto and -fvisibility are required by clang when -fsanitize=cfi is
 	// used, but have no effect on assembly files
 	cfiAsflags = []string{"-flto", "-fvisibility=default"}
 	cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
 		"-Wl,-plugin-opt,O1"}
-	cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
+	cfiExportsMapPath      = "build/soong/cc/config"
+	cfiExportsMapFilename  = "cfi_exports.map"
+	cfiAssemblySupportFlag = "-fno-sanitize-cfi-canonical-jump-tables"
 
 	intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"}
 
@@ -388,6 +392,18 @@
 	exportedVars.ExportStringListStaticVariable("HostOnlySanitizeFlags", hostOnlySanitizeFlags)
 	exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
 
+	// Leave out "-flto" from the slices exported to bazel, as we will use the
+	// dedicated LTO feature for this
+	exportedVars.ExportStringList("CfiCFlags", cfiCflags[1:])
+	exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
+	exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[1:])
+
+	exportedVars.ExportString("CfiBlocklistPath", cfiBlocklistPath)
+	exportedVars.ExportString("CfiBlocklistFilename", cfiBlocklistFilename)
+	exportedVars.ExportString("CfiExportsMapPath", cfiExportsMapPath)
+	exportedVars.ExportString("CfiExportsMapFilename", cfiExportsMapFilename)
+	exportedVars.ExportString("CfiAssemblySupportFlag", cfiAssemblySupportFlag)
+
 	android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
 	android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
 }
@@ -810,7 +826,7 @@
 		flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
 		flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
 		if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) {
-			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-cfi-canonical-jump-tables")
+			flags.Local.CFlags = append(flags.Local.CFlags, cfiAssemblySupportFlag)
 		}
 		// Only append the default visibility flag if -fvisibility has not already been set
 		// to hidden.
@@ -1514,56 +1530,15 @@
 			diagSanitizers = sanitizers
 		}
 
-		// Determine the runtime library required
-		runtimeLibrary := ""
-		alwaysStaticRuntime := false
-		var extraStaticDeps []string
-		toolchain := c.toolchain(mctx)
-		if Bool(sanProps.Address) {
-			runtimeLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
-		} else if Bool(sanProps.Hwaddress) {
-			if c.staticBinary() {
-				runtimeLibrary = config.HWAddressSanitizerStaticLibrary(toolchain)
-				extraStaticDeps = []string{"libdl"}
-			} else {
-				runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
-			}
-		} else if Bool(sanProps.Thread) {
-			runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
-		} else if Bool(sanProps.Scudo) {
-			if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
-				runtimeLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
-			} else {
-				runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
-			}
-		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
-			Bool(sanProps.Fuzzer) ||
-			Bool(sanProps.Undefined) ||
-			Bool(sanProps.All_undefined) {
-			runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
-			if c.staticBinary() || toolchain.Musl() {
-				// Use a static runtime for static binaries.
-				// Also use a static runtime for musl to match
-				// what clang does for glibc.  Otherwise dlopening
-				// libraries that depend on libclang_rt.ubsan_standalone.so
-				// fails with:
-				// Error relocating ...: initial-exec TLS resolves to dynamic definition
-				runtimeLibrary += ".static"
-				alwaysStaticRuntime = true
-			}
-		}
-
-		addStaticDeps := func(deps ...string) {
+		addStaticDeps := func(dep string, hideSymbols bool) {
 			// If we're using snapshots, redirect to snapshot whenever possible
 			snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
-			for idx, dep := range deps {
-				if lib, ok := snapshot.StaticLibs[dep]; ok {
-					deps[idx] = lib
-				}
+			if lib, ok := snapshot.StaticLibs[dep]; ok {
+				dep = lib
 			}
 
 			// static executable gets static runtime libs
-			depTag := libraryDependencyTag{Kind: staticLibraryDependency, unexportedSymbols: true}
+			depTag := libraryDependencyTag{Kind: staticLibraryDependency, unexportedSymbols: hideSymbols}
 			variations := append(mctx.Target().Variations(),
 				blueprint.Variation{Mutator: "link", Variation: "static"})
 			if c.Device() {
@@ -1573,17 +1548,60 @@
 				variations = append(variations,
 					blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
 			}
-			mctx.AddFarVariationDependencies(variations, depTag, deps...)
-
+			mctx.AddFarVariationDependencies(variations, depTag, dep)
 		}
+
+		// Determine the runtime library required
+		runtimeSharedLibrary := ""
+		toolchain := c.toolchain(mctx)
+		if Bool(sanProps.Address) {
+			if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) {
+				// Use a static runtime for musl to match what clang does for glibc.
+				addStaticDeps(config.AddressSanitizerStaticRuntimeLibrary(toolchain), false)
+				addStaticDeps(config.AddressSanitizerCXXStaticRuntimeLibrary(toolchain), false)
+			} else {
+				runtimeSharedLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
+			}
+		} else if Bool(sanProps.Hwaddress) {
+			if c.staticBinary() {
+				addStaticDeps(config.HWAddressSanitizerStaticLibrary(toolchain), true)
+				addStaticDeps("libdl", false)
+			} else {
+				runtimeSharedLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
+			}
+		} else if Bool(sanProps.Thread) {
+			runtimeSharedLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
+		} else if Bool(sanProps.Scudo) {
+			if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
+				runtimeSharedLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
+			} else {
+				runtimeSharedLibrary = config.ScudoRuntimeLibrary(toolchain)
+			}
+		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
+			Bool(sanProps.Fuzzer) ||
+			Bool(sanProps.Undefined) ||
+			Bool(sanProps.All_undefined) {
+			if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) {
+				// Use a static runtime for static binaries.
+				// Also use a static runtime for musl to match
+				// what clang does for glibc.  Otherwise dlopening
+				// libraries that depend on libclang_rt.ubsan_standalone.so
+				// fails with:
+				// Error relocating ...: initial-exec TLS resolves to dynamic definition
+				addStaticDeps(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)+".static", true)
+			} else {
+				runtimeSharedLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
+			}
+		}
+
 		if enableMinimalRuntime(c.sanitize) || c.sanitize.Properties.MinimalRuntimeDep {
-			addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain))
+			addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), true)
 		}
 		if c.sanitize.Properties.BuiltinsDep {
-			addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain))
+			addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain), true)
 		}
 
-		if runtimeLibrary != "" && (toolchain.Bionic() || toolchain.Musl() || c.sanitize.Properties.UbsanRuntimeDep) {
+		if runtimeSharedLibrary != "" && (toolchain.Bionic() || toolchain.Musl() || c.sanitize.Properties.UbsanRuntimeDep) {
 			// UBSan is supported on non-bionic linux host builds as well
 
 			// Adding dependency to the runtime library. We are using *FarVariation*
@@ -1593,14 +1611,17 @@
 			//
 			// Note that by adding dependency with {static|shared}DepTag, the lib is
 			// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
-			if c.staticBinary() || alwaysStaticRuntime {
-				addStaticDeps(runtimeLibrary)
-				addStaticDeps(extraStaticDeps...)
+			if c.staticBinary() {
+				// Most sanitizers are either disabled for static binaries or have already
+				// handled the static binary case above through a direct call to addStaticDeps.
+				// If not, treat the runtime shared library as a static library and hope for
+				// the best.
+				addStaticDeps(runtimeSharedLibrary, true)
 			} else if !c.static() && !c.Header() {
 				// If we're using snapshots, redirect to snapshot whenever possible
 				snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
-				if lib, ok := snapshot.SharedLibs[runtimeLibrary]; ok {
-					runtimeLibrary = lib
+				if lib, ok := snapshot.SharedLibs[runtimeSharedLibrary]; ok {
+					runtimeSharedLibrary = lib
 				}
 
 				// Skip apex dependency check for sharedLibraryDependency
@@ -1624,7 +1645,7 @@
 					variations = append(variations,
 						blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
 				}
-				AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeLibrary, "", true)
+				AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeSharedLibrary, "", true)
 			}
 			// static lib does not have dependency to the runtime library. The
 			// dependency will be added to the executables or shared libs using
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 71c5a22..718186d 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -127,6 +127,7 @@
 const (
 	RUNTIME_LINKAGE_NONE   = expectedRuntimeLinkage(0)
 	RUNTIME_LINKAGE_SHARED = iota
+	RUNTIME_LINKAGE_STATIC
 )
 
 func TestAsan(t *testing.T) {
@@ -245,6 +246,8 @@
 		libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
 
 		libAsanSharedRuntime := result.ModuleForTests("libclang_rt.asan", sharedVariant)
+		libAsanStaticRuntime := result.ModuleForTests("libclang_rt.asan.static", staticVariant)
+		libAsanStaticCxxRuntime := result.ModuleForTests("libclang_rt.asan_cxx.static", staticVariant)
 
 		expectSharedLinkDep(t, ctx, binWithAsan, libShared)
 		expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
@@ -289,12 +292,38 @@
 			expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
 			expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
 		}
+
+		if runtimeLinkage == RUNTIME_LINKAGE_STATIC {
+			expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
+			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
+			expectStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
+			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
+			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)
+
+			expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
+			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
+			expectStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
+			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
+			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
+		} else {
+			expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
+			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
+			expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
+			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
+			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)
+
+			expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
+			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
+			expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
+			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
+			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
+		}
 	}
 
 	t.Run("host", func(t *testing.T) { check(t, buildOS, RUNTIME_LINKAGE_NONE, preparer) })
 	t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", RUNTIME_LINKAGE_SHARED, preparer) })
 	t.Run("host musl", func(t *testing.T) {
-		check(t, "linux_musl_x86_64", RUNTIME_LINKAGE_SHARED,
+		check(t, "linux_musl_x86_64", RUNTIME_LINKAGE_STATIC,
 			android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
 	})
 }
diff --git a/cc/testing.go b/cc/testing.go
index d38a57c..f78ea0f 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -40,7 +40,6 @@
 	ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
 	ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
 	ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
-	ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
 	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
 	ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory)
 }
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index d12a17b..79a5ce4 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -24,6 +24,7 @@
 	"time"
 
 	"android/soong/android"
+	"android/soong/android/allowlists"
 	"android/soong/bazel"
 	"android/soong/bp2build"
 	"android/soong/shared"
@@ -105,6 +106,7 @@
 	ctx.SetNameInterface(newNameResolver(configuration))
 	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
 	ctx.AddIncludeTags(configuration.IncludeTags()...)
+	ctx.AddSourceRootDirs(configuration.SourceRootDirs()...)
 	return ctx
 }
 
@@ -253,6 +255,29 @@
 	return ret
 }
 
+func writeNinjaHint(ctx *android.Context) error {
+	wantModules := make([]string, len(allowlists.HugeModulesMap))
+	i := 0
+	for k := range allowlists.HugeModulesMap {
+		wantModules[i] = k
+		i += 1
+	}
+	outputsMap := ctx.Context.GetOutputsFromModuleNames(wantModules)
+	var outputBuilder strings.Builder
+	for k, v := range allowlists.HugeModulesMap {
+		for _, output := range outputsMap[k] {
+			outputBuilder.WriteString(fmt.Sprintf("%s,%d\n", output, v))
+		}
+	}
+	weightListFile := filepath.Join(topDir, ctx.Config().OutDir(), ".ninja_weight_list")
+
+	err := os.WriteFile(weightListFile, []byte(outputBuilder.String()), 0644)
+	if err != nil {
+		return fmt.Errorf("could not write ninja weight list file %s", err)
+	}
+	return nil
+}
+
 func writeMetrics(configuration android.Config, eventHandler *metrics.EventHandler, metricsDir string) {
 	if len(metricsDir) < 1 {
 		fmt.Fprintf(os.Stderr, "\nMissing required env var for generating soong metrics: LOG_DIR\n")
@@ -413,6 +438,9 @@
 		} else {
 			finalOutputFile = runSoongOnlyBuild(ctx, extraNinjaDeps)
 		}
+		if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") {
+			writeNinjaHint(ctx)
+		}
 		writeMetrics(configuration, ctx.EventHandler, metricsDir)
 	}
 	writeUsedEnvironmentFile(configuration, finalOutputFile)
diff --git a/java/aar.go b/java/aar.go
index f162a17..47e6efa 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -721,8 +721,8 @@
 	return a.SdkVersion(ctx).ApiLevel
 }
 
-func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
-	return android.SdkSpecFrom(ctx, "")
+func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+	return android.SdkSpecFrom(ctx, "").ApiLevel
 }
 
 func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/java/base.go b/java/base.go
index 2d213a1..1bcff2e 100644
--- a/java/base.go
+++ b/java/base.go
@@ -490,7 +490,7 @@
 
 	sdkVersion    android.SdkSpec
 	minSdkVersion android.ApiLevel
-	maxSdkVersion android.SdkSpec
+	maxSdkVersion android.ApiLevel
 
 	sourceExtensions []string
 }
@@ -672,16 +672,20 @@
 	return j.SdkVersion(ctx).ApiLevel
 }
 
-func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
-	maxSdkVersion := proptools.StringDefault(j.deviceProperties.Max_sdk_version, "")
-	// SdkSpecFrom returns SdkSpecPrivate for this, which may be confusing.
-	// TODO(b/208456999): ideally MaxSdkVersion should be an ApiLevel and not SdkSpec.
-	return android.SdkSpecFrom(ctx, maxSdkVersion)
+func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+	if j.deviceProperties.Max_sdk_version != nil {
+		return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version)
+	}
+	// Default is PrivateApiLevel
+	return android.SdkSpecPrivate.ApiLevel
 }
 
-func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
-	replaceMaxSdkVersionPlaceholder := proptools.StringDefault(j.deviceProperties.Replace_max_sdk_version_placeholder, "")
-	return android.SdkSpecFrom(ctx, replaceMaxSdkVersionPlaceholder)
+func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+	if j.deviceProperties.Replace_max_sdk_version_placeholder != nil {
+		return android.ApiLevelFrom(ctx, *j.deviceProperties.Replace_max_sdk_version_placeholder)
+	}
+	// Default is PrivateApiLevel
+	return android.SdkSpecPrivate.ApiLevel
 }
 
 func (j *Module) MinSdkVersionString() string {
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 45e6175..bc9de50 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -136,11 +136,11 @@
 							jar.minSdkVersion = s.minSdkVersion.String()
 						}
 					}
-					if s.maxSdkVersion.ApiLevel.Specified() {
-						if s.maxSdkVersion.ApiLevel.IsCurrent() {
+					if s.maxSdkVersion.Specified() {
+						if s.maxSdkVersion.IsCurrent() {
 							jar.maxSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
 						} else {
-							jar.maxSdkVersion = s.maxSdkVersion.ApiLevel.String()
+							jar.maxSdkVersion = s.maxSdkVersion.String()
 						}
 					}
 				}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index c5a957e..dbe021d 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -252,8 +252,8 @@
 	return j.SdkVersion(ctx).ApiLevel
 }
 
-func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
-	return j.SdkVersion(ctx)
+func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+	return j.SdkVersion(ctx).ApiLevel
 }
 
 func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/java/java.go b/java/java.go
index 91193cc..499a6b6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1613,10 +1613,15 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 
+	hiddenAPI
+	dexer
+
 	properties JavaApiLibraryProperties
 
 	stubsSrcJar android.WritablePath
 	stubsJar    android.WritablePath
+	// .dex of stubs, used for hiddenapi processing
+	dexJarFile OptionalDexJarPath
 }
 
 type JavaApiLibraryProperties struct {
@@ -1808,6 +1813,20 @@
 		Inputs(staticLibs)
 	builder.Build("merge_zips", "merge jar files")
 
+	// compile stubs to .dex for hiddenapi processing
+	dexParams := &compileDexParams{
+		flags:         javaBuilderFlags{},
+		sdkVersion:    al.SdkVersion(ctx),
+		minSdkVersion: al.MinSdkVersion(ctx),
+		classesJar:    al.stubsJar,
+		jarName:       ctx.ModuleName() + ".jar",
+	}
+	dexOutputFile := al.dexer.compileDex(ctx, dexParams)
+	uncompressed := true
+	al.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), al.stubsJar, &uncompressed)
+	dexOutputFile = al.hiddenAPIEncodeDex(ctx, dexOutputFile)
+	al.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
+
 	ctx.Phony(ctx.ModuleName(), al.stubsJar)
 
 	ctx.SetProvider(JavaInfoProvider, JavaInfo{
@@ -1818,6 +1837,32 @@
 	})
 }
 
+func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {
+	return al.dexJarFile
+}
+
+func (al *ApiLibrary) DexJarInstallPath() android.Path {
+	return al.dexJarFile.Path()
+}
+
+func (al *ApiLibrary) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+	return nil
+}
+
+// java_api_library constitutes the sdk, and does not build against one
+func (al *ApiLibrary) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+	return android.SdkSpecNone
+}
+
+// java_api_library is always at "current". Return FutureApiLevel
+func (al *ApiLibrary) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+	return android.FutureApiLevel
+}
+
+// implement the following interfaces for hiddenapi processing
+var _ hiddenAPIModule = (*ApiLibrary)(nil)
+var _ UsesLibraryDependency = (*ApiLibrary)(nil)
+
 //
 // Java prebuilts
 //
@@ -1915,11 +1960,12 @@
 	return j.SdkVersion(ctx).ApiLevel
 }
 
-func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
+func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
 	if j.properties.Replace_max_sdk_version_placeholder != nil {
-		return android.SdkSpecFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
+		return android.ApiLevelFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
 	}
-	return android.SdkSpecFrom(ctx, "")
+	// Default is PrivateApiLevel
+	return android.SdkSpecPrivate.ApiLevel
 }
 
 func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/java/rro.go b/java/rro.go
index 6a9ad9a..53faca0 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -182,8 +182,8 @@
 	return r.SdkVersion(ctx).ApiLevel
 }
 
-func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
-	return android.SdkSpecFrom(ctx, "")
+func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+	return android.SdkSpecPrivate.ApiLevel
 }
 
 func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/rust/Android.bp b/rust/Android.bp
index 3fd68e5..b01a94a 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -42,6 +42,7 @@
         "toolchain_library.go",
     ],
     testSrcs: [
+        "afdo_test.go",
         "benchmark_test.go",
         "binary_test.go",
         "bindgen_test.go",
diff --git a/rust/afdo_test.go b/rust/afdo_test.go
new file mode 100644
index 0000000..fa20eef
--- /dev/null
+++ b/rust/afdo_test.go
@@ -0,0 +1,76 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+	"android/soong/android"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func TestAfdoEnabled(t *testing.T) {
+	bp := `
+	rust_binary {
+		name: "foo",
+		srcs: ["foo.rs"],
+		afdo: true,
+	}
+`
+	result := android.GroupFixturePreparers(
+		prepareForRustTest,
+		android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo.afdo", ""),
+		rustMockedFiles.AddToFixture(),
+	).RunTestWithBp(t, bp)
+
+	foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+
+	expectedCFlag := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo.afdo")
+
+	if !strings.Contains(foo.Args["rustcFlags"], expectedCFlag) {
+		t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"])
+	}
+}
+
+func TestAfdoEnabledWithMultiArchs(t *testing.T) {
+	bp := `
+	rust_binary {
+		name: "foo",
+		srcs: ["foo.rs"],
+		afdo: true,
+		compile_multilib: "both",
+	}
+`
+	result := android.GroupFixturePreparers(
+		prepareForRustTest,
+		android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", ""),
+		android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", ""),
+		rustMockedFiles.AddToFixture(),
+	).RunTestWithBp(t, bp)
+
+	fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc")
+	fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+
+	expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm.afdo")
+	expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm64.afdo")
+
+	if !strings.Contains(fooArm.Args["rustcFlags"], expectedCFlagArm) {
+		t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm, fooArm.Args["rustcFlags"])
+	}
+
+	if !strings.Contains(fooArm64.Args["rustcFlags"], expectedCFlagArm64) {
+		t.Errorf("Expected 'fooArm64' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm64, fooArm64.Args["rustcFlags"])
+	}
+}
diff --git a/rust/builder.go b/rust/builder.go
index 4b20e2b..09dfe02 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -218,6 +218,7 @@
 
 	var inputs android.Paths
 	var implicits android.Paths
+	var orderOnly android.Paths
 	var output buildOutput
 	var rustcFlags, linkFlags []string
 	var implicitOutputs android.WritablePaths
@@ -285,6 +286,8 @@
 	implicits = append(implicits, deps.CrtBegin...)
 	implicits = append(implicits, deps.CrtEnd...)
 
+	orderOnly = append(orderOnly, deps.SharedLibs...)
+
 	if len(deps.SrcDeps) > 0 {
 		moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
 		var outputs android.WritablePaths
@@ -331,6 +334,7 @@
 			ImplicitOutputs: nil,
 			Inputs:          inputs,
 			Implicits:       implicits,
+			OrderOnly:       orderOnly,
 			Args: map[string]string{
 				"rustcFlags":  strings.Join(rustcFlags, " "),
 				"libFlags":    strings.Join(libFlags, " "),
@@ -349,6 +353,7 @@
 		ImplicitOutputs: implicitOutputs,
 		Inputs:          inputs,
 		Implicits:       implicits,
+		OrderOnly:       orderOnly,
 		Args: map[string]string{
 			"rustcFlags": strings.Join(rustcFlags, " "),
 			"linkFlags":  strings.Join(linkFlags, " "),
@@ -367,6 +372,7 @@
 			Output:      kytheFile,
 			Inputs:      inputs,
 			Implicits:   implicits,
+			OrderOnly:   orderOnly,
 			Args: map[string]string{
 				"rustcFlags": strings.Join(rustcFlags, " "),
 				"linkFlags":  strings.Join(linkFlags, " "),
diff --git a/rust/rust.go b/rust/rust.go
index 018cdab..f85babc 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1413,7 +1413,7 @@
 
 	depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
 	depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
-	depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibDepFiles...)
+	depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibFiles...)
 	depPaths.SharedLibDeps = append(depPaths.SharedLibDeps, sharedLibDepFiles...)
 	depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
 	depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 3bcd58c..e8e5800 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -209,6 +209,10 @@
 // Test to make sure dependencies are being picked up correctly.
 func TestDepsTracking(t *testing.T) {
 	ctx := testRust(t, `
+		cc_library {
+			host_supported: true,
+			name: "cc_stubs_dep",
+		}
 		rust_ffi_host_static {
 			name: "libstatic",
 			srcs: ["foo.rs"],
@@ -235,6 +239,7 @@
 			crate_name: "rlib",
 			static_libs: ["libstatic"],
 			whole_static_libs: ["libwholestatic"],
+			shared_libs: ["cc_stubs_dep"],
 		}
 		rust_proc_macro {
 			name: "libpm",
@@ -279,6 +284,17 @@
 		t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.Args["rustcFlags"])
 	}
 
+	if !strings.Contains(rustc.Args["linkFlags"], "cc_stubs_dep.so") {
+		t.Errorf("shared cc_library not being passed to rustc linkFlags %#v", rustc.Args["linkFlags"])
+	}
+
+	if !android.SuffixInList(rustc.OrderOnly.Strings(), "cc_stubs_dep.so") {
+		t.Errorf("shared cc dep not being passed as order-only to rustc %#v", rustc.OrderOnly.Strings())
+	}
+
+	if !android.SuffixInList(rustc.Implicits.Strings(), "cc_stubs_dep.so.toc") {
+		t.Errorf("shared cc dep TOC not being passed as implicit to rustc %#v", rustc.Implicits.Strings())
+	}
 }
 
 func TestSourceProviderDeps(t *testing.T) {
@@ -331,7 +347,7 @@
 			source_stem: "bindings",
 			host_supported: true,
 			wrapper_src: "src/any.h",
-        }
+		}
 	`)
 
 	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Rule("rustc")
@@ -371,7 +387,6 @@
 	if !android.InList("libbindings.rlib-std", libprocmacroMod.Properties.AndroidMkRlibs) {
 		t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
 	}
-
 }
 
 func TestSourceProviderTargetMismatch(t *testing.T) {
diff --git a/tests/apex_cc_module_arch_variant_tests.sh b/tests/apex_cc_module_arch_variant_tests.sh
index b0cade1..1f5e003 100755
--- a/tests/apex_cc_module_arch_variant_tests.sh
+++ b/tests/apex_cc_module_arch_variant_tests.sh
@@ -56,12 +56,12 @@
 
 # Number of CppCompile actions with arch variant flag
 actions_with_arch_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
-  'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' | grep -c \'-march=$ARCH_VARIANT_CFLAG\')
+  'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c \'-march=$ARCH_VARIANT_CFLAG\')
 
 # Number of all CppCompile actions
 all_cppcompile_actions_num=0
 aquery_summary=$(call_bazel aquery --config=bp2build --config=ci --config=android --output=summary \
-  'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' \
+  'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' \
   | egrep -o '.*opt-ST.*: ([0-9]+)$' \
   | cut -d: -f2 -)
 
@@ -82,7 +82,7 @@
 then
   # Number of CppCompiler actions with cpu variant flag
   actions_with_cpu_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
-    'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' | grep -c "\-mcpu=$CPU_VARIANT_CFLAG")
+    'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c "\-mcpu=$CPU_VARIANT_CFLAG")
 
   if [ $actions_with_cpu_variant_num -eq $all_cppcompile_actions_num ]
   then
@@ -91,4 +91,4 @@
     echo "Error: number of CppCompile actions with cpu variant set: actual=$actions_with_cpu_variant_num, expected=$all_cppcompile_actions_num"
     exit 1
   fi
-fi
\ No newline at end of file
+fi
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index 5007078..e350323 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -66,10 +66,10 @@
 call_bazel build --config=bp2build --config=ci --config=android \
   //packages/modules/adb/apex:com.android.adbd \
   //system/timezone/apex:com.android.tzdata \
-  //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex
+  //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal
 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))"
+BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))"
 
 # # 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
diff --git a/tests/lib.sh b/tests/lib.sh
index 2bcb630..26608b8 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -91,6 +91,7 @@
   symlink_directory prebuilts/go
   symlink_directory prebuilts/build-tools
   symlink_directory prebuilts/clang/host
+  symlink_directory external/compiler-rt
   symlink_directory external/go-cmp
   symlink_directory external/golang-protobuf
   symlink_directory external/starlark-go
diff --git a/ui/build/config.go b/ui/build/config.go
index 7c226dd..a755d14 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -118,7 +118,8 @@
 
 	bazelForceEnabledModules string
 
-	includeTags []string
+	includeTags    []string
+	sourceRootDirs []string
 
 	// Data source to write ninja weight list
 	ninjaWeightListSource NinjaWeightListSource
@@ -133,6 +134,10 @@
 	NINJA_LOG
 	// ninja thinks every task has the same weight.
 	EVENLY_DISTRIBUTED
+	// ninja uses an external custom weight list
+	EXTERNAL_FILE
+	// ninja uses a prioritized module list from Soong
+	HINT_FROM_SOONG
 )
 const srcDirFileCheck = "build/soong/root.bp"
 
@@ -318,6 +323,10 @@
 
 	ret.totalRAM = detectTotalRAM(ctx)
 	ret.parseArgs(ctx, args)
+
+	if ret.ninjaWeightListSource == HINT_FROM_SOONG {
+		ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "true")
+	}
 	// Make sure OUT_DIR is set appropriately
 	if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
 		ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
@@ -553,6 +562,10 @@
 		return smpb.BuildConfig_NINJA_LOG.Enum()
 	case EVENLY_DISTRIBUTED:
 		return smpb.BuildConfig_EVENLY_DISTRIBUTED.Enum()
+	case EXTERNAL_FILE:
+		return smpb.BuildConfig_EXTERNAL_FILE.Enum()
+	case HINT_FROM_SOONG:
+		return smpb.BuildConfig_HINT_FROM_SOONG.Enum()
 	default:
 		return smpb.BuildConfig_NOT_USED.Enum()
 	}
@@ -836,6 +849,19 @@
 				c.ninjaWeightListSource = EVENLY_DISTRIBUTED
 			} else if source == "not_used" {
 				c.ninjaWeightListSource = NOT_USED
+			} else if source == "soong" {
+				c.ninjaWeightListSource = HINT_FROM_SOONG
+			} else if strings.HasPrefix(source, "file,") {
+				c.ninjaWeightListSource = EXTERNAL_FILE
+				filePath := strings.TrimPrefix(source, "file,")
+				err := validateNinjaWeightList(filePath)
+				if err != nil {
+					ctx.Fatalf("Malformed weight list from %s: %s", filePath, err)
+				}
+				_, err = copyFile(filePath, filepath.Join(c.OutDir(), ".ninja_weight_list"))
+				if err != nil {
+					ctx.Fatalf("Error to copy ninja weight list from %s: %s", filePath, err)
+				}
 			} else {
 				ctx.Fatalf("unknown option for ninja_weight_source: %s", source)
 			}
@@ -911,6 +937,25 @@
 	}
 }
 
+func validateNinjaWeightList(weightListFilePath string) (err error) {
+	data, err := os.ReadFile(weightListFilePath)
+	if err != nil {
+		return
+	}
+	lines := strings.Split(strings.TrimSpace(string(data)), "\n")
+	for _, line := range lines {
+		fields := strings.Split(line, ",")
+		if len(fields) != 2 {
+			return fmt.Errorf("wrong format, each line should have two fields, but '%s'", line)
+		}
+		_, err = strconv.Atoi(fields[1])
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
 func (c *configImpl) configureLocale(ctx Context) {
 	cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
 	output, err := cmd.Output()
@@ -1197,6 +1242,14 @@
 	return c.parallel
 }
 
+func (c *configImpl) GetSourceRootDirs() []string {
+	return c.sourceRootDirs
+}
+
+func (c *configImpl) SetSourceRootDirs(i []string) {
+	c.sourceRootDirs = i
+}
+
 func (c *configImpl) GetIncludeTags() []string {
 	return c.includeTags
 }
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index a9c298f..efe7478 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -148,6 +148,7 @@
 	"PLATFORM_VERSION_CODENAME",
 	"PLATFORM_VERSION",
 	"PRODUCT_INCLUDE_TAGS",
+	"PRODUCT_SOURCE_ROOT_DIRS",
 	"TARGET_PRODUCT",
 	"TARGET_BUILD_VARIANT",
 	"TARGET_BUILD_APPS",
@@ -299,4 +300,5 @@
 	config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
 	config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(makeVars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
 	config.SetIncludeTags(strings.Fields(makeVars["PRODUCT_INCLUDE_TAGS"]))
+	config.SetSourceRootDirs(strings.Fields(makeVars["PRODUCT_SOURCE_ROOT_DIRS"]))
 }
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 4734494..5d56531 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -30,8 +30,9 @@
 
 const (
 	// File containing the environment state when ninja is executed
-	ninjaEnvFileName = "ninja.environment"
-	ninjaLogFileName = ".ninja_log"
+	ninjaEnvFileName        = "ninja.environment"
+	ninjaLogFileName        = ".ninja_log"
+	ninjaWeightListFileName = ".ninja_weight_list"
 )
 
 func useNinjaBuildLog(ctx Context, config Config, cmd *Cmd) {
@@ -66,7 +67,7 @@
 		ctx.Verbosef("There is an error during reading ninja log, so ninja will use empty weight list: %s", err)
 	}
 
-	weightListFile := filepath.Join(config.OutDir(), ".ninja_weight_list")
+	weightListFile := filepath.Join(config.OutDir(), ninjaWeightListFileName)
 
 	err = os.WriteFile(weightListFile, []byte(outputBuilder.String()), 0644)
 	if err == nil {
@@ -134,6 +135,12 @@
 	case EVENLY_DISTRIBUTED:
 		// pass empty weight list means ninja considers every tasks's weight as 1(default value).
 		cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null")
+	case EXTERNAL_FILE:
+		fallthrough
+	case HINT_FROM_SOONG:
+		// The weight list is already copied/generated.
+		ninjaWeightListPath := filepath.Join(config.OutDir(), ninjaWeightListFileName)
+		cmd.Args = append(cmd.Args, "-o", "usesweightlist="+ninjaWeightListPath)
 	}
 
 	// Allow both NINJA_ARGS and NINJA_EXTRA_ARGS, since both have been
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 1c6da7e..9287731 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -416,6 +416,7 @@
 
 	blueprintCtx := blueprint.NewContext()
 	blueprintCtx.AddIncludeTags(config.GetIncludeTags()...)
+	blueprintCtx.AddSourceRootDirs(config.GetSourceRootDirs()...)
 	blueprintCtx.SetIgnoreUnknownModuleTypes(true)
 	blueprintConfig := BlueprintConfig{
 		soongOutDir: config.SoongOutDir(),
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 4ad4a7b..32d4dc0 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -14,7 +14,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.28.0
+// 	protoc-gen-go v1.30.0
 // 	protoc        v3.21.7
 // source: metrics.proto
 
@@ -164,6 +164,8 @@
 	BuildConfig_NOT_USED           BuildConfig_NinjaWeightListSource = 0
 	BuildConfig_NINJA_LOG          BuildConfig_NinjaWeightListSource = 1
 	BuildConfig_EVENLY_DISTRIBUTED BuildConfig_NinjaWeightListSource = 2
+	BuildConfig_EXTERNAL_FILE      BuildConfig_NinjaWeightListSource = 3
+	BuildConfig_HINT_FROM_SOONG    BuildConfig_NinjaWeightListSource = 4
 )
 
 // Enum value maps for BuildConfig_NinjaWeightListSource.
@@ -172,11 +174,15 @@
 		0: "NOT_USED",
 		1: "NINJA_LOG",
 		2: "EVENLY_DISTRIBUTED",
+		3: "EXTERNAL_FILE",
+		4: "HINT_FROM_SOONG",
 	}
 	BuildConfig_NinjaWeightListSource_value = map[string]int32{
 		"NOT_USED":           0,
 		"NINJA_LOG":          1,
 		"EVENLY_DISTRIBUTED": 2,
+		"EXTERNAL_FILE":      3,
+		"HINT_FROM_SOONG":    4,
 	}
 )
 
@@ -388,7 +394,7 @@
 	// Deprecated because instead of embedding in a MetricsBase, we keep
 	// SoongBuildMetrics in its own file
 	//
-	// Deprecated: Do not use.
+	// Deprecated: Marked as deprecated in metrics.proto.
 	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.
@@ -603,7 +609,7 @@
 	return nil
 }
 
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in metrics.proto.
 func (x *MetricsBase) GetSoongBuildMetrics() *SoongBuildMetrics {
 	if x != nil {
 		return x.SoongBuildMetrics
@@ -709,6 +715,8 @@
 	// NOT_USED - ninja doesn't use weight list.
 	// NINJA_LOG - ninja uses weight list based on previous builds by ninja log
 	// EVENLY_DISTRIBUTED - ninja thinks every task has the same weight.
+	// EXTERNAL_FILE - ninja uses an external custom weight list
+	// HINT_FROM_SOONG - ninja uses a prioritized module list from Soong
 	NinjaWeightListSource *BuildConfig_NinjaWeightListSource `protobuf:"varint,8,opt,name=ninja_weight_list_source,json=ninjaWeightListSource,enum=soong_build_metrics.BuildConfig_NinjaWeightListSource,def=0" json:"ninja_weight_list_source,omitempty"`
 }
 
@@ -879,7 +887,7 @@
 	RealTime *uint64 `protobuf:"varint,4,opt,name=real_time,json=realTime" json:"real_time,omitempty"`
 	// The number of MB for memory use (deprecated as it is too generic).
 	//
-	// Deprecated: Do not use.
+	// Deprecated: Marked as deprecated in metrics.proto.
 	MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"`
 	// The resource information of each executed process.
 	ProcessesResourceInfo []*ProcessResourceInfo `protobuf:"bytes,6,rep,name=processes_resource_info,json=processesResourceInfo" json:"processes_resource_info,omitempty"`
@@ -950,7 +958,7 @@
 	return 0
 }
 
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in metrics.proto.
 func (x *PerfInfo) GetMemoryUse() uint64 {
 	if x != nil && x.MemoryUse != nil {
 		return *x.MemoryUse
@@ -1772,7 +1780,7 @@
 	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, 0xe2, 0x03, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+	0x04, 0x22, 0x8a, 0x04, 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,
@@ -1797,165 +1805,167 @@
 	0x67, 0x2e, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73,
 	0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45,
 	0x44, 0x52, 0x15, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69,
-	0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x4c, 0x0a, 0x15, 0x4e, 0x69, 0x6e, 0x6a,
+	0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x74, 0x0a, 0x15, 0x4e, 0x69, 0x6e, 0x6a,
 	0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63,
 	0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x10, 0x00, 0x12,
 	0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x4e, 0x4a, 0x41, 0x5f, 0x4c, 0x4f, 0x47, 0x10, 0x01, 0x12, 0x16,
 	0x0a, 0x12, 0x45, 0x56, 0x45, 0x4e, 0x4c, 0x59, 0x5f, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42,
-	0x55, 0x54, 0x45, 0x44, 0x10, 0x02, 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,
+	0x55, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e,
+	0x41, 0x4c, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x48, 0x49, 0x4e,
+	0x54, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x04, 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, 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, 0x22, 0x8a, 0x02, 0x0a, 0x10,
-	0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f,
-	0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65,
-	0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65,
-	0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
-	0x12, 0x39, 0x0a, 0x19, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74,
-	0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74,
-	0x68, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x63,
-	0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03,
-	0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
-	0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f,
-	0x52, 0x0c, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48,
-	0x0a, 0x11, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6a,
-	0x6f, 0x62, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
-	0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
-	0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e,
-	0x6e, 0x69, 0x6e, 0x67, 0x4a, 0x6f, 0x62, 0x73, 0x22, 0x62, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x49,
-	0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74,
-	0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
-	0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63,
-	0x72, 0x6f, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6a, 0x6f, 0x62, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72,
-	0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6a, 0x6f,
-	0x62, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 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,
+	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, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+	0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70,
+	0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69,
+	0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x72, 0x69, 0x74,
+	0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d,
+	0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x72, 0x69,
+	0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63,
+	0x72, 0x6f, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f,
+	0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f,
+	0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+	0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63,
+	0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72,
+	0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+	0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+	0x0f, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x4a, 0x6f, 0x62, 0x73,
+	0x22, 0x62, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65,
+	0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72,
+	0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65,
+	0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6a,
+	0x6f, 0x62, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 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 5e9a055..6db83e9 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -138,6 +138,8 @@
     NOT_USED = 0;
     NINJA_LOG = 1;
     EVENLY_DISTRIBUTED = 2;
+    EXTERNAL_FILE = 3;
+    HINT_FROM_SOONG = 4;
   }
 
   optional bool use_goma = 1;
@@ -163,6 +165,8 @@
   // NOT_USED - ninja doesn't use weight list.
   // NINJA_LOG - ninja uses weight list based on previous builds by ninja log
   // EVENLY_DISTRIBUTED - ninja thinks every task has the same weight.
+  // EXTERNAL_FILE - ninja uses an external custom weight list
+  // HINT_FROM_SOONG - ninja uses a prioritized module list from Soong
   optional NinjaWeightListSource ninja_weight_list_source = 8 [default = NOT_USED];
 }