Merge "Move LLNDK related logic to llndk_library" into main
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index d5291fc..ec0a6b6 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -22,6 +22,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"fmt"
+	"strconv"
 	"strings"
 )
 
@@ -87,11 +88,13 @@
 	if mode != "force-read-only" {
 		deps.SharedLibs = append(deps.SharedLibs, baseLibDep)
 
-		deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageReadApiCcDep)
-		deps.SharedLibs = append(deps.SharedLibs, libLogDep)
-
-		deps.StaticLibs = append(deps.StaticLibs, libBaseDep)
 	}
+
+	// TODO: after storage migration is over, don't add these in force-read-only-mode.
+	deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageReadApiCcDep)
+	deps.SharedLibs = append(deps.SharedLibs, libBaseDep)
+	deps.SharedLibs = append(deps.SharedLibs, libLogDep)
+
 	// TODO: It'd be really nice if we could reexport this library and not make everyone do it.
 
 	return deps
@@ -153,6 +156,7 @@
 		Args: map[string]string{
 			"gendir": this.generatedDir.String(),
 			"mode":   mode,
+			"debug":  strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorageCc()),
 		},
 	})
 
diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go
index 2e7fdc2..cf9ffbd 100644
--- a/aconfig/codegen/cc_aconfig_library_test.go
+++ b/aconfig/codegen/cc_aconfig_library_test.go
@@ -249,6 +249,22 @@
 				aconfig_declarations: "my_aconfig_declarations",
 				mode: "force-read-only",
 			}
+
+
+			cc_library {
+    		                name: "libbase",
+    		                srcs: ["libbase.cc"],
+			}
+
+			cc_library {
+    		                name: "liblog",
+    		                srcs: ["liblog.cc"],
+			}
+
+			cc_library {
+    		                name: "libaconfig_storage_read_api_cc",
+    		                srcs: ["libaconfig_storage_read_api_cc.cc"],
+			}
 		`))
 
 	module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared").Module()
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
index 73a8951..6182e14 100644
--- a/aconfig/codegen/init.go
+++ b/aconfig/codegen/init.go
@@ -49,11 +49,12 @@
 				` && ${aconfig} create-cpp-lib` +
 				`    --mode ${mode}` +
 				`    --cache ${in}` +
-				`    --out ${gendir}`,
+				`    --out ${gendir}` +
+				`    --allow-instrumentation ${debug}`,
 			CommandDeps: []string{
 				"$aconfig",
 			},
-		}, "gendir", "mode")
+		}, "gendir", "mode", "debug")
 
 	// For rust_aconfig_library: Generate Rust library
 	rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index dd09fbf..f5c50d3 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -15,8 +15,6 @@
 package android
 
 import (
-	"strings"
-
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -115,15 +113,6 @@
 func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
 	addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
 		for _, content := range m.Contents() {
-			// Coverage builds for TARGET_RELEASE=foo should always build from source,
-			// even if TARGET_RELEASE=foo uses prebuilt mainline modules.
-			// This is necessary because the checked-in prebuilts were generated with
-			// instrumentation turned off.
-			//
-			// Skip any prebuilt contents in coverage builds
-			if strings.HasPrefix(content, "prebuilt_") && (ctx.Config().JavaCoverageEnabled() || ctx.DeviceConfig().NativeCoverageEnabled()) {
-				continue
-			}
 			if !ctx.OtherModuleExists(content) && !ctx.Config().AllowMissingDependencies() {
 				ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name())
 			}
diff --git a/android/config.go b/android/config.go
index 75d135f..3ea9d4d 100644
--- a/android/config.go
+++ b/android/config.go
@@ -229,6 +229,11 @@
 	return c.config.productVariables.GetBuildFlagBool("RELEASE_NDK_ABI_MONITORED")
 }
 
+// Enable read flag from new storage, for C/C++
+func (c Config) ReleaseReadFromNewStorageCc() bool {
+	return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE_CC")
+}
+
 func (c Config) ReleaseHiddenApiExportableStubs() bool {
 	return c.config.productVariables.GetBuildFlagBool("RELEASE_HIDDEN_API_EXPORTABLE_STUBS") ||
 		Bool(c.config.productVariables.HiddenapiExportableStubs)
@@ -2099,6 +2104,7 @@
 		"RELEASE_APEX_CONTRIBUTIONS_IPSEC",
 		"RELEASE_APEX_CONTRIBUTIONS_MEDIA",
 		"RELEASE_APEX_CONTRIBUTIONS_MEDIAPROVIDER",
+		"RELEASE_APEX_CONTRIBUTIONS_MODULE_METADATA",
 		"RELEASE_APEX_CONTRIBUTIONS_NETWORKSTACKGOOGLE",
 		"RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS",
 		"RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION",
diff --git a/android/module.go b/android/module.go
index 5fe379c..effca03 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2142,13 +2142,13 @@
 func (e configurationEvalutor) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
 	ctx := e.ctx
 	m := e.m
-	switch condition.FunctionName {
+	switch condition.FunctionName() {
 	case "release_variable":
-		if len(condition.Args) != 1 {
-			ctx.OtherModulePropertyErrorf(m, property, "release_variable requires 1 argument, found %d", len(condition.Args))
+		if condition.NumArgs() != 1 {
+			ctx.OtherModulePropertyErrorf(m, property, "release_variable requires 1 argument, found %d", condition.NumArgs())
 			return proptools.ConfigurableValueUndefined()
 		}
-		if v, ok := ctx.Config().productVariables.BuildFlags[condition.Args[0]]; ok {
+		if v, ok := ctx.Config().productVariables.BuildFlags[condition.Arg(0)]; ok {
 			return proptools.ConfigurableValueString(v)
 		}
 		return proptools.ConfigurableValueUndefined()
@@ -2157,12 +2157,12 @@
 		ctx.OtherModulePropertyErrorf(m, property, "TODO(b/323382414): Product variables are not yet supported in selects")
 		return proptools.ConfigurableValueUndefined()
 	case "soong_config_variable":
-		if len(condition.Args) != 2 {
-			ctx.OtherModulePropertyErrorf(m, property, "soong_config_variable requires 2 arguments, found %d", len(condition.Args))
+		if condition.NumArgs() != 2 {
+			ctx.OtherModulePropertyErrorf(m, property, "soong_config_variable requires 2 arguments, found %d", condition.NumArgs())
 			return proptools.ConfigurableValueUndefined()
 		}
-		namespace := condition.Args[0]
-		variable := condition.Args[1]
+		namespace := condition.Arg(0)
+		variable := condition.Arg(1)
 		if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok {
 			if v, ok := n[variable]; ok {
 				return proptools.ConfigurableValueString(v)
@@ -2170,8 +2170,8 @@
 		}
 		return proptools.ConfigurableValueUndefined()
 	case "arch":
-		if len(condition.Args) != 0 {
-			ctx.OtherModulePropertyErrorf(m, property, "arch requires no arguments, found %d", len(condition.Args))
+		if condition.NumArgs() != 0 {
+			ctx.OtherModulePropertyErrorf(m, property, "arch requires no arguments, found %d", condition.NumArgs())
 			return proptools.ConfigurableValueUndefined()
 		}
 		if !m.base().ArchReady() {
@@ -2180,8 +2180,8 @@
 		}
 		return proptools.ConfigurableValueString(m.base().Arch().ArchType.Name)
 	case "os":
-		if len(condition.Args) != 0 {
-			ctx.OtherModulePropertyErrorf(m, property, "os requires no arguments, found %d", len(condition.Args))
+		if condition.NumArgs() != 0 {
+			ctx.OtherModulePropertyErrorf(m, property, "os requires no arguments, found %d", condition.NumArgs())
 			return proptools.ConfigurableValueUndefined()
 		}
 		// the arch mutator runs after the os mutator, we can just use this to enforce that os is ready.
@@ -2194,8 +2194,8 @@
 		// We currently don't have any other boolean variables (we should add support for typing
 		// the soong config variables), so add this fake one for testing the boolean select
 		// functionality.
-		if len(condition.Args) != 0 {
-			ctx.OtherModulePropertyErrorf(m, property, "boolean_var_for_testing requires 0 arguments, found %d", len(condition.Args))
+		if condition.NumArgs() != 0 {
+			ctx.OtherModulePropertyErrorf(m, property, "boolean_var_for_testing requires 0 arguments, found %d", condition.NumArgs())
 			return proptools.ConfigurableValueUndefined()
 		}
 
diff --git a/android/module_context.go b/android/module_context.go
index d3e2770..dea22ba 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -476,6 +476,7 @@
 		executable:            executable,
 		effectiveLicenseFiles: &licenseFiles,
 		partition:             fullInstallPath.partition,
+		skipInstall:           m.skipInstall(),
 	}
 	m.packagingSpecs = append(m.packagingSpecs, spec)
 	return spec
@@ -599,6 +600,7 @@
 		symlinkTarget:    relPath,
 		executable:       false,
 		partition:        fullInstallPath.partition,
+		skipInstall:      m.skipInstall(),
 	})
 
 	return fullInstallPath
@@ -640,6 +642,7 @@
 		symlinkTarget:    absPath,
 		executable:       false,
 		partition:        fullInstallPath.partition,
+		skipInstall:      m.skipInstall(),
 	})
 
 	return fullInstallPath
diff --git a/android/packaging.go b/android/packaging.go
index a8fb28d..6677218 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -43,6 +43,11 @@
 	effectiveLicenseFiles *Paths
 
 	partition string
+
+	// Whether this packaging spec represents an installation of the srcPath (i.e. this struct
+	// is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via
+	// PackageFile).
+	skipInstall bool
 }
 
 // Get file name of installed package
@@ -74,6 +79,10 @@
 	return p.partition
 }
 
+func (p *PackagingSpec) SkipInstall() bool {
+	return p.skipInstall
+}
+
 type PackageModule interface {
 	Module
 	packagingBase() *PackagingBase
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 2574ed4..575b926 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -610,45 +610,3 @@
 		}
 		`, selectMainlineModuleContritbutions)
 }
-
-// Test that apex_contributions of prebuilt modules are ignored in coverage builds
-func TestSourceIsSelectedInCoverageBuilds(t *testing.T) {
-	prebuiltMainlineContributions := GroupFixturePreparers(
-		FixtureModifyProductVariables(func(variables FixtureProductVariables) {
-			variables.BuildFlags = map[string]string{
-				"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_prebuilt_apex_contributions",
-			}
-		}),
-		FixtureMergeEnv(map[string]string{
-			"EMMA_INSTRUMENT_FRAMEWORK": "true",
-		}),
-	)
-	bp := `
-		source {
-			name: "foo",
-		}
-		prebuilt {
-			name: "foo",
-			srcs: ["prebuilt_file"],
-		}
-		apex_contributions {
-			name: "my_prebuilt_apex_contributions",
-			api_domain: "my_mainline_module",
-			contents: [
-			  "prebuilt_foo",
-			],
-		}
-		all_apex_contributions {
-			name: "all_apex_contributions",
-		}
-		`
-	ctx := GroupFixturePreparers(
-		PrepareForTestWithArchMutator,
-		PrepareForTestWithPrebuilts,
-		FixtureRegisterWithContext(registerTestPrebuiltModules),
-		prebuiltMainlineContributions).RunTestWithBp(t, bp)
-	source := ctx.ModuleForTests("foo", "android_common").Module()
-	AssertBoolEquals(t, "Source should be preferred in coverage builds", true, !source.IsHideFromMake())
-	prebuilt := ctx.ModuleForTests("prebuilt_foo", "android_common").Module()
-	AssertBoolEquals(t, "Prebuilt should not be preferred in coverage builds", false, !prebuilt.IsHideFromMake())
-}
diff --git a/android/selects_test.go b/android/selects_test.go
index f912ce6..d9499a5 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -28,6 +28,7 @@
 		name          string
 		bp            string
 		provider      selectsTestProvider
+		providers     map[string]selectsTestProvider
 		vendorVars    map[string]map[string]string
 		expectedError string
 	}{
@@ -411,6 +412,42 @@
 			},
 		},
 		{
+			name: "defaults applied to multiple modules",
+			bp: `
+			my_module_type {
+				name: "foo2",
+				defaults: ["bar"],
+				my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
+					"a": ["a1"],
+					default: ["b1"],
+				}),
+			}
+			my_module_type {
+				name: "foo",
+				defaults: ["bar"],
+				my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
+					"a": ["a1"],
+					default: ["b1"],
+				}),
+			}
+			my_defaults {
+				name: "bar",
+				my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
+					"a": ["a2"],
+					default: ["b2"],
+				}),
+			}
+			`,
+			providers: map[string]selectsTestProvider{
+				"foo": {
+					my_string_list: &[]string{"b2", "b1"},
+				},
+				"foo2": {
+					my_string_list: &[]string{"b2", "b1"},
+				},
+			},
+		},
+		{
 			name: "Replacing string list",
 			bp: `
 			my_module_type {
@@ -596,6 +633,61 @@
 			},
 			expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string",
 		},
+		{
+			name: "Assigning select to nonconfigurable bool",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_nonconfigurable_bool: select(arch(), {
+					"x86_64": true,
+					default: false,
+				}),
+			}
+			`,
+			expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`,
+		},
+		{
+			name: "Assigning select to nonconfigurable string",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_nonconfigurable_string: select(arch(), {
+					"x86_64": "x86!",
+					default: "unknown!",
+				}),
+			}
+			`,
+			expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
+		},
+		{
+			name: "Assigning appended selects to nonconfigurable string",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_nonconfigurable_string: select(arch(), {
+					"x86_64": "x86!",
+					default: "unknown!",
+				}) + select(os(), {
+					"darwin": "_darwin!",
+					default: "unknown!",
+				}),
+			}
+			`,
+			expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`,
+		},
+		{
+			name: "Assigning select to nonconfigurable string list",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_nonconfigurable_string_list: select(arch(), {
+					"x86_64": ["foo", "bar"],
+					default: ["baz", "qux"],
+				}),
+			}
+			`,
+			expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`,
+		},
 	}
 
 	for _, tc := range testCases {
@@ -617,10 +709,19 @@
 			result := fixtures.RunTestWithBp(t, tc.bp)
 
 			if tc.expectedError == "" {
-				m := result.ModuleForTests("foo", "android_arm64_armv8-a")
-				p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
-				if !reflect.DeepEqual(p, tc.provider) {
-					t.Errorf("Expected:\n  %q\ngot:\n  %q", tc.provider.String(), p.String())
+				if len(tc.providers) == 0 {
+					tc.providers = map[string]selectsTestProvider{
+						"foo": tc.provider,
+					}
+				}
+
+				for moduleName := range tc.providers {
+					expected := tc.providers[moduleName]
+					m := result.ModuleForTests(moduleName, "android_arm64_armv8-a")
+					p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
+					if !reflect.DeepEqual(p, expected) {
+						t.Errorf("Expected:\n  %q\ngot:\n  %q", expected.String(), p.String())
+					}
 				}
 			}
 		})
@@ -628,11 +729,14 @@
 }
 
 type selectsTestProvider struct {
-	my_bool               *bool
-	my_string             *string
-	my_string_list        *[]string
-	my_paths              *[]string
-	replacing_string_list *[]string
+	my_bool                        *bool
+	my_string                      *string
+	my_string_list                 *[]string
+	my_paths                       *[]string
+	replacing_string_list          *[]string
+	my_nonconfigurable_bool        *bool
+	my_nonconfigurable_string      *string
+	my_nonconfigurable_string_list []string
 }
 
 func (p *selectsTestProvider) String() string {
@@ -644,23 +748,42 @@
 	if p.my_string != nil {
 		myStringStr = *p.my_string
 	}
+	myNonconfigurableStringStr := "nil"
+	if p.my_string != nil {
+		myNonconfigurableStringStr = *p.my_nonconfigurable_string
+	}
 	return fmt.Sprintf(`selectsTestProvider {
 	my_bool: %v,
 	my_string: %s,
     my_string_list: %s,
     my_paths: %s,
 	replacing_string_list %s,
-}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths, p.replacing_string_list)
+	my_nonconfigurable_bool: %v,
+	my_nonconfigurable_string: %s,
+	my_nonconfigurable_string_list: %s,
+}`,
+		myBoolStr,
+		myStringStr,
+		p.my_string_list,
+		p.my_paths,
+		p.replacing_string_list,
+		p.my_nonconfigurable_bool,
+		myNonconfigurableStringStr,
+		p.my_nonconfigurable_string_list,
+	)
 }
 
 var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
 
 type selectsMockModuleProperties struct {
-	My_bool               proptools.Configurable[bool]
-	My_string             proptools.Configurable[string]
-	My_string_list        proptools.Configurable[[]string]
-	My_paths              proptools.Configurable[[]string] `android:"path"`
-	Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
+	My_bool                        proptools.Configurable[bool]
+	My_string                      proptools.Configurable[string]
+	My_string_list                 proptools.Configurable[[]string]
+	My_paths                       proptools.Configurable[[]string] `android:"path"`
+	Replacing_string_list          proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
+	My_nonconfigurable_bool        *bool
+	My_nonconfigurable_string      *string
+	My_nonconfigurable_string_list []string
 }
 
 type selectsMockModule struct {
@@ -671,11 +794,14 @@
 
 func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 	SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
-		my_bool:               p.properties.My_bool.Get(ctx),
-		my_string:             p.properties.My_string.Get(ctx),
-		my_string_list:        p.properties.My_string_list.Get(ctx),
-		my_paths:              p.properties.My_paths.Get(ctx),
-		replacing_string_list: p.properties.Replacing_string_list.Get(ctx),
+		my_bool:                        p.properties.My_bool.Get(ctx),
+		my_string:                      p.properties.My_string.Get(ctx),
+		my_string_list:                 p.properties.My_string_list.Get(ctx),
+		my_paths:                       p.properties.My_paths.Get(ctx),
+		replacing_string_list:          p.properties.Replacing_string_list.Get(ctx),
+		my_nonconfigurable_bool:        p.properties.My_nonconfigurable_bool,
+		my_nonconfigurable_string:      p.properties.My_nonconfigurable_string,
+		my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list,
 	})
 }
 
diff --git a/bin/build-flag b/bin/build-flag
new file mode 100755
index 0000000..dc404bc
--- /dev/null
+++ b/bin/build-flag
@@ -0,0 +1,28 @@
+#!/bin/bash -eu
+#
+# Copyright 2017 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.
+
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+require_top
+
+# Save the current PWD for use in soong_ui
+export ORIGINAL_PWD=${PWD}
+export TOP=$(gettop)
+source ${TOP}/build/soong/scripts/microfactory.bash
+
+soong_build_go build-flag android/soong/cmd/release_config/build_flag
+
+cd ${TOP}
+exec "$(getoutdir)/build-flag" "$@"
diff --git a/cc/builder.go b/cc/builder.go
index 845176e..e78b8c0 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -855,8 +855,8 @@
 // into a single .ldump sAbi dump file
 func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
 	baseName string, exportedIncludeDirs []string, symbolFile android.OptionalPath,
-	excludedSymbolVersions, excludedSymbolTags []string,
-	api string) android.Path {
+	excludedSymbolVersions, excludedSymbolTags, includedSymbolTags []string,
+	api string, isLlndk bool) android.Path {
 
 	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
 
@@ -874,6 +874,12 @@
 	for _, tag := range excludedSymbolTags {
 		symbolFilterStr += " --exclude-symbol-tag " + tag
 	}
+	for _, tag := range includedSymbolTags {
+		symbolFilterStr += " --include-symbol-tag " + tag
+	}
+	if isLlndk {
+		symbolFilterStr += " --symbol-tag-policy MatchTagOnly"
+	}
 	apiLevelsJson := android.GetApiLevelsJson(ctx)
 	implicits = append(implicits, apiLevelsJson)
 	symbolFilterStr += " --api-map " + apiLevelsJson.String()
diff --git a/cc/library.go b/cc/library.go
index 44bbdfc..a436649 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1249,28 +1249,29 @@
 
 func (library *libraryDecorator) linkLlndkSAbiDumpFiles(ctx ModuleContext,
 	deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string,
-	excludeSymbolVersions, excludeSymbolTags []string) android.Path {
+	excludeSymbolVersions, excludeSymbolTags []string,
+	vendorApiLevel string) android.Path {
 	// NDK symbols in version 34 are LLNDK symbols. Those in version 35 are not.
-	// TODO(b/314010764): Add parameters to read LLNDK symbols from the symbol file.
 	return transformDumpToLinkedDump(ctx,
 		sAbiDumpFiles, soFile, libFileName+".llndk",
 		library.llndkIncludeDirsForAbiCheck(ctx, deps),
 		android.OptionalPathForModuleSrc(ctx, library.Properties.Llndk.Symbol_file),
 		append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
 		append([]string{"platform-only"}, excludeSymbolTags...),
-		"34")
+		[]string{"llndk=" + vendorApiLevel}, "34", true /* isLlndk */)
 }
 
 func (library *libraryDecorator) linkApexSAbiDumpFiles(ctx ModuleContext,
 	deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string,
-	excludeSymbolVersions, excludeSymbolTags []string, sdkVersion string) android.Path {
+	excludeSymbolVersions, excludeSymbolTags []string,
+	sdkVersion string) android.Path {
 	return transformDumpToLinkedDump(ctx,
 		sAbiDumpFiles, soFile, libFileName+".apex",
 		library.exportedIncludeDirsForAbiCheck(ctx),
 		android.OptionalPathForModuleSrc(ctx, library.Properties.Stubs.Symbol_file),
 		append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
 		append([]string{"platform-only"}, excludeSymbolTags...),
-		sdkVersion)
+		[]string{"apex", "systemapi"}, sdkVersion, false /* isLlndk */)
 }
 
 func getRefAbiDumpFile(ctx android.ModuleInstallPathContext,
@@ -1397,18 +1398,19 @@
 			android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
 			headerAbiChecker.Exclude_symbol_versions,
 			headerAbiChecker.Exclude_symbol_tags,
-			currSdkVersion)
+			[]string{} /* includeSymbolTags */, currSdkVersion, false /* isLlndk */)
 
 		var llndkDump, apexVariantDump android.Path
 		tags := classifySourceAbiDump(ctx)
 		for _, tag := range tags {
-			if tag == llndkLsdumpTag {
+			if tag == llndkLsdumpTag && currVendorVersion != "" {
 				if llndkDump == nil {
 					// TODO(b/323447559): Evaluate if replacing sAbiDumpFiles with implDump is faster
 					llndkDump = library.linkLlndkSAbiDumpFiles(ctx,
 						deps, objs.sAbiDumpFiles, soFile, fileName,
 						headerAbiChecker.Exclude_symbol_versions,
-						headerAbiChecker.Exclude_symbol_tags)
+						headerAbiChecker.Exclude_symbol_tags,
+						currVendorVersion)
 				}
 				addLsdumpPath(string(tag) + ":" + llndkDump.String())
 			} else if tag == apexLsdumpTag {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index cbb5d58d..e9f790f 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -177,7 +177,7 @@
 				implicits = append(implicits, importLibOutputFile)
 
 				ctx.Build(pctx, android.BuildParams{
-					Rule:        android.Cp,
+					Rule:        android.CpExecutable,
 					Description: "prebuilt import library",
 					Input:       importLibSrc,
 					Output:      importLibOutputFile,
@@ -188,7 +188,7 @@
 			}
 
 			ctx.Build(pctx, android.BuildParams{
-				Rule:        android.Cp,
+				Rule:        android.CpExecutable,
 				Description: "prebuilt shared library",
 				Implicits:   implicits,
 				Input:       in,
diff --git a/cc/sanitize.go b/cc/sanitize.go
index db046ec..2a1ee3c 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -55,7 +55,6 @@
 		// higher number of "optimized out" stack variables.
 		// b/112437883.
 		"-instcombine-lower-dbg-declare=0",
-		"-hwasan-use-after-scope=1",
 		"-dom-tree-reachability-max-bbs-to-explore=128",
 	}
 
@@ -82,7 +81,8 @@
 		"-fno-sanitize-recover=integer,undefined"}
 	hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
 		"export_memory_stats=0", "max_malloc_fill_size=131072", "malloc_fill_byte=0"}
-	memtagStackCommonFlags = []string{"-march=armv8-a+memtag", "-mllvm", "-dom-tree-reachability-max-bbs-to-explore=128"}
+	memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
+	memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"}
 
 	hostOnlySanitizeFlags   = []string{"-fno-sanitize-recover=all"}
 	deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all"}
@@ -879,6 +879,13 @@
 		flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...)
 		flags.Local.AsFlags = append(flags.Local.AsFlags, memtagStackCommonFlags...)
 		flags.Local.LdFlags = append(flags.Local.LdFlags, memtagStackCommonFlags...)
+
+		for _, flag := range memtagStackLlvmFlags {
+			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag)
+		}
+		for _, flag := range memtagStackLlvmFlags {
+			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag)
+		}
 	}
 
 	if (Bool(sanProps.Memtag_heap) || Bool(sanProps.Memtag_stack) || Bool(sanProps.Memtag_globals)) && ctx.binary() {
diff --git a/cmd/release_config/build_flag/main.go b/cmd/release_config/build_flag/main.go
index 6f909af..ec7d64f 100644
--- a/cmd/release_config/build_flag/main.go
+++ b/cmd/release_config/build_flag/main.go
@@ -1,10 +1,12 @@
 package main
 
 import (
+	"cmp"
 	"flag"
 	"fmt"
 	"os"
 	"path/filepath"
+	"slices"
 	"strings"
 
 	rc_lib "android/soong/cmd/release_config/release_config_lib"
@@ -36,6 +38,16 @@
 
 	// Disable warning messages
 	quiet bool
+
+	// Show all release configs
+	allReleases bool
+
+	// Call get_build_var PRODUCT_RELEASE_CONFIG_MAPS to get the
+	// product-specific map directories.
+	useGetBuildVar bool
+
+	// Panic on errors.
+	debug bool
 }
 
 type CommandFunc func(*rc_lib.ReleaseConfigs, Flags, string, []string) error
@@ -60,6 +72,14 @@
 	return "", fmt.Errorf("Could not determine directory from %s", path)
 }
 
+func MarshalFlagDefaultValue(config *rc_lib.ReleaseConfig, name string) (ret string, err error) {
+	fa, ok := config.FlagArtifacts[name]
+	if !ok {
+		return "", fmt.Errorf("%s not found in %s", name, config.Name)
+	}
+	return rc_lib.MarshalValue(fa.Traces[0].Value), nil
+}
+
 func MarshalFlagValue(config *rc_lib.ReleaseConfig, name string) (ret string, err error) {
 	fa, ok := config.FlagArtifacts[name]
 	if !ok {
@@ -68,19 +88,41 @@
 	return rc_lib.MarshalValue(fa.Value), nil
 }
 
+// Returns a list of ReleaseConfig objects for which to process flags.
 func GetReleaseArgs(configs *rc_lib.ReleaseConfigs, commonFlags Flags) ([]*rc_lib.ReleaseConfig, error) {
 	var all bool
-	relFlags := flag.NewFlagSet("set", flag.ExitOnError)
-	relFlags.BoolVar(&all, "all", false, "Display all flags")
+	relFlags := flag.NewFlagSet("releaseFlags", flag.ExitOnError)
+	relFlags.BoolVar(&all, "all", false, "Display all releases")
 	relFlags.Parse(commonFlags.targetReleases)
 	var ret []*rc_lib.ReleaseConfig
-	if all {
+	if all || commonFlags.allReleases {
+		sortMap := map[string]int{
+			"trunk_staging": 0,
+			"trunk_food":    10,
+			"trunk":         20,
+			// Anything not listed above, uses this for key 1 in the sort.
+			"-default": 100,
+		}
+
 		for _, config := range configs.ReleaseConfigs {
 			ret = append(ret, config)
 		}
+		slices.SortFunc(ret, func(a, b *rc_lib.ReleaseConfig) int {
+			mapValue := func(v *rc_lib.ReleaseConfig) int {
+				if v, ok := sortMap[v.Name]; ok {
+					return v
+				}
+				return sortMap["-default"]
+			}
+			if n := cmp.Compare(mapValue(a), mapValue(b)); n != 0 {
+				return n
+			}
+			return cmp.Compare(a.Name, b.Name)
+		})
 		return ret, nil
 	}
 	for _, arg := range relFlags.Args() {
+		// Return releases in the order that they were given.
 		config, err := configs.GetReleaseConfig(arg)
 		if err != nil {
 			return nil, err
@@ -92,12 +134,17 @@
 
 func GetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, args []string) error {
 	isTrace := cmd == "trace"
+	isSet := cmd == "set"
+
 	var all bool
-	getFlags := flag.NewFlagSet("set", flag.ExitOnError)
+	getFlags := flag.NewFlagSet("get", flag.ExitOnError)
 	getFlags.BoolVar(&all, "all", false, "Display all flags")
 	getFlags.Parse(args)
 	args = getFlags.Args()
 
+	if isSet {
+		commonFlags.allReleases = true
+	}
 	releaseConfigList, err := GetReleaseArgs(configs, commonFlags)
 	if err != nil {
 		return err
@@ -113,21 +160,72 @@
 		}
 	}
 
-	showName := len(releaseConfigList) > 1 || len(args) > 1
-	for _, config := range releaseConfigList {
-		var configName string
-		if len(releaseConfigList) > 1 {
-			configName = fmt.Sprintf("%s.", config.Name)
-		}
+	var maxVariableNameLen, maxReleaseNameLen int
+	var releaseNameFormat, variableNameFormat string
+	valueFormat := "%s"
+	showReleaseName := len(releaseConfigList) > 1
+	showVariableName := len(args) > 1
+	if showVariableName {
 		for _, arg := range args {
-			val, err := MarshalFlagValue(config, arg)
-			if err != nil {
-				return err
+			maxVariableNameLen = max(len(arg), maxVariableNameLen)
+		}
+		variableNameFormat = fmt.Sprintf("%%-%ds ", maxVariableNameLen)
+		valueFormat = "'%s'"
+	}
+	if showReleaseName {
+		for _, config := range releaseConfigList {
+			maxReleaseNameLen = max(len(config.Name), maxReleaseNameLen)
+		}
+		releaseNameFormat = fmt.Sprintf("%%-%ds ", maxReleaseNameLen)
+		valueFormat = "'%s'"
+	}
+
+	outputOneLine := func(variable, release, value, valueFormat string) {
+		var outStr string
+		if showVariableName {
+			outStr += fmt.Sprintf(variableNameFormat, variable)
+		}
+		if showReleaseName {
+			outStr += fmt.Sprintf(releaseNameFormat, release)
+		}
+		outStr += fmt.Sprintf(valueFormat, value)
+		fmt.Println(outStr)
+	}
+
+	for _, arg := range args {
+		if _, ok := configs.FlagArtifacts[arg]; !ok {
+			return fmt.Errorf("%s is not a defined build flag", arg)
+		}
+	}
+
+	for _, arg := range args {
+		for _, config := range releaseConfigList {
+			if isSet {
+				// If this is from the set command, format the output as:
+				// <default>           ""
+				// trunk_staging       ""
+				// trunk               ""
+				//
+				// ap1a                ""
+				// ...
+				switch {
+				case config.Name == "trunk_staging":
+					defaultValue, err := MarshalFlagDefaultValue(config, arg)
+					if err != nil {
+						return err
+					}
+					outputOneLine(arg, "<default>", defaultValue, valueFormat)
+				case config.AconfigFlagsOnly:
+					continue
+				case config.Name == "trunk":
+					fmt.Println()
+				}
 			}
-			if showName {
-				fmt.Printf("%s%s=%s\n", configName, arg, val)
+			val, err := MarshalFlagValue(config, arg)
+			if err == nil {
+				outputOneLine(arg, config.Name, val, valueFormat)
 			} else {
-				fmt.Printf("%s\n", val)
+				outputOneLine(arg, config.Name, "REDACTED", "%s")
 			}
 			if isTrace {
 				for _, trace := range config.FlagArtifacts[arg].Traces {
@@ -160,6 +258,9 @@
 	if err != nil {
 		return err
 	}
+	if release.AconfigFlagsOnly {
+		return fmt.Errorf("%s does not allow build flag overrides", targetRelease)
+	}
 	flagArtifact, ok := release.FlagArtifacts[name]
 	if !ok {
 		return fmt.Errorf("Unknown build flag %s", name)
@@ -177,26 +278,48 @@
 		Value: rc_lib.UnmarshalValue(value),
 	}
 	flagPath := filepath.Join(valueDir, "flag_values", targetRelease, fmt.Sprintf("%s.textproto", name))
-	return rc_lib.WriteMessage(flagPath, flagValue)
+	err = rc_lib.WriteMessage(flagPath, flagValue)
+	if err != nil {
+		return err
+	}
+
+	// Reload the release configs.
+	configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, commonFlags.targetReleases[0], commonFlags.useGetBuildVar)
+	if err != nil {
+		return err
+	}
+	err = GetCommand(configs, commonFlags, cmd, args[0:1])
+	if err != nil {
+		return err
+	}
+	fmt.Printf("Updated: %s\n", flagPath)
+	return nil
 }
 
 func main() {
-	var err error
 	var commonFlags Flags
 	var configs *rc_lib.ReleaseConfigs
+	topDir, err := rc_lib.GetTopDir()
 
-	outEnv := os.Getenv("OUT_DIR")
-	if outEnv == "" {
-		outEnv = "out"
-	}
 	// Handle the common arguments
-	flag.StringVar(&commonFlags.top, "top", ".", "path to top of workspace")
+	flag.StringVar(&commonFlags.top, "top", topDir, "path to top of workspace")
 	flag.BoolVar(&commonFlags.quiet, "quiet", false, "disable warning messages")
 	flag.Var(&commonFlags.maps, "map", "path to a release_config_map.textproto. may be repeated")
-	flag.StringVar(&commonFlags.outDir, "out_dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created")
+	flag.StringVar(&commonFlags.outDir, "out-dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created")
 	flag.Var(&commonFlags.targetReleases, "release", "TARGET_RELEASE for this build")
+	flag.BoolVar(&commonFlags.allReleases, "all-releases", false, "operate on all releases. (Ignored for set command)")
+	flag.BoolVar(&commonFlags.useGetBuildVar, "use-get-build-var", true, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS to get needed maps")
+	flag.BoolVar(&commonFlags.debug, "debug", false, "turn on debugging output for errors")
 	flag.Parse()
 
+	errorExit := func(err error) {
+		if commonFlags.debug {
+			panic(err)
+		}
+		fmt.Fprintf(os.Stderr, "%s\n", err)
+		os.Exit(1)
+	}
+
 	if commonFlags.quiet {
 		rc_lib.DisableWarnings()
 	}
@@ -206,24 +329,23 @@
 	}
 
 	if err = os.Chdir(commonFlags.top); err != nil {
-		panic(err)
+		errorExit(err)
 	}
 
 	// Get the current state of flagging.
 	relName := commonFlags.targetReleases[0]
 	if relName == "--all" || relName == "-all" {
-		// If the users said `--release --all`, grab trunk staging for simplicity.
-		relName = "trunk_staging"
+		commonFlags.allReleases = true
 	}
-	configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, relName)
+	configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, relName, commonFlags.useGetBuildVar)
 	if err != nil {
-		panic(err)
+		errorExit(err)
 	}
 
 	if cmd, ok := commandMap[flag.Arg(0)]; ok {
 		args := flag.Args()
 		if err = cmd(configs, commonFlags, args[0], args[1:]); err != nil {
-			panic(err)
+			errorExit(err)
 		}
 	}
 }
diff --git a/cmd/release_config/crunch_flags/main.go b/cmd/release_config/crunch_flags/main.go
index 29290a4..95342b1 100644
--- a/cmd/release_config/crunch_flags/main.go
+++ b/cmd/release_config/crunch_flags/main.go
@@ -15,18 +15,29 @@
 	"google.golang.org/protobuf/proto"
 )
 
-// When a flag declaration has an initial value that is a string, the default workflow is PREBUILT.
-// If the flag name starts with any of prefixes in manualFlagNamePrefixes, it is MANUAL.
-var manualFlagNamePrefixes []string = []string{
-	"RELEASE_ACONFIG_",
-	"RELEASE_PLATFORM_",
-}
+var (
+	// When a flag declaration has an initial value that is a string, the default workflow is PREBUILT.
+	// If the flag name starts with any of prefixes in manualFlagNamePrefixes, it is MANUAL.
+	manualFlagNamePrefixes []string = []string{
+		"RELEASE_ACONFIG_",
+		"RELEASE_PLATFORM_",
+	}
 
-var defaultFlagNamespace string = "android_UNKNOWN"
+	// Set `aconfig_flags_only: true` in these release configs.
+	aconfigFlagsOnlyConfigs map[string]bool = map[string]bool{
+		"trunk_food": true,
+	}
+
+	// Default namespace value.  This is intentionally invalid.
+	defaultFlagNamespace string = "android_UNKNOWN"
+
+	// What is the current name for "next".
+	nextName string = "ap3a"
+)
 
 func RenameNext(name string) string {
 	if name == "next" {
-		return "ap3a"
+		return nextName
 	}
 	return name
 }
@@ -102,10 +113,13 @@
 			description = ""
 			continue
 		}
-		declValue := matches[declRegexp.SubexpIndex("value")]
 		declName := matches[declRegexp.SubexpIndex("name")]
-		container := rc_proto.Container(rc_proto.Container_value[matches[declRegexp.SubexpIndex("container")]])
+		declValue := matches[declRegexp.SubexpIndex("value")]
 		description = strings.TrimSpace(description)
+		containers := []string{strings.ToLower(matches[declRegexp.SubexpIndex("container")])}
+		if containers[0] == "all" {
+			containers = []string{"product", "system", "system_ext", "vendor"}
+		}
 		var namespace string
 		var ok bool
 		if namespace, ok = namespaceMap[declName]; !ok {
@@ -115,7 +129,7 @@
 			Name:        proto.String(declName),
 			Namespace:   proto.String(namespace),
 			Description: proto.String(description),
-			Container:   &container,
+			Containers:  containers,
 		}
 		description = ""
 		// Most build flags are `workflow: PREBUILT`.
@@ -202,6 +216,9 @@
 				fmt.Printf("%s: Unexpected value %s=%s\n", path, valName, valValue)
 			}
 			if flagValue != nil {
+				if releaseProto.GetAconfigFlagsOnly() {
+					return fmt.Errorf("%s does not allow build flag overrides", RenameNext(name))
+				}
 				valPath := filepath.Join(dir, "flag_values", RenameNext(name), fmt.Sprintf("%s.textproto", valName))
 				err := WriteFile(valPath, flagValue)
 				if err != nil {
@@ -213,6 +230,12 @@
 	return err
 }
 
+var (
+	allContainers = func() []string {
+		return []string{"product", "system", "system_ext", "vendor"}
+	}()
+)
+
 func ProcessReleaseConfigMap(dir string, descriptionMap map[string]string) error {
 	path := filepath.Join(dir, "release_config_map.mk")
 	if _, err := os.Stat(path); err != nil {
@@ -235,16 +258,16 @@
 		return err
 	}
 	cleanDir := strings.TrimLeft(dir, "../")
-	var defaultContainer rc_proto.Container
+	var defaultContainers []string
 	switch {
 	case strings.HasPrefix(cleanDir, "build/") || cleanDir == "vendor/google_shared/build":
-		defaultContainer = rc_proto.Container(rc_proto.Container_ALL)
+		defaultContainers = allContainers
 	case cleanDir == "vendor/google/release":
-		defaultContainer = rc_proto.Container(rc_proto.Container_ALL)
+		defaultContainers = allContainers
 	default:
-		defaultContainer = rc_proto.Container(rc_proto.Container_VENDOR)
+		defaultContainers = []string{"vendor"}
 	}
-	releaseConfigMap := &rc_proto.ReleaseConfigMap{DefaultContainer: &defaultContainer}
+	releaseConfigMap := &rc_proto.ReleaseConfigMap{DefaultContainers: defaultContainers}
 	// If we find a description for the directory, include it.
 	if description, ok := descriptionMap[cleanDir]; ok {
 		releaseConfigMap.Description = proto.String(description)
@@ -276,6 +299,9 @@
 		releaseConfig := &rc_proto.ReleaseConfig{
 			Name: proto.String(RenameNext(name)),
 		}
+		if aconfigFlagsOnlyConfigs[name] {
+			releaseConfig.AconfigFlagsOnly = proto.Bool(true)
+		}
 		configFiles := config[configRegexp.SubexpIndex("files")]
 		files := strings.Split(strings.ReplaceAll(configFiles, "$(local_dir)", dir+"/"), " ")
 		configInherits := config[configRegexp.SubexpIndex("inherits")]
@@ -302,15 +328,26 @@
 	var dirs rc_lib.StringList
 	var namespacesFile string
 	var descriptionsFile string
+	var debug bool
+	defaultTopDir, err := rc_lib.GetTopDir()
 
-	flag.StringVar(&top, "top", ".", "path to top of workspace")
+	flag.StringVar(&top, "top", defaultTopDir, "path to top of workspace")
 	flag.Var(&dirs, "dir", "directory to process, relative to the top of the workspace")
 	flag.StringVar(&namespacesFile, "namespaces", "", "location of file with 'flag_name namespace' information")
 	flag.StringVar(&descriptionsFile, "descriptions", "", "location of file with 'directory description' information")
+	flag.BoolVar(&debug, "debug", false, "turn on debugging output for errors")
 	flag.Parse()
 
+	errorExit := func(err error) {
+		if debug {
+			panic(err)
+		}
+		fmt.Fprintf(os.Stderr, "%s\n", err)
+		os.Exit(1)
+	}
+
 	if err = os.Chdir(top); err != nil {
-		panic(err)
+		errorExit(err)
 	}
 	if len(dirs) == 0 {
 		dirs = rc_lib.StringList{"build/release", "vendor/google_shared/build/release", "vendor/google/release"}
@@ -320,12 +357,12 @@
 	if namespacesFile != "" {
 		data, err := os.ReadFile(namespacesFile)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 		for idx, line := range strings.Split(string(data), "\n") {
 			fields := strings.Split(line, " ")
 			if len(fields) > 2 {
-				panic(fmt.Errorf("line %d: too many fields: %s", idx, line))
+				errorExit(fmt.Errorf("line %d: too many fields: %s", idx, line))
 			}
 			namespaceMap[fields[0]] = fields[1]
 		}
@@ -337,7 +374,7 @@
 	if descriptionsFile != "" {
 		data, err := os.ReadFile(descriptionsFile)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 		for _, line := range strings.Split(string(data), "\n") {
 			if strings.TrimSpace(line) != "" {
@@ -351,12 +388,12 @@
 	for _, dir := range dirs {
 		err = ProcessBuildFlags(dir, namespaceMap)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 
 		err = ProcessReleaseConfigMap(dir, descriptionMap)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 	}
 }
diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go
index 22e72a5..c443257 100644
--- a/cmd/release_config/release_config/main.go
+++ b/cmd/release_config/release_config/main.go
@@ -34,6 +34,7 @@
 	var json, pb, textproto bool
 	var product string
 	var allMake bool
+	var useBuildVar bool
 
 	defaultRelease := os.Getenv("TARGET_RELEASE")
 	if defaultRelease == "" {
@@ -50,6 +51,8 @@
 	flag.BoolVar(&json, "json", true, "write artifacts as json")
 	flag.BoolVar(&pb, "pb", true, "write artifacts as binary protobuf")
 	flag.BoolVar(&allMake, "all_make", true, "write makefiles for all release configs")
+	flag.BoolVar(&useBuildVar, "use_get_build_var", false, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS")
+
 	flag.Parse()
 
 	if quiet {
@@ -59,7 +62,7 @@
 	if err = os.Chdir(top); err != nil {
 		panic(err)
 	}
-	configs, err = rc_lib.ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease)
+	configs, err = rc_lib.ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease, useBuildVar)
 	if err != nil {
 		panic(err)
 	}
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index a7a05ae..e51ff08 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -62,6 +62,10 @@
 	// The names of release configs that we inherit
 	InheritNames []string
 
+	// True if this release config only allows inheritance and aconfig flag
+	// overrides. Build flag value overrides are an error.
+	AconfigFlagsOnly bool
+
 	// Unmarshalled flag artifacts
 	FlagArtifacts FlagArtifacts
 
@@ -109,23 +113,17 @@
 	config.FlagArtifacts = configs.FlagArtifacts.Clone()
 	// Add RELEASE_ACONFIG_VALUE_SETS
 	workflowManual := rc_proto.Workflow(rc_proto.Workflow_MANUAL)
-	container := rc_proto.Container(rc_proto.Container_ALL)
 	releaseAconfigValueSets := FlagArtifact{
 		FlagDeclaration: &rc_proto.FlagDeclaration{
 			Name:        proto.String("RELEASE_ACONFIG_VALUE_SETS"),
 			Namespace:   proto.String("android_UNKNOWN"),
 			Description: proto.String("Aconfig value sets assembled by release-config"),
 			Workflow:    &workflowManual,
-			Container:   &container,
-			Value:       &rc_proto.Value{Val: &rc_proto.Value_StringValue{""}},
+			Containers:  []string{"system", "system_ext", "product", "vendor"},
+			Value:       &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}},
 		},
 		DeclarationIndex: -1,
-		Traces: []*rc_proto.Tracepoint{
-			&rc_proto.Tracepoint{
-				Source: proto.String("$release-config"),
-				Value:  &rc_proto.Value{Val: &rc_proto.Value_StringValue{""}},
-			},
-		},
+		Traces:           []*rc_proto.Tracepoint{},
 	}
 	config.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"] = &releaseAconfigValueSets
 
@@ -163,23 +161,26 @@
 	}
 	myDirsMap := make(map[int]bool)
 	for _, contrib := range contributionsToApply {
-		if len(contrib.proto.AconfigValueSets) > 0 {
-			contribAconfigValueSets := []string{}
-			for _, v := range contrib.proto.AconfigValueSets {
-				if _, ok := myAconfigValueSetsMap[v]; !ok {
-					contribAconfigValueSets = append(contribAconfigValueSets, v)
-					myAconfigValueSetsMap[v] = true
-				}
+		contribAconfigValueSets := []string{}
+		// Gather the aconfig_value_sets from this contribution that are not already in the list.
+		for _, v := range contrib.proto.AconfigValueSets {
+			if _, ok := myAconfigValueSetsMap[v]; !ok {
+				contribAconfigValueSets = append(contribAconfigValueSets, v)
+				myAconfigValueSetsMap[v] = true
 			}
-			myAconfigValueSets = append(myAconfigValueSets, contribAconfigValueSets...)
-			releaseAconfigValueSets.Traces = append(
-				releaseAconfigValueSets.Traces,
-				&rc_proto.Tracepoint{
-					Source: proto.String(contrib.path),
-					Value:  &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.Join(contribAconfigValueSets, " ")}},
-				})
 		}
+		myAconfigValueSets = append(myAconfigValueSets, contribAconfigValueSets...)
+		releaseAconfigValueSets.Traces = append(
+			releaseAconfigValueSets.Traces,
+			&rc_proto.Tracepoint{
+				Source: proto.String(contrib.path),
+				Value:  &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.Join(contribAconfigValueSets, " ")}},
+			})
+
 		myDirsMap[contrib.DeclarationIndex] = true
+		if config.AconfigFlagsOnly && len(contrib.FlagValues) > 0 {
+			return fmt.Errorf("%s does not allow build flag overrides", config.Name)
+		}
 		for _, value := range contrib.FlagValues {
 			name := *value.proto.Name
 			fa, ok := config.FlagArtifacts[name]
@@ -214,30 +215,16 @@
 
 	// Now build the per-partition artifacts
 	config.PartitionBuildFlags = make(map[string]*rc_proto.FlagArtifacts)
-	addPartitionArtifact := func(container string, artifact *rc_proto.FlagArtifact) {
-		if _, ok := config.PartitionBuildFlags[container]; !ok {
-			config.PartitionBuildFlags[container] = &rc_proto.FlagArtifacts{}
-		}
-		config.PartitionBuildFlags[container].FlagArtifacts = append(config.PartitionBuildFlags[container].FlagArtifacts, artifact)
-	}
 	for _, v := range config.FlagArtifacts {
-		container := strings.ToLower(rc_proto.Container_name[int32(v.FlagDeclaration.GetContainer())])
 		artifact, err := v.MarshalWithoutTraces()
 		if err != nil {
 			return err
 		}
-		switch container {
-		case "all":
-			for cVal, cName := range rc_proto.Container_name {
-				// Skip unspecified, and "ALL", but place the flag in the rest.
-				if cVal == 0 || cName == "ALL" {
-					continue
-				}
-				cName = strings.ToLower(cName)
-				addPartitionArtifact(cName, artifact)
+		for _, container := range v.FlagDeclaration.Containers {
+			if _, ok := config.PartitionBuildFlags[container]; !ok {
+				config.PartitionBuildFlags[container] = &rc_proto.FlagArtifacts{}
 			}
-		default:
-			addPartitionArtifact(container, artifact)
+			config.PartitionBuildFlags[container].FlagArtifacts = append(config.PartitionBuildFlags[container].FlagArtifacts, artifact)
 		}
 	}
 	config.ReleaseConfigArtifact = &rc_proto.ReleaseConfigArtifact{
diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go
index 3204b18..cedf247 100644
--- a/cmd/release_config/release_config_lib/release_configs.go
+++ b/cmd/release_config/release_config_lib/release_configs.go
@@ -117,9 +117,17 @@
 }
 
 func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error {
+	if _, err := os.Stat(path); err != nil {
+		return fmt.Errorf("%s does not exist\n", path)
+	}
 	m := ReleaseConfigMapFactory(path)
-	if m.proto.DefaultContainer == nil {
-		return fmt.Errorf("Release config map %s lacks default_container", path)
+	if m.proto.DefaultContainers == nil {
+		return fmt.Errorf("Release config map %s lacks default_containers", path)
+	}
+	for _, container := range m.proto.DefaultContainers {
+		if !validContainer(container) {
+			return fmt.Errorf("Release config map %s has invalid container %s", path, container)
+		}
 	}
 	dir := filepath.Dir(path)
 	// Record any aliases, checking for duplicates.
@@ -138,9 +146,16 @@
 	err = WalkTextprotoFiles(dir, "flag_declarations", func(path string, d fs.DirEntry, err error) error {
 		flagDeclaration := FlagDeclarationFactory(path)
 		// Container must be specified.
-		if flagDeclaration.Container == nil {
-			flagDeclaration.Container = m.proto.DefaultContainer
+		if flagDeclaration.Containers == nil {
+			flagDeclaration.Containers = m.proto.DefaultContainers
+		} else {
+			for _, container := range flagDeclaration.Containers {
+				if !validContainer(container) {
+					return fmt.Errorf("Flag declaration %s has invalid container %s", path, container)
+				}
+			}
 		}
+
 		// TODO: once we have namespaces initialized, we can throw an error here.
 		if flagDeclaration.Namespace == nil {
 			flagDeclaration.Namespace = proto.String("android_UNKNOWN")
@@ -194,6 +209,9 @@
 		if err2 != nil {
 			return err2
 		}
+		if releaseConfigContribution.proto.GetAconfigFlagsOnly() {
+			config.AconfigFlagsOnly = true
+		}
 		m.ReleaseConfigContributions[name] = releaseConfigContribution
 		config.Contributions = append(config.Contributions, releaseConfigContribution)
 		return nil
@@ -253,19 +271,12 @@
 		flag := myFlagArtifacts[name]
 		decl := flag.FlagDeclaration
 
-		// cName := strings.ToLower(rc_proto.Container_name[decl.GetContainer()])
-		cName := strings.ToLower(decl.Container.String())
-		if cName == strings.ToLower(rc_proto.Container_ALL.String()) {
-			partitions["product"] = append(partitions["product"], name)
-			partitions["system"] = append(partitions["system"], name)
-			partitions["system_ext"] = append(partitions["system_ext"], name)
-			partitions["vendor"] = append(partitions["vendor"], name)
-		} else {
-			partitions[cName] = append(partitions[cName], name)
+		for _, container := range decl.Containers {
+			partitions[container] = append(partitions[container], name)
 		}
 		value := MarshalValue(flag.Value)
 		makeVars[name] = value
-		addVar(name, "PARTITIONS", cName)
+		addVar(name, "PARTITIONS", strings.Join(decl.Containers, " "))
 		addVar(name, "DEFAULT", MarshalValue(decl.Value))
 		addVar(name, "VALUE", value)
 		addVar(name, "DECLARED_IN", *flag.Traces[0].Source)
@@ -360,15 +371,18 @@
 	return nil
 }
 
-func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string) (*ReleaseConfigs, error) {
+func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string, useBuildVar bool) (*ReleaseConfigs, error) {
 	var err error
 
 	if len(releaseConfigMapPaths) == 0 {
-		releaseConfigMapPaths = GetDefaultMapPaths()
+		releaseConfigMapPaths, err = GetDefaultMapPaths(useBuildVar)
+		if err != nil {
+			return nil, err
+		}
 		if len(releaseConfigMapPaths) == 0 {
 			return nil, fmt.Errorf("No maps found")
 		}
-		fmt.Printf("No --map argument provided.  Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map "))
+		warnf("No --map argument provided.  Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map "))
 	}
 
 	configs := ReleaseConfigsFactory()
@@ -382,6 +396,8 @@
 		mapsRead[configDir] = true
 		configs.configDirIndexes[configDir] = idx
 		configs.configDirs = append(configs.configDirs, configDir)
+		// Force the path to be the textproto path, so that both the scl and textproto formats can coexist.
+		releaseConfigMapPath = filepath.Join(configDir, "release_config_map.textproto")
 		err = configs.LoadReleaseConfigMap(releaseConfigMapPath, idx)
 		if err != nil {
 			return nil, err
diff --git a/cmd/release_config/release_config_lib/util.go b/cmd/release_config/release_config_lib/util.go
index 86940da..c0ea789 100644
--- a/cmd/release_config/release_config_lib/util.go
+++ b/cmd/release_config/release_config_lib/util.go
@@ -19,14 +19,19 @@
 	"fmt"
 	"io/fs"
 	"os"
+	"os/exec"
 	"path/filepath"
+	"regexp"
 	"strings"
 
 	"google.golang.org/protobuf/encoding/prototext"
 	"google.golang.org/protobuf/proto"
 )
 
-var disableWarnings bool
+var (
+	disableWarnings    bool
+	containerRegexp, _ = regexp.Compile("^[a-z][a-z0-9]*([._][a-z][a-z0-9]*)*$")
+)
 
 type StringList []string
 
@@ -123,11 +128,15 @@
 
 func warnf(format string, args ...any) (n int, err error) {
 	if !disableWarnings {
-		return fmt.Printf(format, args...)
+		return fmt.Fprintf(os.Stderr, format, args...)
 	}
 	return 0, nil
 }
 
+func validContainer(container string) bool {
+	return containerRegexp.MatchString(container)
+}
+
 // Returns the default value for release config artifacts.
 func GetDefaultOutDir() string {
 	outEnv := os.Getenv("OUT_DIR")
@@ -137,22 +146,64 @@
 	return filepath.Join(outEnv, "soong", "release-config")
 }
 
+// Find the top of the workspace.
+//
+// This mirrors the logic in build/envsetup.sh's gettop().
+func GetTopDir() (topDir string, err error) {
+	workingDir, err := os.Getwd()
+	if err != nil {
+		return
+	}
+	topFile := "build/make/core/envsetup.mk"
+	for topDir = workingDir; topDir != "/"; topDir = filepath.Dir(topDir) {
+		if _, err = os.Stat(filepath.Join(topDir, topFile)); err == nil {
+			return filepath.Rel(workingDir, topDir)
+		}
+	}
+	return "", fmt.Errorf("Unable to locate top of workspace")
+}
+
 // Return the default list of map files to use.
-func GetDefaultMapPaths() StringList {
-	var defaultMapPaths StringList
-	defaultLocations := StringList{
+func GetDefaultMapPaths(queryMaps bool) (defaultMapPaths StringList, err error) {
+	var defaultLocations StringList
+	workingDir, err := os.Getwd()
+	if err != nil {
+		return
+	}
+	defer func() {
+		os.Chdir(workingDir)
+	}()
+	topDir, err := GetTopDir()
+	os.Chdir(topDir)
+
+	defaultLocations = StringList{
 		"build/release/release_config_map.textproto",
 		"vendor/google_shared/build/release/release_config_map.textproto",
 		"vendor/google/release/release_config_map.textproto",
 	}
 	for _, path := range defaultLocations {
-		if _, err := os.Stat(path); err == nil {
+		if _, err = os.Stat(path); err == nil {
 			defaultMapPaths = append(defaultMapPaths, path)
 		}
 	}
-	prodMaps := os.Getenv("PRODUCT_RELEASE_CONFIG_MAPS")
-	if prodMaps != "" {
+
+	var prodMaps string
+	if queryMaps {
+		getBuildVar := exec.Command("build/soong/soong_ui.bash", "--dumpvar-mode", "PRODUCT_RELEASE_CONFIG_MAPS")
+		var stdout strings.Builder
+		getBuildVar.Stdin = strings.NewReader("")
+		getBuildVar.Stdout = &stdout
+		err = getBuildVar.Run()
+		if err != nil {
+			return
+		}
+		prodMaps = stdout.String()
+	} else {
+		prodMaps = os.Getenv("PRODUCT_RELEASE_CONFIG_MAPS")
+	}
+	prodMaps = strings.TrimSpace(prodMaps)
+	if len(prodMaps) > 0 {
 		defaultMapPaths = append(defaultMapPaths, strings.Split(prodMaps, " ")...)
 	}
-	return defaultMapPaths
+	return
 }
diff --git a/cmd/release_config/release_config_proto/build_flags_src.pb.go b/cmd/release_config/release_config_proto/build_flags_src.pb.go
index ca2005c..dded975 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_src.pb.go
@@ -98,76 +98,6 @@
 	return file_build_flags_src_proto_rawDescGZIP(), []int{0}
 }
 
-type Container int32
-
-const (
-	Container_UNSPECIFIED_container Container = 0
-	// All containers
-	Container_ALL Container = 1
-	// Specific containers
-	Container_PRODUCT    Container = 2
-	Container_SYSTEM     Container = 3
-	Container_SYSTEM_EXT Container = 4
-	Container_VENDOR     Container = 5
-)
-
-// Enum value maps for Container.
-var (
-	Container_name = map[int32]string{
-		0: "UNSPECIFIED_container",
-		1: "ALL",
-		2: "PRODUCT",
-		3: "SYSTEM",
-		4: "SYSTEM_EXT",
-		5: "VENDOR",
-	}
-	Container_value = map[string]int32{
-		"UNSPECIFIED_container": 0,
-		"ALL":                   1,
-		"PRODUCT":               2,
-		"SYSTEM":                3,
-		"SYSTEM_EXT":            4,
-		"VENDOR":                5,
-	}
-)
-
-func (x Container) Enum() *Container {
-	p := new(Container)
-	*p = x
-	return p
-}
-
-func (x Container) String() string {
-	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (Container) Descriptor() protoreflect.EnumDescriptor {
-	return file_build_flags_src_proto_enumTypes[1].Descriptor()
-}
-
-func (Container) Type() protoreflect.EnumType {
-	return &file_build_flags_src_proto_enumTypes[1]
-}
-
-func (x Container) Number() protoreflect.EnumNumber {
-	return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Do not use.
-func (x *Container) UnmarshalJSON(b []byte) error {
-	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
-	if err != nil {
-		return err
-	}
-	*x = Container(num)
-	return nil
-}
-
-// Deprecated: Use Container.Descriptor instead.
-func (Container) EnumDescriptor() ([]byte, []int) {
-	return file_build_flags_src_proto_rawDescGZIP(), []int{1}
-}
-
 type Value struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -298,7 +228,7 @@
 	Workflow *Workflow `protobuf:"varint,205,opt,name=workflow,enum=android.release_config_proto.Workflow" json:"workflow,omitempty"`
 	// The container for this flag.  This overrides any default container given
 	// in the release_config_map message.
-	Container *Container `protobuf:"varint,206,opt,name=container,enum=android.release_config_proto.Container" json:"container,omitempty"`
+	Containers []string `protobuf:"bytes,206,rep,name=containers" json:"containers,omitempty"`
 }
 
 func (x *FlagDeclaration) Reset() {
@@ -368,11 +298,11 @@
 	return Workflow_UNSPECIFIED_workflow
 }
 
-func (x *FlagDeclaration) GetContainer() Container {
-	if x != nil && x.Container != nil {
-		return *x.Container
+func (x *FlagDeclaration) GetContainers() []string {
+	if x != nil {
+		return x.Containers
 	}
-	return Container_UNSPECIFIED_container
+	return nil
 }
 
 type FlagValue struct {
@@ -457,6 +387,8 @@
 	// List of names of the aconfig_value_set soong module(s) for this
 	// contribution.
 	AconfigValueSets []string `protobuf:"bytes,3,rep,name=aconfig_value_sets,json=aconfigValueSets" json:"aconfig_value_sets,omitempty"`
+	// Only aconfig flags are allowed in this release config.
+	AconfigFlagsOnly *bool `protobuf:"varint,4,opt,name=aconfig_flags_only,json=aconfigFlagsOnly" json:"aconfig_flags_only,omitempty"`
 }
 
 func (x *ReleaseConfig) Reset() {
@@ -512,6 +444,13 @@
 	return nil
 }
 
+func (x *ReleaseConfig) GetAconfigFlagsOnly() bool {
+	if x != nil && x.AconfigFlagsOnly != nil {
+		return *x.AconfigFlagsOnly
+	}
+	return false
+}
+
 // Any aliases.  These are used for continuous integration builder config.
 type ReleaseAlias struct {
 	state         protoimpl.MessageState
@@ -581,7 +520,7 @@
 	// Description of this map and its intended use.
 	Description *string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"`
 	// The default container for flags declared here.
-	DefaultContainer *Container `protobuf:"varint,3,opt,name=default_container,json=defaultContainer,enum=android.release_config_proto.Container" json:"default_container,omitempty"`
+	DefaultContainers []string `protobuf:"bytes,3,rep,name=default_containers,json=defaultContainers" json:"default_containers,omitempty"`
 }
 
 func (x *ReleaseConfigMap) Reset() {
@@ -630,11 +569,11 @@
 	return ""
 }
 
-func (x *ReleaseConfigMap) GetDefaultContainer() Container {
-	if x != nil && x.DefaultContainer != nil {
-		return *x.DefaultContainer
+func (x *ReleaseConfigMap) GetDefaultContainers() []string {
+	if x != nil {
+		return x.DefaultContainers
 	}
-	return Container_UNSPECIFIED_container
+	return nil
 }
 
 var File_build_flags_src_proto protoreflect.FileDescriptor
@@ -653,7 +592,7 @@
 	0x6c, 0x75, 0x65, 0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f,
 	0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x08, 0x6f, 0x62, 0x73, 0x6f, 0x6c,
 	0x65, 0x74, 0x65, 0x18, 0xcb, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x6f, 0x62,
-	0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x22, 0xbd, 0x02,
+	0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x96, 0x02,
 	0x0a, 0x10, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69,
 	0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
 	0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
@@ -668,59 +607,50 @@
 	0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
 	0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70,
 	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x08, 0x77,
-	0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x46, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61,
-	0x69, 0x6e, 0x65, 0x72, 0x18, 0xce, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x61, 0x6e,
-	0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
-	0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4a,
-	0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x06, 0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01, 0x22, 0x79, 0x0a,
-	0x0a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-	0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x23, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
-	0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x08, 0x72,
-	0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64, 0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
-	0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64, 0x22, 0x6e, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65,
-	0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a,
-	0x0a, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
-	0x52, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73,
-	0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56,
-	0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x74, 0x73, 0x22, 0x3b, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x65,
-	0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a,
-	0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74,
-	0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
-	0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x12, 0x45, 0x0a, 0x07,
-	0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
-	0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f,
-	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c,
-	0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61,
-	0x73, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
-	0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
-	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x54, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
-	0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e,
-	0x32, 0x27, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61,
-	0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, 0x75,
-	0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2a, 0x4a, 0x0a, 0x08, 0x77,
-	0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x4e, 0x53, 0x50, 0x45,
-	0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x10,
-	0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c, 0x0a,
-	0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d,
-	0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x64, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61,
-	0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
-	0x49, 0x45, 0x44, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x10, 0x00, 0x12,
-	0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x44,
-	0x55, 0x43, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10,
-	0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x45, 0x58, 0x54, 0x10,
-	0x04, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45, 0x4e, 0x44, 0x4f, 0x52, 0x10, 0x05, 0x42, 0x33, 0x5a,
-	0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72,
-	0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65,
-	0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f,
-	0x74, 0x6f,
+	0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61,
+	0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0xce, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x06,
+	0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01, 0x22, 0x79, 0x0a, 0x0a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+	0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x08, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64,
+	0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x65,
+	0x64, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x68, 0x65,
+	0x72, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x68, 0x65,
+	0x72, 0x69, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
+	0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65,
+	0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x66, 0x6c,
+	0x61, 0x67, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10,
+	0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x4f, 0x6e, 0x6c, 0x79,
+	0x22, 0x3b, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61,
+	0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xac, 0x01,
+	0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x5f, 0x6d, 0x61, 0x70, 0x12, 0x45, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18,
+	0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
+	0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69,
+	0x61, 0x73, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64,
+	0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a,
+	0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
+	0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75,
+	0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2a, 0x4a, 0x0a, 0x08,
+	0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x4e, 0x53, 0x50,
+	0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
+	0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c,
+	0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06,
+	0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72,
+	0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
+	0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
+	0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 }
 
 var (
@@ -735,30 +665,27 @@
 	return file_build_flags_src_proto_rawDescData
 }
 
-var file_build_flags_src_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
+var file_build_flags_src_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
 var file_build_flags_src_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
 var file_build_flags_src_proto_goTypes = []interface{}{
 	(Workflow)(0),            // 0: android.release_config_proto.workflow
-	(Container)(0),           // 1: android.release_config_proto.container
-	(*Value)(nil),            // 2: android.release_config_proto.value
-	(*FlagDeclaration)(nil),  // 3: android.release_config_proto.flag_declaration
-	(*FlagValue)(nil),        // 4: android.release_config_proto.flag_value
-	(*ReleaseConfig)(nil),    // 5: android.release_config_proto.release_config
-	(*ReleaseAlias)(nil),     // 6: android.release_config_proto.release_alias
-	(*ReleaseConfigMap)(nil), // 7: android.release_config_proto.release_config_map
+	(*Value)(nil),            // 1: android.release_config_proto.value
+	(*FlagDeclaration)(nil),  // 2: android.release_config_proto.flag_declaration
+	(*FlagValue)(nil),        // 3: android.release_config_proto.flag_value
+	(*ReleaseConfig)(nil),    // 4: android.release_config_proto.release_config
+	(*ReleaseAlias)(nil),     // 5: android.release_config_proto.release_alias
+	(*ReleaseConfigMap)(nil), // 6: android.release_config_proto.release_config_map
 }
 var file_build_flags_src_proto_depIdxs = []int32{
-	2, // 0: android.release_config_proto.flag_declaration.value:type_name -> android.release_config_proto.value
+	1, // 0: android.release_config_proto.flag_declaration.value:type_name -> android.release_config_proto.value
 	0, // 1: android.release_config_proto.flag_declaration.workflow:type_name -> android.release_config_proto.workflow
-	1, // 2: android.release_config_proto.flag_declaration.container:type_name -> android.release_config_proto.container
-	2, // 3: android.release_config_proto.flag_value.value:type_name -> android.release_config_proto.value
-	6, // 4: android.release_config_proto.release_config_map.aliases:type_name -> android.release_config_proto.release_alias
-	1, // 5: android.release_config_proto.release_config_map.default_container:type_name -> android.release_config_proto.container
-	6, // [6:6] is the sub-list for method output_type
-	6, // [6:6] is the sub-list for method input_type
-	6, // [6:6] is the sub-list for extension type_name
-	6, // [6:6] is the sub-list for extension extendee
-	0, // [0:6] is the sub-list for field type_name
+	1, // 2: android.release_config_proto.flag_value.value:type_name -> android.release_config_proto.value
+	5, // 3: android.release_config_proto.release_config_map.aliases:type_name -> android.release_config_proto.release_alias
+	4, // [4:4] is the sub-list for method output_type
+	4, // [4:4] is the sub-list for method input_type
+	4, // [4:4] is the sub-list for extension type_name
+	4, // [4:4] is the sub-list for extension extendee
+	0, // [0:4] is the sub-list for field type_name
 }
 
 func init() { file_build_flags_src_proto_init() }
@@ -851,7 +778,7 @@
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_build_flags_src_proto_rawDesc,
-			NumEnums:      2,
+			NumEnums:      1,
 			NumMessages:   6,
 			NumExtensions: 0,
 			NumServices:   0,
diff --git a/cmd/release_config/release_config_proto/build_flags_src.proto b/cmd/release_config/release_config_proto/build_flags_src.proto
index 92edc2a..0ef1a5f 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.proto
+++ b/cmd/release_config/release_config_proto/build_flags_src.proto
@@ -53,19 +53,6 @@
   MANUAL = 3;
 }
 
-enum container {
-  UNSPECIFIED_container = 0;
-
-  // All containers
-  ALL = 1;
-
-  // Specific containers
-  PRODUCT = 2;
-  SYSTEM = 3;
-  SYSTEM_EXT = 4;
-  VENDOR = 5;
-}
-
 message value {
   oneof val {
     bool unspecified_value = 200;
@@ -100,7 +87,7 @@
 
   // The container for this flag.  This overrides any default container given
   // in the release_config_map message.
-  optional container container = 206;
+  repeated string containers = 206;
 
   // The package associated with this flag.
   // (when Gantry is ready for it) optional string package = 207;
@@ -132,6 +119,9 @@
   // List of names of the aconfig_value_set soong module(s) for this
   // contribution.
   repeated string aconfig_value_sets = 3;
+
+  // Only aconfig flags are allowed in this release config.
+  optional bool aconfig_flags_only = 4;
 }
 
 // Any aliases.  These are used for continuous integration builder config.
@@ -152,7 +142,7 @@
   optional string description = 2;
 
   // The default container for flags declared here.
-  optional container default_container = 3;
+  repeated string default_containers = 3;
 
   // If needed, we can add these fields instead of hardcoding the location.
   // Flag declarations: `flag_declarations/*.textproto`
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 3a5071d..1215048 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -299,43 +299,6 @@
 		cmd, "--include_descriptors_from_image ")
 }
 
-func TestFileSystemShouldInstallCoreVariantIfTargetBuildAppsIsSet(t *testing.T) {
-	context := android.GroupFixturePreparers(
-		fixture,
-		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
-			variables.Unbundled_build_apps = []string{"bar"}
-		}),
-	)
-	result := context.RunTestWithBp(t, `
-		android_system_image {
-			name: "myfilesystem",
-			deps: [
-				"libfoo",
-			],
-			linker_config_src: "linker.config.json",
-		}
-
-		cc_library {
-			name: "libfoo",
-			shared_libs: [
-				"libbar",
-			],
-			stl: "none",
-		}
-
-		cc_library {
-			name: "libbar",
-			sdk_version: "9",
-			stl: "none",
-		}
-	`)
-
-	inputs := result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img").Implicits
-	android.AssertStringListContains(t, "filesystem should have libbar even for unbundled build",
-		inputs.Strings(),
-		"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
-}
-
 func TestFileSystemWithCoverageVariants(t *testing.T) {
 	context := android.GroupFixturePreparers(
 		fixture,
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 0ebab4d..07bc5c1 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -151,10 +151,14 @@
 	return jars
 }
 
+func (c *ClasspathFragmentBase) outputFilename() string {
+	return strings.ToLower(c.classpathType.String()) + ".pb"
+}
+
 func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, jars []classpathJar) {
 	generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true)
 	if generateProto {
-		outputFilename := strings.ToLower(c.classpathType.String()) + ".pb"
+		outputFilename := c.outputFilename()
 		c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
 		c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
 
@@ -181,6 +185,10 @@
 	android.SetProvider(ctx, ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
 }
 
+func (c *ClasspathFragmentBase) installClasspathProto(ctx android.ModuleContext) android.InstallPath {
+	return ctx.InstallFile(c.installDirPath, c.outputFilename(), c.outputFilepath)
+}
+
 func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
 	var content strings.Builder
 
diff --git a/java/droidstubs.go b/java/droidstubs.go
index ffd3caf..08caf91 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -614,11 +614,36 @@
 
 	filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
 
+	// TODO: Avoid the duplication of API surfaces, reuse apiScope.
+	// Add all relevant --android-jar-pattern patterns for Metalava.
+	// When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
+	// an actual file present on disk (in the order the patterns were passed). For system APIs for
+	// privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
+	// for older releases. Similarly, module-lib falls back to system API.
+	var sdkDirs []string
+	switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
+	case "system-server":
+		sdkDirs = []string{"system-server", "module-lib", "system", "public"}
+	case "module-lib":
+		sdkDirs = []string{"module-lib", "system", "public"}
+	case "system":
+		sdkDirs = []string{"system", "public"}
+	case "public":
+		sdkDirs = []string{"public"}
+	default:
+		ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
+		return
+	}
+
+	// Use the first item in the sdkDirs array as that is the sdk type for the target API levels
+	// being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
+	extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/%s/.*\.jar`, sdkDirs[0])
+
 	var dirs []string
 	var extensions_dir string
 	ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
 		if t, ok := m.(*ExportedDroiddocDir); ok {
-			extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
+			extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern)
 
 			// Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
 			// ideally this should be read from prebuiltApis.properties.Extensions_*
@@ -650,26 +675,6 @@
 		}
 	})
 
-	// Add all relevant --android-jar-pattern patterns for Metalava.
-	// When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
-	// an actual file present on disk (in the order the patterns were passed). For system APIs for
-	// privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
-	// for older releases. Similarly, module-lib falls back to system API.
-	var sdkDirs []string
-	switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
-	case "system-server":
-		sdkDirs = []string{"system-server", "module-lib", "system", "public"}
-	case "module-lib":
-		sdkDirs = []string{"module-lib", "system", "public"}
-	case "system":
-		sdkDirs = []string{"system", "public"}
-	case "public":
-		sdkDirs = []string{"public"}
-	default:
-		ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
-		return
-	}
-
 	for _, sdkDir := range sdkDirs {
 		for _, dir := range dirs {
 			cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 4db426e..b3c9ce5 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -221,6 +221,7 @@
 	// ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH
 	classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
 	b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
+	b.classpathFragmentBase().installClasspathProto(ctx)
 }
 
 func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index b291e70..bad2cf1 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -69,6 +69,7 @@
 	configuredJars = configuredJars.AppendList(&standaloneConfiguredJars)
 	classpathJars = append(classpathJars, standaloneClasspathJars...)
 	p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
+	p.classpathFragmentBase().installClasspathProto(ctx)
 }
 
 func (p *platformSystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
diff --git a/python/scripts/precompile_python.py b/python/scripts/precompile_python.py
index 07b8fe9..b3cf950 100644
--- a/python/scripts/precompile_python.py
+++ b/python/scripts/precompile_python.py
@@ -30,6 +30,7 @@
     # Date was chosen to be the same as
     # https://cs.android.com/android/platform/superproject/main/+/main:build/soong/jar/jar.go;l=36;drc=2863e4535eb65e15f955dc8ed48fa99b1d2a1db5
     info = zipfile.ZipInfo(filename=name, date_time=(2008, 1, 1, 0, 0, 0))
+    info.compress_type = zipfile.ZIP_DEFLATED
 
     if not info.filename.endswith('.py'):
         outzip.writestr(info, infile.read())
diff --git a/rust/config/global.go b/rust/config/global.go
index ba08560..03333b8 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -53,6 +53,9 @@
 		"--color=always",
 		"-Z dylib-lto",
 		"-Z link-native-libraries=no",
+
+		// cfg flag to indicate that we are building in AOSP with Soong
+		"--cfg soong",
 	}
 
 	LinuxHostGlobalLinkFlags = []string{
diff --git a/rust/project_json.go b/rust/project_json.go
index ad9b690..05fc09b 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -96,7 +96,7 @@
 		var childId int
 		cInfo, known := singleton.knownCrates[rChild.Name()]
 		if !known {
-			childId, ok = singleton.addCrate(ctx, rChild, make(map[string]int))
+			childId, ok = singleton.addCrate(ctx, rChild)
 			if !ok {
 				return
 			}
@@ -128,7 +128,8 @@
 // addCrate adds a crate to singleton.project.Crates ensuring that required
 // dependencies are also added. It returns the index of the new crate in
 // singleton.project.Crates
-func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, deps map[string]int) (int, bool) {
+func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module) (int, bool) {
+	deps := make(map[string]int)
 	rootModule, err := rModule.compiler.checkedCrateRootPath()
 	if err != nil {
 		return 0, false
@@ -180,7 +181,7 @@
 	if cInfo, ok := singleton.knownCrates[module.Name()]; ok {
 		// If we have a new device variant, override the old one
 		if !cInfo.Device && rModule.Device() {
-			singleton.addCrate(ctx, rModule, cInfo.Deps)
+			singleton.addCrate(ctx, rModule)
 			return
 		}
 		crate := singleton.project.Crates[cInfo.Idx]
@@ -188,7 +189,7 @@
 		singleton.project.Crates[cInfo.Idx] = crate
 		return
 	}
-	singleton.addCrate(ctx, rModule, make(map[string]int))
+	singleton.addCrate(ctx, rModule)
 }
 
 func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go
index 9127f67..b2d5631 100644
--- a/tradefed_modules/test_module_config.go
+++ b/tradefed_modules/test_module_config.go
@@ -160,35 +160,17 @@
 
 }
 
-// Any test suites in base should not be repeated in the derived class, except "general-tests".
-// We may restrict derived tests to only be "general-tests" as it doesn't make sense to add a slice
-// of a test to compatibility suite.
+// Ensure at least one test_suite is listed.  Ideally it should be general-tests
+// or device-tests, whichever is listed in base and prefer general-tests if both are listed.
+// However this is not enforced yet.
 //
-// Returns ErrorMessage, false on problems
-// Returns _, true if okay.
+// Returns true if okay and reports errors via ModuleErrorf.
 func (m *testModuleConfigModule) validateTestSuites(ctx android.ModuleContext) bool {
 	if len(m.tradefedProperties.Test_suites) == 0 {
-		ctx.ModuleErrorf("At least one test-suite must be set or this won't run. Use \"general-tests\"")
+		ctx.ModuleErrorf("At least one test-suite must be set or this won't run. Use \"general-tests\" or \"device-tests\"")
 		return false
 	}
 
-	derivedSuites := make(map[string]bool)
-	// See if any suites in base is also in derived (other than general-tests)
-	for _, s := range m.tradefedProperties.Test_suites {
-		if s != "general-tests" {
-			derivedSuites[s] = true
-		}
-	}
-	if len(derivedSuites) == 0 {
-		return true
-	}
-	for _, baseSuite := range m.provider.TestSuites {
-		if derivedSuites[baseSuite] {
-			ctx.ModuleErrorf("TestSuite %s exists in the base, do not add it here", baseSuite)
-			return false
-		}
-	}
-
 	return true
 }
 
diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go
index 6997228..b2049b1 100644
--- a/tradefed_modules/test_module_config_test.go
+++ b/tradefed_modules/test_module_config_test.go
@@ -325,30 +325,6 @@
 		RunTestWithBp(t, badBp)
 }
 
-func TestModuleConfigHostDuplicateTestSuitesGiveErrors(t *testing.T) {
-	badBp := `
-		java_test_host {
-			name: "base",
-                        srcs: ["a.java"],
-                        test_suites: ["general-tests", "some-compat"],
-		}
-
-                test_module_config_host {
-                        name: "derived_test",
-                        base: "base",
-                        exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
-                        include_annotations: ["android.platform.test.annotations.LargeTest"],
-                        test_suites: ["general-tests", "some-compat"],
-                }`
-
-	android.GroupFixturePreparers(
-		java.PrepareForTestWithJavaDefaultModules,
-		android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
-	).ExtendWithErrorHandler(
-		android.FixtureExpectsAtLeastOneErrorMatchingPattern("TestSuite some-compat exists in the base")).
-		RunTestWithBp(t, badBp)
-}
-
 func TestTestOnlyProvider(t *testing.T) {
 	t.Parallel()
 	ctx := android.GroupFixturePreparers(