Merge "Do not check ssh credentials when running gcertstatus"
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
new file mode 100644
index 0000000..d19b543
--- /dev/null
+++ b/aconfig/Android.bp
@@ -0,0 +1,32 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+    name: "soong-aconfig",
+    pkgPath: "android/soong/aconfig",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "sbox_proto",
+        "soong",
+        "soong-android",
+        "soong-bazel",
+        "soong-android",
+        "soong-java",
+    ],
+    srcs: [
+        "aconfig_declarations.go",
+        "aconfig_values.go",
+        "aconfig_value_set.go",
+        "init.go",
+        "java_aconfig_library.go",
+        "testing.go",
+    ],
+    testSrcs: [
+        "aconfig_declarations_test.go",
+        "aconfig_values_test.go",
+        "aconfig_value_set_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/device_config/device_config_definitions.go b/aconfig/aconfig_declarations.go
similarity index 62%
rename from device_config/device_config_definitions.go
rename to aconfig/aconfig_declarations.go
index ab2e4f7..007d529 100644
--- a/device_config/device_config_definitions.go
+++ b/aconfig/aconfig_declarations.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"android/soong/android"
@@ -21,27 +21,27 @@
 	"strings"
 )
 
-type DefinitionsModule struct {
+type DeclarationsModule struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
 
-	// Properties for "device_config_definitions"
+	// Properties for "aconfig_declarations"
 	properties struct {
 		// aconfig files, relative to this Android.bp file
 		Srcs []string `android:"path"`
 
-		// Release config flag namespace
-		Namespace string
+		// Release config flag package
+		Package string
 
-		// Values from TARGET_RELEASE / RELEASE_DEVICE_CONFIG_VALUE_SETS
+		// Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS
 		Values []string `blueprint:"mutated"`
 	}
 
 	intermediatePath android.WritablePath
 }
 
-func DefinitionsFactory() android.Module {
-	module := &DefinitionsModule{}
+func DeclarationsFactory() android.Module {
+	module := &DeclarationsModule{}
 
 	android.InitAndroidModule(module)
 	android.InitDefaultableModule(module)
@@ -58,24 +58,24 @@
 
 var implicitValuesTag = implicitValuesTagType{}
 
-func (module *DefinitionsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
 	// Validate Properties
 	if len(module.properties.Srcs) == 0 {
 		ctx.PropertyErrorf("srcs", "missing source files")
 		return
 	}
-	if len(module.properties.Namespace) == 0 {
-		ctx.PropertyErrorf("namespace", "missing namespace property")
+	if len(module.properties.Package) == 0 {
+		ctx.PropertyErrorf("package", "missing package property")
 	}
 
-	// Add a dependency on the device_config_value_sets defined in
-	// RELEASE_DEVICE_CONFIG_VALUE_SETS, and add any device_config_values that
-	// match our namespace.
-	valuesFromConfig := ctx.Config().ReleaseDeviceConfigValueSets()
+	// Add a dependency on the aconfig_value_sets defined in
+	// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
+	// match our package.
+	valuesFromConfig := ctx.Config().ReleaseAconfigValueSets()
 	ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
 }
 
-func (module *DefinitionsModule) OutputFiles(tag string) (android.Paths, error) {
+func (module *DeclarationsModule) OutputFiles(tag string) (android.Paths, error) {
 	switch tag {
 	case "":
 		// The default output of this module is the intermediates format, which is
@@ -83,7 +83,7 @@
 		// correctly.
 		return []android.Path{module.intermediatePath}, nil
 	default:
-		return nil, fmt.Errorf("unsupported device_config_definitions module reference tag %q", tag)
+		return nil, fmt.Errorf("unsupported aconfig_declarations module reference tag %q", tag)
 	}
 }
 
@@ -96,23 +96,23 @@
 	return sb.String()
 }
 
-// Provider published by device_config_value_set
-type definitionsProviderData struct {
-	namespace        string
-	intermediatePath android.WritablePath
+// Provider published by aconfig_value_set
+type declarationsProviderData struct {
+	Package          string
+	IntermediatePath android.WritablePath
 }
 
-var definitionsProviderKey = blueprint.NewProvider(definitionsProviderData{})
+var declarationsProviderKey = blueprint.NewProvider(declarationsProviderData{})
 
-func (module *DefinitionsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// Get the values that came from the global RELEASE_DEVICE_CONFIG_VALUE_SETS flag
+func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		if !ctx.OtherModuleHasProvider(dep, valueSetProviderKey) {
 			// Other modules get injected as dependencies too, for example the license modules
 			return
 		}
 		depData := ctx.OtherModuleProvider(dep, valueSetProviderKey).(valueSetProviderData)
-		valuesFiles, ok := depData.AvailableNamespaces[module.properties.Namespace]
+		valuesFiles, ok := depData.AvailablePackages[module.properties.Package]
 		if ok {
 			for _, path := range valuesFiles {
 				module.properties.Values = append(module.properties.Values, path.String())
@@ -127,17 +127,17 @@
 		Rule:        aconfigRule,
 		Inputs:      inputFiles,
 		Output:      intermediatePath,
-		Description: "device_config_definitions",
+		Description: "aconfig_declarations",
 		Args: map[string]string{
 			"release_version": ctx.Config().ReleaseVersion(),
-			"namespace":       module.properties.Namespace,
+			"package":         module.properties.Package,
 			"values":          joinAndPrefix(" --values ", module.properties.Values),
 		},
 	})
 
-	ctx.SetProvider(definitionsProviderKey, definitionsProviderData{
-		namespace:        module.properties.Namespace,
-		intermediatePath: intermediatePath,
+	ctx.SetProvider(declarationsProviderKey, declarationsProviderData{
+		Package:          module.properties.Package,
+		IntermediatePath: intermediatePath,
 	})
 
 }
diff --git a/device_config/device_config_definitions_test.go b/aconfig/aconfig_declarations_test.go
similarity index 69%
rename from device_config/device_config_definitions_test.go
rename to aconfig/aconfig_declarations_test.go
index 6bc6eaa..e14ca38 100644
--- a/device_config/device_config_definitions_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"strings"
@@ -21,22 +21,22 @@
 	"android/soong/android"
 )
 
-func TestDeviceConfigDefinitions(t *testing.T) {
+func TestAconfigDeclarations(t *testing.T) {
 	bp := `
-		device_config_definitions {
+		aconfig_declarations {
 			name: "module_name",
-			namespace: "com.example.package",
+			package: "com.example.package",
 			srcs: ["foo.aconfig"],
 		}
 	`
 	result := runTest(t, android.FixtureExpectsNoErrors, bp)
 
-	module := result.ModuleForTests("module_name", "").Module().(*DefinitionsModule)
+	module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
 
 	// Check that the provider has the right contents
-	depData := result.ModuleProvider(module, definitionsProviderKey).(definitionsProviderData)
-	android.AssertStringEquals(t, "namespace", depData.namespace, "com.example.package")
-	if !strings.HasSuffix(depData.intermediatePath.String(), "/intermediate.pb") {
-		t.Errorf("Missing intermediates path in provider: %s", depData.intermediatePath.String())
+	depData := result.ModuleProvider(module, declarationsProviderKey).(declarationsProviderData)
+	android.AssertStringEquals(t, "package", depData.Package, "com.example.package")
+	if !strings.HasSuffix(depData.IntermediatePath.String(), "/intermediate.pb") {
+		t.Errorf("Missing intermediates path in provider: %s", depData.IntermediatePath.String())
 	}
 }
diff --git a/device_config/device_config_value_set.go b/aconfig/aconfig_value_set.go
similarity index 76%
rename from device_config/device_config_value_set.go
rename to aconfig/aconfig_value_set.go
index e406d20..252908f 100644
--- a/device_config/device_config_value_set.go
+++ b/aconfig/aconfig_value_set.go
@@ -12,20 +12,20 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"android/soong/android"
 	"github.com/google/blueprint"
 )
 
-// Properties for "device_config_value_set"
+// Properties for "aconfig_value_set"
 type ValueSetModule struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
 
 	properties struct {
-		// device_config_values modules
+		// aconfig_values modules
 		Values []string
 	}
 }
@@ -49,11 +49,11 @@
 
 var valueSetTag = valueSetType{}
 
-// Provider published by device_config_value_set
+// Provider published by aconfig_value_set
 type valueSetProviderData struct {
-	// The namespace of each of the
-	// (map of namespace --> device_config_module)
-	AvailableNamespaces map[string]android.Paths
+	// The package of each of the
+	// (map of package --> aconfig_module)
+	AvailablePackages map[string]android.Paths
 }
 
 var valueSetProviderKey = blueprint.NewProvider(valueSetProviderData{})
@@ -63,17 +63,17 @@
 	for _, dep := range deps {
 		_, ok := dep.(*ValuesModule)
 		if !ok {
-			ctx.PropertyErrorf("values", "values must be a device_config_values module")
+			ctx.PropertyErrorf("values", "values must be a aconfig_values module")
 			return
 		}
 	}
 }
 
 func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// Accumulate the namespaces of the values modules listed, and set that as an
-	// valueSetProviderKey provider that device_config modules can read and use
+	// Accumulate the packages of the values modules listed, and set that as an
+	// valueSetProviderKey provider that aconfig modules can read and use
 	// to append values to their aconfig actions.
-	namespaces := make(map[string]android.Paths)
+	packages := make(map[string]android.Paths)
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		if !ctx.OtherModuleHasProvider(dep, valuesProviderKey) {
 			// Other modules get injected as dependencies too, for example the license modules
@@ -83,10 +83,10 @@
 
 		srcs := make([]android.Path, len(depData.Values))
 		copy(srcs, depData.Values)
-		namespaces[depData.Namespace] = srcs
+		packages[depData.Package] = srcs
 
 	})
 	ctx.SetProvider(valueSetProviderKey, valueSetProviderData{
-		AvailableNamespaces: namespaces,
+		AvailablePackages: packages,
 	})
 }
diff --git a/device_config/device_config_value_set_test.go b/aconfig/aconfig_value_set_test.go
similarity index 78%
rename from device_config/device_config_value_set_test.go
rename to aconfig/aconfig_value_set_test.go
index f9e7c38..9127872 100644
--- a/device_config/device_config_value_set_test.go
+++ b/aconfig/aconfig_value_set_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"testing"
@@ -20,15 +20,15 @@
 	"android/soong/android"
 )
 
-func TestDeviceConfigValueSet(t *testing.T) {
+func TestAconfigValueSet(t *testing.T) {
 	bp := `
-				device_config_values {
+				aconfig_values {
 					name: "one",
 					srcs: [ "blah.aconfig_values" ],
-					namespace: "foo.namespace"
+					package: "foo.package"
 				}
 
-				device_config_value_set {
+				aconfig_value_set {
 					name: "module_name",
           values: [ "one" ],
 				}
@@ -39,5 +39,5 @@
 
 	// Check that the provider has the right contents
 	depData := result.ModuleProvider(module, valueSetProviderKey).(valueSetProviderData)
-	android.AssertStringEquals(t, "AvailableNamespaces", "blah.aconfig_values", depData.AvailableNamespaces["foo.namespace"][0].String())
+	android.AssertStringEquals(t, "AvailablePackages", "blah.aconfig_values", depData.AvailablePackages["foo.package"][0].String())
 }
diff --git a/device_config/device_config_values.go b/aconfig/aconfig_values.go
similarity index 73%
rename from device_config/device_config_values.go
rename to aconfig/aconfig_values.go
index 110f12a..91f1c90 100644
--- a/device_config/device_config_values.go
+++ b/aconfig/aconfig_values.go
@@ -12,14 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"android/soong/android"
 	"github.com/google/blueprint"
 )
 
-// Properties for "device_config_value"
+// Properties for "aconfig_value"
 type ValuesModule struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
@@ -28,8 +28,8 @@
 		// aconfig files, relative to this Android.bp file
 		Srcs []string `android:"path"`
 
-		// Release config flag namespace
-		Namespace string
+		// Release config flag package
+		Package string
 	}
 }
 
@@ -45,10 +45,10 @@
 	return module
 }
 
-// Provider published by device_config_value_set
+// Provider published by aconfig_value_set
 type valuesProviderData struct {
-	// The namespace that this values module values
-	Namespace string
+	// The package that this values module values
+	Package string
 
 	// The values aconfig files, relative to the root of the tree
 	Values android.Paths
@@ -57,14 +57,14 @@
 var valuesProviderKey = blueprint.NewProvider(valuesProviderData{})
 
 func (module *ValuesModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	if len(module.properties.Namespace) == 0 {
-		ctx.PropertyErrorf("namespace", "missing namespace property")
+	if len(module.properties.Package) == 0 {
+		ctx.PropertyErrorf("package", "missing package property")
 	}
 
-	// Provide the our source files list to the device_config_value_set as a list of files
+	// Provide the our source files list to the aconfig_value_set as a list of files
 	providerData := valuesProviderData{
-		Namespace: module.properties.Namespace,
-		Values:    android.PathsForModuleSrc(ctx, module.properties.Srcs),
+		Package: module.properties.Package,
+		Values:  android.PathsForModuleSrc(ctx, module.properties.Srcs),
 	}
 	ctx.SetProvider(valuesProviderKey, providerData)
 }
diff --git a/device_config/device_config_values_test.go b/aconfig/aconfig_values_test.go
similarity index 83%
rename from device_config/device_config_values_test.go
rename to aconfig/aconfig_values_test.go
index 64c57eb..ab457f0 100644
--- a/device_config/device_config_values_test.go
+++ b/aconfig/aconfig_values_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"testing"
@@ -20,12 +20,12 @@
 	"android/soong/android"
 )
 
-func TestDeviceConfigValues(t *testing.T) {
+func TestAconfigValues(t *testing.T) {
 	bp := `
-				device_config_values {
+				aconfig_values {
 					name: "module_name",
 					srcs: [ "blah.aconfig_values" ],
-					namespace: "foo.namespace"
+					package: "foo.package"
 				}
 			`
 	result := runTest(t, android.FixtureExpectsNoErrors, bp)
@@ -34,6 +34,6 @@
 
 	// Check that the provider has the right contents
 	depData := result.ModuleProvider(module, valuesProviderKey).(valuesProviderData)
-	android.AssertStringEquals(t, "namespace", "foo.namespace", depData.Namespace)
+	android.AssertStringEquals(t, "package", "foo.package", depData.Package)
 	android.AssertPathsEndWith(t, "srcs", []string{"blah.aconfig_values"}, depData.Values)
 }
diff --git a/device_config/init.go b/aconfig/init.go
similarity index 74%
rename from device_config/init.go
rename to aconfig/init.go
index 04bbab6..6b433c9 100644
--- a/device_config/init.go
+++ b/aconfig/init.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"android/soong/android"
@@ -20,13 +20,13 @@
 )
 
 var (
-	pctx = android.NewPackageContext("android/soong/device_config")
+	pctx = android.NewPackageContext("android/soong/aconfig")
 
-	// For device_config_definitions: Generate cache file
+	// For aconfig_declarations: Generate cache file
 	aconfigRule = pctx.AndroidStaticRule("aconfig",
 		blueprint.RuleParams{
 			Command: `${aconfig} create-cache` +
-				` --package ${namespace}` +
+				` --package ${package}` +
 				` --declarations ${in}` +
 				` ${values}` +
 				` --cache ${out}.tmp` +
@@ -36,9 +36,9 @@
 				"${aconfig}",
 			},
 			Restat: true,
-		}, "release_version", "namespace", "values")
+		}, "release_version", "package", "values")
 
-	// For java_device_config_definitions_library: Generate java file
+	// For java_aconfig_library: Generate java file
 	srcJarRule = pctx.AndroidStaticRule("aconfig_srcjar",
 		blueprint.RuleParams{
 			Command: `rm -rf ${out}.tmp` +
@@ -63,8 +63,8 @@
 }
 
 func registerBuildComponents(ctx android.RegistrationContext) {
-	ctx.RegisterModuleType("device_config_definitions", DefinitionsFactory)
-	ctx.RegisterModuleType("device_config_values", ValuesFactory)
-	ctx.RegisterModuleType("device_config_value_set", ValueSetFactory)
-	ctx.RegisterModuleType("java_device_config_definitions_library", JavaDefinitionsLibraryFactory)
+	ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory)
+	ctx.RegisterModuleType("aconfig_values", ValuesFactory)
+	ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
+	ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
 }
diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go
new file mode 100644
index 0000000..0eeb14f
--- /dev/null
+++ b/aconfig/java_aconfig_library.go
@@ -0,0 +1,71 @@
+// 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 aconfig
+
+import (
+	"android/soong/android"
+	"android/soong/java"
+	"fmt"
+	"github.com/google/blueprint"
+)
+
+type declarationsTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+var declarationsTag = declarationsTagType{}
+
+type JavaAconfigDeclarationsLibraryProperties struct {
+	// name of the aconfig_declarations module to generate a library for
+	Aconfig_declarations string
+}
+
+type JavaAconfigDeclarationsLibraryCallbacks struct {
+	properties JavaAconfigDeclarationsLibraryProperties
+}
+
+func JavaDeclarationsLibraryFactory() android.Module {
+	callbacks := &JavaAconfigDeclarationsLibraryCallbacks{}
+	return java.GeneratedJavaLibraryModuleFactory("java_aconfig_library", callbacks, &callbacks.properties)
+}
+
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) DepsMutator(module *java.GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
+	declarations := callbacks.properties.Aconfig_declarations
+	if len(declarations) == 0 {
+		// TODO: Add test for this case
+		ctx.PropertyErrorf("aconfig_declarations", "aconfig_declarations property required")
+	} else {
+		ctx.AddDependency(ctx.Module(), declarationsTag, declarations)
+	}
+}
+
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path {
+	// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+	declarationsModules := ctx.GetDirectDepsWithTag(declarationsTag)
+	if len(declarationsModules) != 1 {
+		panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+	}
+	declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+
+	srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        srcJarRule,
+		Input:       declarations.IntermediatePath,
+		Output:      srcJarPath,
+		Description: "aconfig.srcjar",
+	})
+
+	return srcJarPath
+}
diff --git a/device_config/testing.go b/aconfig/testing.go
similarity index 78%
rename from device_config/testing.go
rename to aconfig/testing.go
index 284a7fa..60cefeb 100644
--- a/device_config/testing.go
+++ b/aconfig/testing.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package device_config
+package aconfig
 
 import (
 	"testing"
@@ -20,10 +20,10 @@
 	"android/soong/android"
 )
 
-var PrepareForTestWithDeviceConfigBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
+var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
 
 func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
-	return android.GroupFixturePreparers(PrepareForTestWithDeviceConfigBuildComponents).
+	return android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
 		ExtendWithErrorHandler(errorHandler).
 		RunTestWithBp(t, bp)
 }
diff --git a/android/config.go b/android/config.go
index 242be18..8c5f6e3 100644
--- a/android/config.go
+++ b/android/config.go
@@ -184,8 +184,8 @@
 }
 
 // The flag values files passed to aconfig, derived from RELEASE_VERSION
-func (c Config) ReleaseDeviceConfigValueSets() []string {
-	return c.config.productVariables.ReleaseDeviceConfigValueSets
+func (c Config) ReleaseAconfigValueSets() []string {
+	return c.config.productVariables.ReleaseAconfigValueSets
 }
 
 // A DeviceConfig object represents the configuration for a particular device
diff --git a/android/neverallow.go b/android/neverallow.go
index f2e8c85..41105e6 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -239,7 +239,9 @@
 func createInitFirstStageRules() []Rule {
 	return []Rule{
 		NeverAllow().
+			Without("name", "init_first_stage_defaults").
 			Without("name", "init_first_stage").
+			Without("name", "init_first_stage.microdroid").
 			With("install_in_root", "true").
 			Because("install_in_root is only for init_first_stage."),
 	}
diff --git a/android/variable.go b/android/variable.go
index c5f1823..00315bc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -477,8 +477,8 @@
 	ProductBrand        string   `json:",omitempty"`
 	BuildVersionTags    []string `json:",omitempty"`
 
-	ReleaseVersion               string   `json:",omitempty"`
-	ReleaseDeviceConfigValueSets []string `json:",omitempty"`
+	ReleaseVersion          string   `json:",omitempty"`
+	ReleaseAconfigValueSets []string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index d391cf5..eab6d25 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -38,11 +38,11 @@
 	}
 	asanLdflags = []string{"-Wl,-u,__asan_preinit"}
 
+	// DO NOT ADD MLLVM FLAGS HERE! ADD THEM BELOW TO hwasanCommonFlags.
 	hwasanCflags = []string{
 		"-fno-omit-frame-pointer",
 		"-Wno-frame-larger-than=",
 		"-fsanitize-hwaddress-abi=platform",
-		"-mllvm", "-hwasan-use-after-scope=1",
 	}
 
 	// ThinLTO performs codegen during link time, thus these flags need to
@@ -60,6 +60,8 @@
 		// GlobalISel is the default at -O0 on aarch64.
 		"--aarch64-enable-global-isel-at-O=-1",
 		"-fast-isel=false",
+		"-hwasan-use-after-scope=1",
+		"-dom-tree-reachability-max-bbs-to-explore=128",
 	}
 
 	sanitizeIgnorelistPrefix = "-fsanitize-ignorelist="
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index b897bb5..c3b0381 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -399,6 +399,9 @@
 	var wg sync.WaitGroup
 	for i := 0; i < jobs; i++ {
 		wg.Add(1)
+		// To smooth out the spikes in memory usage, skew the
+		// initial starting time of the jobs by a small amount.
+		time.Sleep(15 * time.Second)
 		go func() {
 			defer wg.Done()
 			for {
diff --git a/device_config/Android.bp b/device_config/Android.bp
deleted file mode 100644
index 6c44454..0000000
--- a/device_config/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-bootstrap_go_package {
-    name: "soong-device_config",
-    pkgPath: "android/soong/device_config",
-    deps: [
-        "blueprint",
-        "blueprint-pathtools",
-        "sbox_proto",
-        "soong",
-        "soong-android",
-        "soong-bazel",
-        "soong-android",
-        "soong-java",
-    ],
-    srcs: [
-        "device_config_definitions.go",
-        "device_config_values.go",
-        "device_config_value_set.go",
-        "init.go",
-        "java_device_config_definitions_library.go",
-        "testing.go",
-    ],
-    testSrcs: [
-        "device_config_definitions_test.go",
-        "device_config_values_test.go",
-        "device_config_value_set_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
diff --git a/device_config/java_device_config_definitions_library.go b/device_config/java_device_config_definitions_library.go
deleted file mode 100644
index 6e48ece..0000000
--- a/device_config/java_device_config_definitions_library.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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 device_config
-
-import (
-	"android/soong/android"
-	"android/soong/java"
-	"fmt"
-	"github.com/google/blueprint"
-)
-
-type definitionsTagType struct {
-	blueprint.BaseDependencyTag
-}
-
-var definitionsTag = definitionsTagType{}
-
-type JavaDeviceConfigDefinitionsLibraryProperties struct {
-	// name of the device_config_definitions module to generate a library for
-	Device_config_definitions string
-}
-
-type JavaDeviceConfigDefinitionsLibraryCallbacks struct {
-	properties JavaDeviceConfigDefinitionsLibraryProperties
-}
-
-func JavaDefinitionsLibraryFactory() android.Module {
-	callbacks := &JavaDeviceConfigDefinitionsLibraryCallbacks{}
-	return java.GeneratedJavaLibraryModuleFactory("java_device_config_definitions_library", callbacks, &callbacks.properties)
-}
-
-func (callbacks *JavaDeviceConfigDefinitionsLibraryCallbacks) DepsMutator(module *java.GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
-	definitions := callbacks.properties.Device_config_definitions
-	if len(definitions) == 0 {
-		// TODO: Add test for this case
-		ctx.PropertyErrorf("device_config_definitions", "device_config_definitions property required")
-	} else {
-		ctx.AddDependency(ctx.Module(), definitionsTag, definitions)
-	}
-}
-
-func (callbacks *JavaDeviceConfigDefinitionsLibraryCallbacks) GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path {
-	// Get the values that came from the global RELEASE_DEVICE_CONFIG_VALUE_SETS flag
-	definitionsModules := ctx.GetDirectDepsWithTag(definitionsTag)
-	if len(definitionsModules) != 1 {
-		panic(fmt.Errorf("Exactly one device_config_definitions property required"))
-	}
-	definitions := ctx.OtherModuleProvider(definitionsModules[0], definitionsProviderKey).(definitionsProviderData)
-
-	srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        srcJarRule,
-		Input:       definitions.intermediatePath,
-		Output:      srcJarPath,
-		Description: "device_config.srcjar",
-	})
-
-	return srcJarPath
-}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 3de8238..a3d81ce 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -25,6 +25,7 @@
 	"sync"
 
 	"android/soong/ui/metrics/bp2build_metrics_proto"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
@@ -1698,7 +1699,6 @@
 		"MissingPermission",
 		"SdkConstant",
 		"Todo",
-		"Typo",
 		"UnavailableSymbol",
 	}
 	droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
diff --git a/ui/build/bazel_metrics.go b/ui/build/bazel_metrics.go
index c0690c1..3f9fbb1 100644
--- a/ui/build/bazel_metrics.go
+++ b/ui/build/bazel_metrics.go
@@ -121,6 +121,7 @@
 			}
 		}
 		bazelMetrics.PhaseTimings = phaseTimings
+		bazelMetrics.BesId = proto.String(config.besId)
 
 		return bazelMetrics
 	}
diff --git a/ui/build/config.go b/ui/build/config.go
index f5bb6e1..0259009 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -90,8 +90,9 @@
 	skipMetricsUpload        bool
 	buildStartedTime         int64 // For metrics-upload-only - manually specify a build-started time
 	buildFromTextStub        bool
-	ensureAllowlistIntegrity bool  // For CI builds - make sure modules are mixed-built
-	bazelExitCode            int32 // For b-runs - necessary for updating NonZeroExit
+	ensureAllowlistIntegrity bool   // For CI builds - make sure modules are mixed-built
+	bazelExitCode            int32  // For b runs - necessary for updating NonZeroExit
+	besId                    string // For b runs, to identify the BuildEventService logs
 
 	// From the product config
 	katiArgs        []string
@@ -908,6 +909,8 @@
 			} else {
 				ctx.Fatalf("Error parsing bazel-exit-code", err)
 			}
+		} else if strings.HasPrefix(arg, "--bes-id=") {
+			c.besId = strings.TrimPrefix(arg, "--bes-id=")
 		} else if len(arg) > 0 && arg[0] == '-' {
 			parseArgNum := func(def int) int {
 				if len(arg) > 2 {
diff --git a/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go b/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
index 17a6b91..8b97b83 100644
--- a/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
+++ b/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
@@ -42,7 +42,7 @@
 	PhaseTimings []*PhaseTiming `protobuf:"bytes,1,rep,name=phase_timings,json=phaseTimings,proto3" json:"phase_timings,omitempty"`
 	Total        *int64         `protobuf:"varint,2,opt,name=total,proto3,oneof" json:"total,omitempty"`
 	ExitCode     *int32         `protobuf:"varint,3,opt,name=exit_code,json=exitCode,proto3,oneof" json:"exit_code,omitempty"`
-	SpongeId     *string        `protobuf:"bytes,4,opt,name=sponge_id,json=spongeId,proto3,oneof" json:"sponge_id,omitempty"`
+	BesId        *string        `protobuf:"bytes,4,opt,name=bes_id,json=besId,proto3,oneof" json:"bes_id,omitempty"`
 }
 
 func (x *BazelMetrics) Reset() {
@@ -98,9 +98,9 @@
 	return 0
 }
 
-func (x *BazelMetrics) GetSpongeId() string {
-	if x != nil && x.SpongeId != nil {
-		return *x.SpongeId
+func (x *BazelMetrics) GetBesId() string {
+	if x != nil && x.BesId != nil {
+		return *x.BesId
 	}
 	return ""
 }
@@ -177,7 +177,7 @@
 	0x0a, 0x13, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
 	0x6c, 0x64, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
-	0x22, 0xe0, 0x01, 0x0a, 0x0c, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+	0x22, 0xd7, 0x01, 0x0a, 0x0c, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
 	0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x69, 0x6e,
 	0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
 	0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74,
@@ -186,28 +186,28 @@
 	0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52,
 	0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x65, 0x78, 0x69,
 	0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x08,
-	0x65, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x73,
-	0x70, 0x6f, 0x6e, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02,
-	0x52, 0x08, 0x73, 0x70, 0x6f, 0x6e, 0x67, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a,
-	0x06, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x65, 0x78, 0x69, 0x74,
-	0x5f, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x70, 0x6f, 0x6e, 0x67, 0x65,
-	0x5f, 0x69, 0x64, 0x22, 0xd1, 0x01, 0x0a, 0x0b, 0x50, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d,
-	0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x68, 0x61, 0x73, 0x65,
-	0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48,
-	0x01, 0x52, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73,
-	0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x15, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f,
-	0x66, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x05, 0x48, 0x02, 0x52, 0x12, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x66, 0x42,
-	0x75, 0x69, 0x6c, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f,
-	0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x64,
-	0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73, 0x42, 0x18, 0x0a,
-	0x16, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x66, 0x5f, 0x62, 0x75, 0x69,
-	0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-	0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72,
-	0x69, 0x63, 0x73, 0x2f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x65, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x06, 0x62,
+	0x65, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x05, 0x62,
+	0x65, 0x73, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x74, 0x61,
+	0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x42,
+	0x09, 0x0a, 0x07, 0x5f, 0x62, 0x65, 0x73, 0x5f, 0x69, 0x64, 0x22, 0xd1, 0x01, 0x0a, 0x0b, 0x50,
+	0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x68,
+	0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
+	0x52, 0x09, 0x70, 0x68, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2a,
+	0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x73,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x15, 0x70, 0x6f,
+	0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x66, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74,
+	0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x12, 0x70, 0x6f, 0x72,
+	0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x66, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x88,
+	0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
+	0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e,
+	0x61, 0x6e, 0x6f, 0x73, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e,
+	0x5f, 0x6f, 0x66, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x2e,
+	0x5a, 0x2c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f,
+	0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x62, 0x61, 0x7a, 0x65, 0x6c,
+	0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/ui/metrics/bazel_metrics_proto/bazel_metrics.proto b/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
index e7e1015..e45d2bf 100644
--- a/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
+++ b/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
@@ -21,7 +21,7 @@
   repeated PhaseTiming phase_timings = 1;
   optional int64 total = 2;
   optional int32 exit_code = 3;
-  optional string sponge_id = 4;
+  optional string bes_id = 4;
 }
 
 message PhaseTiming {
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index fc0e21a..fb760ac 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -174,6 +174,7 @@
 						IOOutputKB:                 msg.EdgeFinished.GetIoOutputKb(),
 						VoluntaryContextSwitches:   msg.EdgeFinished.GetVoluntaryContextSwitches(),
 						InvoluntaryContextSwitches: msg.EdgeFinished.GetInvoluntaryContextSwitches(),
+						Tags:                       msg.EdgeFinished.GetTags(),
 					},
 				})
 			}
diff --git a/ui/status/ninja_frontend/frontend.pb.go b/ui/status/ninja_frontend/frontend.pb.go
index bcadc67..d0c4953 100644
--- a/ui/status/ninja_frontend/frontend.pb.go
+++ b/ui/status/ninja_frontend/frontend.pb.go
@@ -14,8 +14,8 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.26.0
-// 	protoc        v3.9.1
+// 	protoc-gen-go v1.28.1
+// 	protoc        v3.21.12
 // source: frontend.proto
 
 package ninja_frontend
@@ -459,6 +459,9 @@
 	VoluntaryContextSwitches *uint64 `protobuf:"varint,12,opt,name=voluntary_context_switches,json=voluntaryContextSwitches" json:"voluntary_context_switches,omitempty"`
 	// Involuntary context switches
 	InvoluntaryContextSwitches *uint64 `protobuf:"varint,13,opt,name=involuntary_context_switches,json=involuntaryContextSwitches" json:"involuntary_context_switches,omitempty"`
+	// Arbitrary tags for build system profiling (module names and types, rule
+	// names, etc). Format of the string is implementation defined.
+	Tags *string `protobuf:"bytes,14,opt,name=tags" json:"tags,omitempty"`
 }
 
 func (x *Status_EdgeFinished) Reset() {
@@ -584,6 +587,13 @@
 	return 0
 }
 
+func (x *Status_EdgeFinished) GetTags() string {
+	if x != nil && x.Tags != nil {
+		return *x.Tags
+	}
+	return ""
+}
+
 type Status_Message struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -650,7 +660,7 @@
 
 var file_frontend_proto_rawDesc = []byte{
 	0x0a, 0x0e, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x12, 0x05, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x22, 0xb4, 0x0a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74,
+	0x12, 0x05, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x22, 0xc8, 0x0a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74,
 	0x75, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x64, 0x67, 0x65,
 	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x2e,
 	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x45, 0x64, 0x67, 0x65,
@@ -694,7 +704,7 @@
 	0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x06,
 	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18, 0x0a,
 	0x07, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
-	0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x1a, 0xdf, 0x03, 0x0a, 0x0c, 0x45, 0x64, 0x67, 0x65,
+	0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x1a, 0xf3, 0x03, 0x0a, 0x0c, 0x45, 0x64, 0x67, 0x65,
 	0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
 	0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f,
 	0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54,
@@ -724,19 +734,20 @@
 	0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73,
 	0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0d, 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, 0x1a, 0x92, 0x01, 0x0a, 0x07, 0x4d, 0x65,
-	0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x2e, 0x53, 0x74, 0x61,
-	0x74, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x65, 0x76, 0x65,
-	0x6c, 0x3a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18,
-	0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x34, 0x0a, 0x05, 0x4c, 0x65, 0x76, 0x65,
-	0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x57,
-	0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f,
-	0x52, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x03, 0x42, 0x2a,
-	0x48, 0x03, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
-	0x67, 0x2f, 0x75, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2f, 0x6e, 0x69, 0x6e, 0x6a,
-	0x61, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64,
+	0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67,
+	0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x92, 0x01,
+	0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x6c, 0x65, 0x76,
+	0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, 0x69, 0x6e, 0x6a, 0x61,
+	0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
+	0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x05, 0x6c, 0x65, 0x76,
+	0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x34, 0x0a, 0x05,
+	0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12,
+	0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05,
+	0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47,
+	0x10, 0x03, 0x42, 0x2a, 0x48, 0x03, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+	0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2f,
+	0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64,
 }
 
 var (
diff --git a/ui/status/ninja_frontend/frontend.proto b/ui/status/ninja_frontend/frontend.proto
index 5730388..6cb4a0d 100644
--- a/ui/status/ninja_frontend/frontend.proto
+++ b/ui/status/ninja_frontend/frontend.proto
@@ -79,6 +79,9 @@
     optional uint64 voluntary_context_switches = 12;
     // Involuntary context switches
     optional uint64 involuntary_context_switches = 13;
+    // Arbitrary tags for build system profiling (module names and types, rule
+    // names, etc). Format of the string is implementation defined.
+    optional string tags = 14;
   }
 
   message Message {
diff --git a/ui/status/status.go b/ui/status/status.go
index a5b4a28..f3e58b6 100644
--- a/ui/status/status.go
+++ b/ui/status/status.go
@@ -85,6 +85,8 @@
 
 	// Involuntary context switches
 	InvoluntaryContextSwitches uint64
+
+	Tags string
 }
 
 // Counts describes the number of actions in each state
diff --git a/ui/tracer/status.go b/ui/tracer/status.go
index a8b4e62..f973613 100644
--- a/ui/tracer/status.go
+++ b/ui/tracer/status.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/ui/status"
+	"strings"
 	"time"
 )
 
@@ -60,6 +61,24 @@
 	}
 }
 
+func (s *statusOutput) parseTags(rawTags string) map[string]string {
+	if rawTags == "" {
+		return nil
+	}
+
+	tags := map[string]string{}
+	for _, pair := range strings.Split(rawTags, ";") {
+		if pair == "" {
+			// Ignore empty tag pairs. It's hard to generate these cleanly from
+			// make so some tag strings might be something like ";key=value".
+			continue
+		}
+		parts := strings.SplitN(pair, "=", 2)
+		tags[parts[0]] = parts[1]
+	}
+	return tags
+}
+
 func (s *statusOutput) FinishAction(result status.ActionResult, counts status.Counts) {
 	start, ok := s.running[result.Action]
 	if !ok {
@@ -90,20 +109,22 @@
 			IOOutputKB:                 result.Stats.IOOutputKB,
 			VoluntaryContextSwitches:   result.Stats.VoluntaryContextSwitches,
 			InvoluntaryContextSwitches: result.Stats.InvoluntaryContextSwitches,
+			Tags:                       s.parseTags(result.Stats.Tags),
 		},
 	})
 }
 
 type statsArg struct {
-	UserTime                   uint32 `json:"user_time"`
-	SystemTime                 uint32 `json:"system_time_ms"`
-	MaxRssKB                   uint64 `json:"max_rss_kb"`
-	MinorPageFaults            uint64 `json:"minor_page_faults"`
-	MajorPageFaults            uint64 `json:"major_page_faults"`
-	IOInputKB                  uint64 `json:"io_input_kb"`
-	IOOutputKB                 uint64 `json:"io_output_kb"`
-	VoluntaryContextSwitches   uint64 `json:"voluntary_context_switches"`
-	InvoluntaryContextSwitches uint64 `json:"involuntary_context_switches"`
+	UserTime                   uint32            `json:"user_time"`
+	SystemTime                 uint32            `json:"system_time_ms"`
+	MaxRssKB                   uint64            `json:"max_rss_kb"`
+	MinorPageFaults            uint64            `json:"minor_page_faults"`
+	MajorPageFaults            uint64            `json:"major_page_faults"`
+	IOInputKB                  uint64            `json:"io_input_kb"`
+	IOOutputKB                 uint64            `json:"io_output_kb"`
+	VoluntaryContextSwitches   uint64            `json:"voluntary_context_switches"`
+	InvoluntaryContextSwitches uint64            `json:"involuntary_context_switches"`
+	Tags                       map[string]string `json:"tags"`
 }
 
 func (s *statusOutput) Flush()                                        {}