Merge "Filter ABI dumps by LLNDK headers and version scripts" into main
diff --git a/android/Android.bp b/android/Android.bp
index 03619f4..4c59592 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -41,7 +41,6 @@
         "buildinfo_prop.go",
         "config.go",
         "test_config.go",
-        "config_bp2build.go",
         "configured_jars.go",
         "csuite_config.go",
         "deapexer.go",
@@ -90,6 +89,7 @@
         "sandbox.go",
         "sdk.go",
         "sdk_version.go",
+        "shared_properties.go",
         "singleton.go",
         "singleton_module.go",
         "soong_config_modules.go",
@@ -103,6 +103,7 @@
         "visibility.go",
     ],
     testSrcs: [
+        "all_teams_test.go",
         "android_test.go",
         "androidmk_test.go",
         "apex_test.go",
diff --git a/android/all_teams.go b/android/all_teams.go
index b177e20..0c433a6 100644
--- a/android/all_teams.go
+++ b/android/all_teams.go
@@ -23,9 +23,18 @@
 }
 
 // For each module, list the team or the bpFile the module is defined in.
-type moduleTeamInfo struct {
+type moduleTeamAndTestInfo struct {
+	// Name field from bp file for the team
 	teamName string
-	bpFile   string
+	// Blueprint file the module is located in.
+	bpFile string
+	// Is this module only used by tests.
+	testOnly bool
+	// Is this a directly testable target by running the module directly
+	// or via tradefed.
+	topLevelTestTarget bool
+	// String name indicating the module, like `java_library` for reporting.
+	kind string
 }
 
 type allTeamsSingleton struct {
@@ -37,16 +46,16 @@
 	// Map of all team modules we visit during GenerateBuildActions
 	teams map[string]teamProperties
 	// Keeps track of team information or bp file for each module we visit.
-	teams_for_mods map[string]moduleTeamInfo
+	teams_for_mods map[string]moduleTeamAndTestInfo
 }
 
 // See if there is a package module for the given bpFilePath with a team defined, if so return the team.
 // If not ascend up to the parent directory and do the same.
-func (this *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
+func (t *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
 	// return the Default_team listed in the package if is there.
-	if p, ok := this.packages[bpFilePath]; ok {
-		if t := p.Default_team; t != nil {
-			return this.teams[*p.Default_team], true
+	if p, ok := t.packages[bpFilePath]; ok {
+		if defaultTeam := p.Default_team; defaultTeam != nil {
+			return t.teams[*defaultTeam], true
 		}
 	}
 	// Strip a directory and go up.
@@ -57,72 +66,79 @@
 	if current == "." {
 		return teamProperties{}, false
 	}
-	return this.lookupDefaultTeam(filepath.Join(parent, base))
+	return t.lookupDefaultTeam(filepath.Join(parent, base))
 }
 
-// Create a rule to run a tool to collect all the intermediate files
-// which list the team per module into one proto file.
-func (this *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
-	this.packages = make(map[string]packageProperties)
-	this.teams = make(map[string]teamProperties)
-	this.teams_for_mods = make(map[string]moduleTeamInfo)
+// Visit all modules and collect all teams and use WriteFileRuleVerbatim
+// to write it out.
+func (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
+	t.packages = make(map[string]packageProperties)
+	t.teams = make(map[string]teamProperties)
+	t.teams_for_mods = make(map[string]moduleTeamAndTestInfo)
 
 	ctx.VisitAllModules(func(module Module) {
 		bpFile := ctx.BlueprintFile(module)
 
+		testModInfo := TestModuleInformation{}
+		if tmi, ok := SingletonModuleProvider(ctx, module, TestOnlyProviderKey); ok {
+			testModInfo = tmi
+		}
+
 		// Package Modules and Team Modules are stored in a map so we can look them up by name for
 		// modules without a team.
 		if pack, ok := module.(*packageModule); ok {
-			// Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in this context.
+			// Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in t context.
 			pkgKey := bpFile
-			this.packages[pkgKey] = pack.properties
+			t.packages[pkgKey] = pack.properties
 			return
 		}
 		if team, ok := module.(*teamModule); ok {
-			this.teams[team.Name()] = team.properties
+			t.teams[team.Name()] = team.properties
 			return
 		}
 
-		// If a team name is given for a module, store it.
-		// Otherwise store the bpFile so we can do a package walk later.
-		if module.base().Team() != "" {
-			this.teams_for_mods[module.Name()] = moduleTeamInfo{teamName: module.base().Team(), bpFile: bpFile}
-		} else {
-			this.teams_for_mods[module.Name()] = moduleTeamInfo{bpFile: bpFile}
+		entry := moduleTeamAndTestInfo{
+			bpFile:             bpFile,
+			testOnly:           testModInfo.TestOnly,
+			topLevelTestTarget: testModInfo.TopLevelTarget,
+			kind:               ctx.ModuleType(module),
+			teamName:           module.base().Team(),
 		}
+		t.teams_for_mods[module.Name()] = entry
+
 	})
 
 	// Visit all modules again and lookup the team name in the package or parent package if the team
 	// isn't assignged at the module level.
-	allTeams := this.lookupTeamForAllModules()
+	allTeams := t.lookupTeamForAllModules()
 
-	this.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
+	t.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
 	data, err := proto.Marshal(allTeams)
 	if err != nil {
 		ctx.Errorf("Unable to marshal team data. %s", err)
 	}
 
-	WriteFileRuleVerbatim(ctx, this.outputPath, string(data))
-	ctx.Phony("all_teams", this.outputPath)
+	WriteFileRuleVerbatim(ctx, t.outputPath, string(data))
+	ctx.Phony("all_teams", t.outputPath)
 }
 
-func (this *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
-	ctx.DistForGoal("all_teams", this.outputPath)
+func (t *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
+	ctx.DistForGoal("all_teams", t.outputPath)
 }
 
 // Visit every (non-package, non-team) module and write out a proto containing
 // either the declared team data for that module or the package default team data for that module.
-func (this *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
-	teamsProto := make([]*team_proto.Team, len(this.teams_for_mods))
-	for i, moduleName := range SortedKeys(this.teams_for_mods) {
-		m, _ := this.teams_for_mods[moduleName]
+func (t *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
+	teamsProto := make([]*team_proto.Team, len(t.teams_for_mods))
+	for i, moduleName := range SortedKeys(t.teams_for_mods) {
+		m, _ := t.teams_for_mods[moduleName]
 		teamName := m.teamName
 		var teamProperties teamProperties
 		found := false
 		if teamName != "" {
-			teamProperties, found = this.teams[teamName]
+			teamProperties, found = t.teams[teamName]
 		} else {
-			teamProperties, found = this.lookupDefaultTeam(m.bpFile)
+			teamProperties, found = t.lookupDefaultTeam(m.bpFile)
 		}
 
 		trendy_team_id := ""
@@ -130,22 +146,18 @@
 			trendy_team_id = *teamProperties.Trendy_team_id
 		}
 
-		var files []string
 		teamData := new(team_proto.Team)
+		*teamData = team_proto.Team{
+			TargetName:     proto.String(moduleName),
+			Path:           proto.String(m.bpFile),
+			TestOnly:       proto.Bool(m.testOnly),
+			TopLevelTarget: proto.Bool(m.topLevelTestTarget),
+			Kind:           proto.String(m.kind),
+		}
 		if trendy_team_id != "" {
-			*teamData = team_proto.Team{
-				TrendyTeamId: proto.String(trendy_team_id),
-				TargetName:   proto.String(moduleName),
-				Path:         proto.String(m.bpFile),
-				File:         files,
-			}
+			teamData.TrendyTeamId = proto.String(trendy_team_id)
 		} else {
 			// Clients rely on the TrendyTeamId optional field not being set.
-			*teamData = team_proto.Team{
-				TargetName: proto.String(moduleName),
-				Path:       proto.String(m.bpFile),
-				File:       files,
-			}
 		}
 		teamsProto[i] = teamData
 	}
diff --git a/android/all_teams_test.go b/android/all_teams_test.go
index a02b86e..9c2b38e 100644
--- a/android/all_teams_test.go
+++ b/android/all_teams_test.go
@@ -24,9 +24,8 @@
 func TestAllTeams(t *testing.T) {
 	t.Parallel()
 	ctx := GroupFixturePreparers(
-		PrepareForTestWithTeamBuildComponents,
+		prepareForTestWithTeamAndFakes,
 		FixtureRegisterWithContext(func(ctx RegistrationContext) {
-			ctx.RegisterModuleType("fake", fakeModuleFactory)
 			ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
 		}),
 	).RunTestWithBp(t, `
@@ -51,6 +50,12 @@
 
 		fake {
 			name: "noteam",
+                        test_only: true,
+		}
+		fake {
+			name: "test-and-team-and-top",
+                        test_only: true,
+                        team: "team2",
 		}
 	`)
 
@@ -59,16 +64,31 @@
 
 	// map of module name -> trendy team name.
 	actualTeams := make(map[string]*string)
+	actualTests := []string{}
+	actualTopLevelTests := []string{}
+
 	for _, teamProto := range teams.Teams {
 		actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+		if teamProto.GetTestOnly() {
+			actualTests = append(actualTests, teamProto.GetTargetName())
+		}
+		if teamProto.GetTopLevelTarget() {
+			actualTopLevelTests = append(actualTopLevelTests, teamProto.GetTargetName())
+		}
 	}
 	expectedTeams := map[string]*string{
-		"main_test": proto.String("cool_team"),
-		"tool":      proto.String("22222"),
-		"noteam":    nil,
+		"main_test":             proto.String("cool_team"),
+		"tool":                  proto.String("22222"),
+		"test-and-team-and-top": proto.String("22222"),
+		"noteam":                nil,
 	}
 
+	expectedTests := []string{
+		"noteam",
+		"test-and-team-and-top",
+	}
 	AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+	AssertDeepEquals(t, "test matchup", expectedTests, actualTests)
 }
 
 func getTeamProtoOutput(t *testing.T, ctx *TestResult) *team_proto.AllTeams {
@@ -171,10 +191,9 @@
 		} `
 
 	ctx := GroupFixturePreparers(
-		PrepareForTestWithTeamBuildComponents,
+		prepareForTestWithTeamAndFakes,
 		PrepareForTestWithPackageModule,
 		FixtureRegisterWithContext(func(ctx RegistrationContext) {
-			ctx.RegisterModuleType("fake", fakeModuleFactory)
 			ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
 		}),
 		FixtureAddTextFile("Android.bp", rootBp),
@@ -206,3 +225,33 @@
 	}
 	AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
 }
+
+type fakeForTests struct {
+	ModuleBase
+
+	sourceProperties SourceProperties
+}
+
+func fakeFactory() Module {
+	module := &fakeForTests{}
+	module.AddProperties(&module.sourceProperties)
+	InitAndroidModule(module)
+
+	return module
+}
+
+var prepareForTestWithTeamAndFakes = GroupFixturePreparers(
+	FixtureRegisterWithContext(RegisterTeamBuildComponents),
+	FixtureRegisterWithContext(func(ctx RegistrationContext) {
+		ctx.RegisterModuleType("fake", fakeFactory)
+	}),
+)
+
+func (f *fakeForTests) GenerateAndroidBuildActions(ctx ModuleContext) {
+	if Bool(f.sourceProperties.Test_only) {
+		SetProvider(ctx, TestOnlyProviderKey, TestModuleInformation{
+			TestOnly:       Bool(f.sourceProperties.Test_only),
+			TopLevelTarget: false,
+		})
+	}
+}
diff --git a/android/arch.go b/android/arch.go
index 9e79e31..27ce4d4 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -980,7 +980,7 @@
 			panic(fmt.Errorf("unexpected tag format %q", field.Tag))
 		}
 		// these tags don't need to be present in the runtime generated struct type.
-		values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
+		values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path", "replace_instead_of_append"})
 		if len(values) > 0 {
 			panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
 		}
diff --git a/android/config.go b/android/config.go
index 47e10d6..11bd81b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1441,10 +1441,6 @@
 	return "vendor"
 }
 
-func (c *deviceConfig) VndkVersion() string {
-	return String(c.config.productVariables.DeviceVndkVersion)
-}
-
 func (c *deviceConfig) RecoverySnapshotVersion() string {
 	return String(c.config.productVariables.RecoverySnapshotVersion)
 }
diff --git a/android/config_bp2build.go b/android/config_bp2build.go
deleted file mode 100644
index 4c2fb5e..0000000
--- a/android/config_bp2build.go
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2021 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 android
-
-import (
-	"strings"
-
-	"github.com/google/blueprint"
-)
-
-// ExportedVariables is a collection of interdependent configuration variables
-type ExportedVariables struct {
-	// Maps containing toolchain variables that are independent of the
-	// environment variables of the build.
-	exportedStringVars         ExportedStringVariables
-	exportedStringListVars     ExportedStringListVariables
-	exportedStringListDictVars ExportedStringListDictVariables
-
-	exportedVariableReferenceDictVars ExportedVariableReferenceDictVariables
-
-	/// Maps containing variables that are dependent on the build config.
-	exportedConfigDependingVars ExportedConfigDependingVariables
-
-	pctx PackageContext
-}
-
-// NewExportedVariables creats an empty ExportedVariables struct with non-nil maps
-func NewExportedVariables(pctx PackageContext) ExportedVariables {
-	return ExportedVariables{
-		exportedStringVars:                ExportedStringVariables{},
-		exportedStringListVars:            ExportedStringListVariables{},
-		exportedStringListDictVars:        ExportedStringListDictVariables{},
-		exportedVariableReferenceDictVars: ExportedVariableReferenceDictVariables{},
-		exportedConfigDependingVars:       ExportedConfigDependingVariables{},
-		pctx:                              pctx,
-	}
-}
-
-// ExportStringStaticVariable declares a static string variable and exports it to
-// Bazel's toolchain.
-func (ev ExportedVariables) ExportStringStaticVariable(name string, value string) {
-	ev.pctx.StaticVariable(name, value)
-	ev.exportedStringVars.set(name, value)
-}
-
-// ExportStringListStaticVariable declares a static variable and exports it to
-// Bazel's toolchain.
-func (ev ExportedVariables) ExportStringListStaticVariable(name string, value []string) {
-	ev.pctx.StaticVariable(name, strings.Join(value, " "))
-	ev.exportedStringListVars.set(name, value)
-}
-
-// ExportVariableConfigMethod declares a variable whose value is evaluated at
-// runtime via a function with access to the Config and exports it to Bazel's
-// toolchain.
-func (ev ExportedVariables) ExportVariableConfigMethod(name string, method interface{}) blueprint.Variable {
-	ev.exportedConfigDependingVars.set(name, method)
-	return ev.pctx.VariableConfigMethod(name, method)
-}
-
-// ExportSourcePathVariable declares a static "source path" variable and exports
-// it to Bazel's toolchain.
-func (ev ExportedVariables) ExportSourcePathVariable(name string, value string) {
-	ev.pctx.SourcePathVariable(name, value)
-	ev.exportedStringVars.set(name, value)
-}
-
-// ExportVariableFuncVariable declares a variable whose value is evaluated at
-// runtime via a function and exports it to Bazel's toolchain.
-func (ev ExportedVariables) ExportVariableFuncVariable(name string, f func() string) {
-	ev.exportedConfigDependingVars.set(name, func(config Config) string {
-		return f()
-	})
-	ev.pctx.VariableFunc(name, func(PackageVarContext) string {
-		return f()
-	})
-}
-
-// ExportString only exports a variable to Bazel, but does not declare it in Soong
-func (ev ExportedVariables) ExportString(name string, value string) {
-	ev.exportedStringVars.set(name, value)
-}
-
-// ExportStringList only exports a variable to Bazel, but does not declare it in Soong
-func (ev ExportedVariables) ExportStringList(name string, value []string) {
-	ev.exportedStringListVars.set(name, value)
-}
-
-// ExportStringListDict only exports a variable to Bazel, but does not declare it in Soong
-func (ev ExportedVariables) ExportStringListDict(name string, value map[string][]string) {
-	ev.exportedStringListDictVars.set(name, value)
-}
-
-// ExportVariableReferenceDict only exports a variable to Bazel, but does not declare it in Soong
-func (ev ExportedVariables) ExportVariableReferenceDict(name string, value map[string]string) {
-	ev.exportedVariableReferenceDictVars.set(name, value)
-}
-
-// ExportedConfigDependingVariables is a mapping of variable names to functions
-// of type func(config Config) string which return the runtime-evaluated string
-// value of a particular variable
-type ExportedConfigDependingVariables map[string]interface{}
-
-func (m ExportedConfigDependingVariables) set(k string, v interface{}) {
-	m[k] = v
-}
-
-// ExportedStringVariables is a mapping of variable names to string values
-type ExportedStringVariables map[string]string
-
-func (m ExportedStringVariables) set(k string, v string) {
-	m[k] = v
-}
-
-// ExportedStringListVariables is a mapping of variable names to a list of strings
-type ExportedStringListVariables map[string][]string
-
-func (m ExportedStringListVariables) set(k string, v []string) {
-	m[k] = v
-}
-
-// ExportedStringListDictVariables is a mapping from variable names to a
-// dictionary which maps keys to lists of strings
-type ExportedStringListDictVariables map[string]map[string][]string
-
-func (m ExportedStringListDictVariables) set(k string, v map[string][]string) {
-	m[k] = v
-}
-
-// ExportedVariableReferenceDictVariables is a mapping from variable names to a
-// dictionary which references previously defined variables. This is used to
-// create a Starlark output such as:
-//
-//	string_var1 = "string1
-//	var_ref_dict_var1 = {
-//		"key1": string_var1
-//	}
-//
-// This type of variable collection must be expanded last so that it recognizes
-// previously defined variables.
-type ExportedVariableReferenceDictVariables map[string]map[string]string
-
-func (m ExportedVariableReferenceDictVariables) set(k string, v map[string]string) {
-	m[k] = v
-}
diff --git a/android/defs.go b/android/defs.go
index dab012d..a34d302 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -20,8 +20,7 @@
 )
 
 var (
-	pctx         = NewPackageContext("android/soong/android")
-	exportedVars = NewExportedVariables(pctx)
+	pctx = NewPackageContext("android/soong/android")
 
 	cpPreserveSymlinks = pctx.VariableConfigMethod("cpPreserveSymlinks",
 		Config.CpPreserveSymlinksFlags)
@@ -130,9 +129,6 @@
 	pctx.VariableFunc("RBEWrapper", func(ctx PackageVarContext) string {
 		return ctx.Config().RBEWrapper()
 	})
-
-	exportedVars.ExportStringList("NeverAllowNotInIncludeDir", neverallowNotInIncludeDir)
-	exportedVars.ExportStringList("NeverAllowNoUseIncludeDir", neverallowNoUseIncludeDir)
 }
 
 // GlobToListFileRule creates a rule that writes a list of files matching a pattern to a file.
diff --git a/android/module.go b/android/module.go
index f908451..89c4ddd 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1074,14 +1074,22 @@
 		}
 	}
 
+	var deviceTargets []Target
+	deviceTargets = append(deviceTargets, ctx.Config().Targets[Android]...)
+	deviceTargets = append(deviceTargets, ctx.Config().AndroidCommonTarget)
+
+	var hostTargets []Target
+	hostTargets = append(hostTargets, ctx.Config().Targets[ctx.Config().BuildOS]...)
+	hostTargets = append(hostTargets, ctx.Config().BuildOSCommonTarget)
+
 	if m.Device() {
 		for _, depName := range m.RequiredModuleNames() {
-			for _, target := range ctx.Config().Targets[Android] {
+			for _, target := range deviceTargets {
 				addDep(target, depName)
 			}
 		}
 		for _, depName := range m.HostRequiredModuleNames() {
-			for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] {
+			for _, target := range hostTargets {
 				addDep(target, depName)
 			}
 		}
@@ -1089,7 +1097,7 @@
 
 	if m.Host() {
 		for _, depName := range m.RequiredModuleNames() {
-			for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] {
+			for _, target := range hostTargets {
 				// When a host module requires another host module, don't make a
 				// dependency if they have different OSes (i.e. hostcross).
 				if m.Target().HostCross != target.HostCross {
@@ -1099,7 +1107,7 @@
 			}
 		}
 		for _, depName := range m.TargetRequiredModuleNames() {
-			for _, target := range ctx.Config().Targets[Android] {
+			for _, target := range deviceTargets {
 				addDep(target, depName)
 			}
 		}
diff --git a/android/path_properties.go b/android/path_properties.go
index ea92565..6210aee 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -109,9 +109,9 @@
 			case reflect.Struct:
 				intf := sv.Interface()
 				if configurable, ok := intf.(proptools.Configurable[string]); ok {
-					ret = append(ret, proptools.String(configurable.Evaluate(ctx)))
+					ret = append(ret, configurable.GetOrDefault(ctx, ""))
 				} else if configurable, ok := intf.(proptools.Configurable[[]string]); ok {
-					ret = append(ret, proptools.Slice(configurable.Evaluate(ctx))...)
+					ret = append(ret, configurable.GetOrDefault(ctx, nil)...)
 				} else {
 					panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
 						v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
diff --git a/android/selects_test.go b/android/selects_test.go
index a54459c..e59b3e6 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -368,14 +368,62 @@
 				my_bool: proptools.BoolPtr(true),
 			},
 		},
+		{
+			name: "defaults with lists are appended",
+			bp: `
+			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"],
+				}),
+			}
+			`,
+			provider: selectsTestProvider{
+				my_string_list: &[]string{"b2", "b1"},
+			},
+		},
+		{
+			name: "Replacing string list",
+			bp: `
+			my_module_type {
+				name: "foo",
+				defaults: ["bar"],
+				replacing_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
+					"a": ["a1"],
+					default: ["b1"],
+				}),
+			}
+			my_defaults {
+				name: "bar",
+				replacing_string_list: select(soong_config_variable("my_namespace", "my_variable2"), {
+					"a": ["a2"],
+					default: ["b2"],
+				}),
+			}
+			`,
+			provider: selectsTestProvider{
+				replacing_string_list: &[]string{"b1"},
+			},
+		},
 	}
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			fixtures := GroupFixturePreparers(
+				PrepareForTestWithDefaults,
 				PrepareForTestWithArchMutator,
 				FixtureRegisterWithContext(func(ctx RegistrationContext) {
 					ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
+					ctx.RegisterModuleType("my_defaults", newSelectsMockModuleDefaults)
 				}),
 				FixtureModifyProductVariables(func(variables FixtureProductVariables) {
 					variables.VendorVars = tc.vendorVars
@@ -398,10 +446,11 @@
 }
 
 type selectsTestProvider struct {
-	my_bool        *bool
-	my_string      *string
-	my_string_list *[]string
-	my_paths       *[]string
+	my_bool               *bool
+	my_string             *string
+	my_string_list        *[]string
+	my_paths              *[]string
+	replacing_string_list *[]string
 }
 
 func (p *selectsTestProvider) String() string {
@@ -418,16 +467,18 @@
 	my_string: %s,
     my_string_list: %s,
     my_paths: %s,
-}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths)
+	replacing_string_list %s,
+}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths, p.replacing_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"`
+	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"`
 }
 
 type selectsMockModule struct {
@@ -438,10 +489,11 @@
 
 func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 	SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
-		my_bool:        p.properties.My_bool.Evaluate(ctx),
-		my_string:      p.properties.My_string.Evaluate(ctx),
-		my_string_list: p.properties.My_string_list.Evaluate(ctx),
-		my_paths:       p.properties.My_paths.Evaluate(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),
 	})
 }
 
@@ -452,3 +504,23 @@
 	InitDefaultableModule(m)
 	return m
 }
+
+type selectsMockModuleDefaults struct {
+	ModuleBase
+	DefaultsModuleBase
+}
+
+func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+func newSelectsMockModuleDefaults() Module {
+	module := &selectsMockModuleDefaults{}
+
+	module.AddProperties(
+		&selectsMockModuleProperties{},
+	)
+
+	InitDefaultsModule(module)
+
+	return module
+}
diff --git a/android/shared_properties.go b/android/shared_properties.go
new file mode 100644
index 0000000..84d68fa
--- /dev/null
+++ b/android/shared_properties.go
@@ -0,0 +1,26 @@
+// Copyright 2024 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 android
+
+// For storing user-supplied properties about source code on a module to be queried later.
+type SourceProperties struct {
+	// Indicates that the module and its source code are only used in tests, not
+	// production code. Used by coverage reports and potentially other tools.
+	Test_only *bool
+	// Used internally to write if this is a top level test target.
+	// i.e. something that can be run directly or through tradefed as a test.
+	// `java_library` would be false, `java_test` would be true.
+	Top_level_test_target bool `blueprint:"mutated"`
+}
diff --git a/android/team.go b/android/team.go
index df61f40..c273dc6 100644
--- a/android/team.go
+++ b/android/team.go
@@ -14,6 +14,8 @@
 
 package android
 
+import "github.com/google/blueprint"
+
 func init() {
 	RegisterTeamBuildComponents(InitRegistrationContext)
 }
@@ -37,6 +39,13 @@
 	properties teamProperties
 }
 
+type TestModuleInformation struct {
+	TestOnly       bool
+	TopLevelTarget bool
+}
+
+var TestOnlyProviderKey = blueprint.NewProvider[TestModuleInformation]()
+
 // Real work is done for the module that depends on us.
 // If needed, the team can serialize the config to json/proto file as well.
 func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
diff --git a/android/team_proto/team.pb.go b/android/team_proto/team.pb.go
index 61260cf..8414d17 100644
--- a/android/team_proto/team.pb.go
+++ b/android/team_proto/team.pb.go
@@ -46,6 +46,13 @@
 	TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
 	// OPTIONAL: Files directly owned by this module.
 	File []string `protobuf:"bytes,4,rep,name=file" json:"file,omitempty"`
+	// OPTIONAL: Is this a test-only module.
+	TestOnly *bool `protobuf:"varint,5,opt,name=test_only,json=testOnly" json:"test_only,omitempty"`
+	// OPTIONAL: Is this intended to be run as a test target.
+	// This target can be run directly as a test or passed to tradefed.
+	TopLevelTarget *bool `protobuf:"varint,6,opt,name=top_level_target,json=topLevelTarget" json:"top_level_target,omitempty"`
+	// OPTIONAL: Name of module kind, i.e. java_library
+	Kind *string `protobuf:"bytes,7,opt,name=kind" json:"kind,omitempty"`
 }
 
 func (x *Team) Reset() {
@@ -108,6 +115,27 @@
 	return nil
 }
 
+func (x *Team) GetTestOnly() bool {
+	if x != nil && x.TestOnly != nil {
+		return *x.TestOnly
+	}
+	return false
+}
+
+func (x *Team) GetTopLevelTarget() bool {
+	if x != nil && x.TopLevelTarget != nil {
+		return *x.TopLevelTarget
+	}
+	return false
+}
+
+func (x *Team) GetKind() string {
+	if x != nil && x.Kind != nil {
+		return *x.Kind
+	}
+	return ""
+}
+
 type AllTeams struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -159,20 +187,26 @@
 
 var file_team_proto_rawDesc = []byte{
 	0x0a, 0x0a, 0x74, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65,
-	0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x75, 0x0a, 0x04, 0x54, 0x65, 0x61, 0x6d,
-	0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d,
-	0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f,
-	0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74,
-	0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66,
-	0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22,
-	0x32, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x74,
-	0x65, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x61,
-	0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x05, 0x74, 0x65,
-	0x61, 0x6d, 0x73, 0x42, 0x22, 0x5a, 0x20, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73,
-	0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x74, 0x65, 0x61,
-	0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd0, 0x01, 0x0a, 0x04, 0x54, 0x65, 0x61,
+	0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61,
+	0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79,
+	0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
+	0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
+	0x66, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65,
+	0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x28, 0x0a,
+	0x10, 0x74, 0x6f, 0x70, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65,
+	0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x74, 0x6f, 0x70, 0x4c, 0x65, 0x76, 0x65,
+	0x6c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x32, 0x0a, 0x08, 0x41,
+	0x6c, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x74, 0x65, 0x61, 0x6d, 0x73,
+	0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x05, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x42,
+	0x22, 0x5a, 0x20, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+	0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f,
 }
 
 var (
diff --git a/android/team_proto/team.proto b/android/team_proto/team.proto
index 401eccc..69ebf43 100644
--- a/android/team_proto/team.proto
+++ b/android/team_proto/team.proto
@@ -27,6 +27,16 @@
 
   // OPTIONAL: Files directly owned by this module.
   repeated string file = 4;
+
+  // OPTIONAL: Is this a test-only module.
+  optional bool test_only = 5;
+
+  // OPTIONAL: Is this intended to be run as a test target.
+  // This target can be run directly as a test or passed to tradefed.
+  optional bool top_level_target = 6;
+
+  // OPTIONAL: Name of module kind, i.e. java_library
+  optional string kind = 7;
 }
 
 message AllTeams {
diff --git a/android/team_test.go b/android/team_test.go
index 75b3e9f..ccfcaaa 100644
--- a/android/team_test.go
+++ b/android/team_test.go
@@ -27,16 +27,19 @@
 	return module
 }
 
+var prepareForTestWithTeamAndFakeBuildComponents = GroupFixturePreparers(
+	FixtureRegisterWithContext(RegisterTeamBuildComponents),
+	FixtureRegisterWithContext(func(ctx RegistrationContext) {
+		ctx.RegisterModuleType("fake", fakeModuleFactory)
+	}),
+)
+
 func (*fakeModuleForTests) GenerateAndroidBuildActions(ModuleContext) {}
 
 func TestTeam(t *testing.T) {
 	t.Parallel()
-	ctx := GroupFixturePreparers(
-		PrepareForTestWithTeamBuildComponents,
-		FixtureRegisterWithContext(func(ctx RegistrationContext) {
-			ctx.RegisterModuleType("fake", fakeModuleFactory)
-		}),
-	).RunTestWithBp(t, `
+	ctx := prepareForTestWithTeamAndFakeBuildComponents.
+		RunTestWithBp(t, `
 		fake {
 			name: "main_test",
 			team: "someteam",
@@ -66,12 +69,7 @@
 
 func TestMissingTeamFails(t *testing.T) {
 	t.Parallel()
-	GroupFixturePreparers(
-		PrepareForTestWithTeamBuildComponents,
-		FixtureRegisterWithContext(func(ctx RegistrationContext) {
-			ctx.RegisterModuleType("fake", fakeModuleFactory)
-		}),
-	).
+	prepareForTestWithTeamAndFakeBuildComponents.
 		ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")).
 		RunTestWithBp(t, `
 		fake {
@@ -86,9 +84,6 @@
 	GroupFixturePreparers(
 		PrepareForTestWithTeamBuildComponents,
 		PrepareForTestWithPackageModule,
-		FixtureRegisterWithContext(func(ctx RegistrationContext) {
-			ctx.RegisterModuleType("fake", fakeModuleFactory)
-		}),
 	).
 		ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")).
 		RunTestWithBp(t, `
diff --git a/apex/apex.go b/apex/apex.go
index d437efe..cb8449c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -737,33 +737,25 @@
 // suffix indicates the vndk version for vendor/product if vndk is enabled.
 // getImageVariation can simply join the result of this function to get the
 // image variation name.
-func (a *apexBundle) getImageVariationPair(deviceConfig android.DeviceConfig) (string, string) {
+func (a *apexBundle) getImageVariationPair() (string, string) {
 	if a.vndkApex {
 		return cc.VendorVariationPrefix, a.vndkVersion()
 	}
 
 	prefix := android.CoreVariation
-	vndkVersion := ""
-	if deviceConfig.VndkVersion() != "" {
-		if a.SocSpecific() || a.DeviceSpecific() {
-			prefix = cc.VendorVariationPrefix
-			vndkVersion = deviceConfig.VndkVersion()
-		}
-	} else {
-		if a.SocSpecific() || a.DeviceSpecific() {
-			prefix = cc.VendorVariation
-		} else if a.ProductSpecific() {
-			prefix = cc.ProductVariation
-		}
+	if a.SocSpecific() || a.DeviceSpecific() {
+		prefix = cc.VendorVariation
+	} else if a.ProductSpecific() {
+		prefix = cc.ProductVariation
 	}
 
-	return prefix, vndkVersion
+	return prefix, ""
 }
 
 // getImageVariation returns the image variant name for this apexBundle. In most cases, it's simply
 // android.CoreVariation, but gets complicated for the vendor APEXes and the VNDK APEX.
-func (a *apexBundle) getImageVariation(ctx android.BottomUpMutatorContext) string {
-	prefix, vndkVersion := a.getImageVariationPair(ctx.DeviceConfig())
+func (a *apexBundle) getImageVariation() string {
+	prefix, vndkVersion := a.getImageVariationPair()
 	return prefix + vndkVersion
 }
 
@@ -773,7 +765,7 @@
 	// each target os/architectures, appropriate dependencies are selected by their
 	// target.<os>.multilib.<type> groups and are added as (direct) dependencies.
 	targets := ctx.MultiTargets()
-	imageVariation := a.getImageVariation(ctx)
+	imageVariation := a.getImageVariation()
 
 	a.combineProperties(ctx)
 
@@ -1306,30 +1298,26 @@
 	}
 
 	// apexBundle itself is mutated so that it and its dependencies have the same apex variant.
-	if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
-		apexBundleName := ai.ApexVariationName()
+	// Note that a default variation "" is also created as an alias, and the default dependency
+	// variation is set to the default variation. This is to allow an apex to depend on another
+	// module which is outside of the apex. This is because the dependent module is not mutated
+	// for this apex variant.
+	createApexVariation := func(apexBundleName string) {
+		defaultVariation := ""
+		mctx.SetDefaultDependencyVariation(&defaultVariation)
 		mctx.CreateVariations(apexBundleName)
-		if strings.HasPrefix(apexBundleName, "com.android.art") {
-			// Create an alias from the platform variant. This is done to make
-			// test_for dependencies work for modules that are split by the APEX
-			// mutator, since test_for dependencies always go to the platform variant.
-			// This doesn't happen for normal APEXes that are disjunct, so only do
-			// this for the overlapping ART APEXes.
-			// TODO(b/183882457): Remove this if the test_for functionality is
-			// refactored to depend on the proper APEX variants instead of platform.
-			mctx.CreateAliasVariation("", apexBundleName)
-		}
+		mctx.CreateAliasVariation(defaultVariation, apexBundleName)
+	}
+
+	if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
+		createApexVariation(ai.ApexVariationName())
 	} else if o, ok := mctx.Module().(*OverrideApex); ok {
 		apexBundleName := o.GetOverriddenModuleName()
 		if apexBundleName == "" {
 			mctx.ModuleErrorf("base property is not set")
 			return
 		}
-		mctx.CreateVariations(apexBundleName)
-		if strings.HasPrefix(apexBundleName, "com.android.art") {
-			// TODO(b/183882457): See note for CreateAliasVariation above.
-			mctx.CreateAliasVariation("", apexBundleName)
-		}
+		createApexVariation(apexBundleName)
 	}
 }
 
@@ -1534,7 +1522,7 @@
 	// TODO(jiyong): move this info (the sanitizer name, the lib name, etc.) to cc/sanitize.go
 	// Keep only the mechanism here.
 	if sanitizerName == "hwaddress" && strings.HasPrefix(a.Name(), "com.android.runtime") {
-		imageVariation := a.getImageVariation(ctx)
+		imageVariation := a.getImageVariation()
 		for _, target := range ctx.MultiTargets() {
 			if target.Arch.ArchType.Multilib == "lib64" {
 				addDependenciesForNativeModules(ctx, ApexNativeDependencies{
diff --git a/apex/builder.go b/apex/builder.go
index 9bd4b61..763ce4d 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -293,7 +293,7 @@
 	}
 
 	if android.InList(":vndk", requireNativeLibs) {
-		if _, vndkVersion := a.getImageVariationPair(ctx.DeviceConfig()); vndkVersion != "" {
+		if _, vndkVersion := a.getImageVariationPair(); vndkVersion != "" {
 			optCommands = append(optCommands, "-v vndkVersion "+vndkVersion)
 		}
 	}
diff --git a/cc/cc.go b/cc/cc.go
index 2ff8bce..69ecc78 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1865,7 +1865,6 @@
 func getNameSuffixWithVndkVersion(ctx android.ModuleContext, c LinkableInterface) string {
 	// Returns the name suffix for product and vendor variants. If the VNDK version is not
 	// "current", it will append the VNDK version to the name suffix.
-	var vndkVersion string
 	var nameSuffix string
 	if c.InProduct() {
 		if c.ProductSpecific() {
@@ -1875,10 +1874,9 @@
 		}
 		return ProductSuffix
 	} else {
-		vndkVersion = ctx.DeviceConfig().VndkVersion()
 		nameSuffix = VendorSuffix
 	}
-	if c.VndkVersion() != vndkVersion && c.VndkVersion() != "" {
+	if c.VndkVersion() != "" {
 		// add version suffix only if the module is using different vndk version than the
 		// version in product or vendor partition.
 		nameSuffix += "." + c.VndkVersion()
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 10342a3..fb81e42 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -91,16 +91,14 @@
 )
 
 func init() {
-	exportedVars.ExportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
+	pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
 
-	exportedVars.ExportStringList("Arm64Lldflags", arm64Lldflags)
 	pctx.VariableFunc("Arm64Lldflags", func(ctx android.PackageVarContext) string {
 		maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
 		flags := append(arm64Lldflags, maxPageSizeFlag)
 		return strings.Join(flags, " ")
 	})
 
-	exportedVars.ExportStringList("Arm64Cflags", arm64Cflags)
 	pctx.VariableFunc("Arm64Cflags", func(ctx android.PackageVarContext) string {
 		flags := arm64Cflags
 		if ctx.Config().NoBionicPageSizeMacro() {
@@ -109,25 +107,21 @@
 		return strings.Join(flags, " ")
 	})
 
-	exportedVars.ExportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
+	pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
 
-	exportedVars.ExportVariableReferenceDict("Arm64ArchVariantCflags", arm64ArchVariantCflagsVar)
-	exportedVars.ExportVariableReferenceDict("Arm64CpuVariantCflags", arm64CpuVariantCflagsVar)
-	exportedVars.ExportVariableReferenceDict("Arm64CpuVariantLdflags", arm64CpuVariantLdflags)
+	pctx.StaticVariable("Arm64Armv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
+	pctx.StaticVariable("Arm64Armv8ABranchProtCflags", strings.Join(arm64ArchVariantCflags["armv8-a-branchprot"], " "))
+	pctx.StaticVariable("Arm64Armv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
+	pctx.StaticVariable("Arm64Armv82ADotprodCflags", strings.Join(arm64ArchVariantCflags["armv8-2a-dotprod"], " "))
+	pctx.StaticVariable("Arm64Armv9ACflags", strings.Join(arm64ArchVariantCflags["armv9-a"], " "))
 
-	exportedVars.ExportStringListStaticVariable("Arm64Armv8ACflags", arm64ArchVariantCflags["armv8-a"])
-	exportedVars.ExportStringListStaticVariable("Arm64Armv8ABranchProtCflags", arm64ArchVariantCflags["armv8-a-branchprot"])
-	exportedVars.ExportStringListStaticVariable("Arm64Armv82ACflags", arm64ArchVariantCflags["armv8-2a"])
-	exportedVars.ExportStringListStaticVariable("Arm64Armv82ADotprodCflags", arm64ArchVariantCflags["armv8-2a-dotprod"])
-	exportedVars.ExportStringListStaticVariable("Arm64Armv9ACflags", arm64ArchVariantCflags["armv9-a"])
+	pctx.StaticVariable("Arm64CortexA53Cflags", strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
+	pctx.StaticVariable("Arm64CortexA55Cflags", strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
+	pctx.StaticVariable("Arm64KryoCflags", strings.Join(arm64CpuVariantCflags["kryo"], " "))
+	pctx.StaticVariable("Arm64ExynosM1Cflags", strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))
+	pctx.StaticVariable("Arm64ExynosM2Cflags", strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
 
-	exportedVars.ExportStringListStaticVariable("Arm64CortexA53Cflags", arm64CpuVariantCflags["cortex-a53"])
-	exportedVars.ExportStringListStaticVariable("Arm64CortexA55Cflags", arm64CpuVariantCflags["cortex-a55"])
-	exportedVars.ExportStringListStaticVariable("Arm64KryoCflags", arm64CpuVariantCflags["kryo"])
-	exportedVars.ExportStringListStaticVariable("Arm64ExynosM1Cflags", arm64CpuVariantCflags["exynos-m1"])
-	exportedVars.ExportStringListStaticVariable("Arm64ExynosM2Cflags", arm64CpuVariantCflags["exynos-m2"])
-
-	exportedVars.ExportStringListStaticVariable("Arm64FixCortexA53Ldflags", []string{"-Wl,--fix-cortex-a53-843419"})
+	pctx.StaticVariable("Arm64FixCortexA53Ldflags", "-Wl,--fix-cortex-a53-843419")
 }
 
 var (
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index f7d190b..438e0e6 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -61,9 +61,9 @@
 )
 
 func init() {
-	exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Cflags", linuxCrossCflags)
-	exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Ldflags", linuxCrossLdflags)
-	exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Lldflags", linuxCrossLldflags)
+	pctx.StaticVariable("LinuxBionicArm64Cflags", strings.Join(linuxCrossCflags, " "))
+	pctx.StaticVariable("LinuxBionicArm64Ldflags", strings.Join(linuxCrossLdflags, " "))
+	pctx.StaticVariable("LinuxBionicArm64Lldflags", strings.Join(linuxCrossLldflags, " "))
 }
 
 // toolchain config for ARM64 Linux CrossHost. Almost everything is the same as the ARM64 Android
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 3284e4b..3cb1909 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -35,7 +35,7 @@
 	armCppflags = []string{
 		// Revert this after b/322359235 is fixed
 		"-mllvm", "-enable-shrink-wrap=false",
-  }
+	}
 
 	armLdflags = []string{
 		"-Wl,-m,armelf",
@@ -185,43 +185,37 @@
 )
 
 func init() {
-	// Just exported. Not created as a Ninja static variable.
-	exportedVars.ExportString("ArmClangTriple", clangTriple)
+	pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
+	pctx.StaticVariable("ArmLldflags", strings.Join(armLldflags, " "))
 
-	exportedVars.ExportStringListStaticVariable("ArmLdflags", armLdflags)
-	exportedVars.ExportStringListStaticVariable("ArmLldflags", armLldflags)
-
-	exportedVars.ExportStringListStaticVariable("ArmFixCortexA8LdFlags", armFixCortexA8LdFlags)
-	exportedVars.ExportStringListStaticVariable("ArmNoFixCortexA8LdFlags", armNoFixCortexA8LdFlags)
+	pctx.StaticVariable("ArmFixCortexA8LdFlags", strings.Join(armFixCortexA8LdFlags, " "))
+	pctx.StaticVariable("ArmNoFixCortexA8LdFlags", strings.Join(armNoFixCortexA8LdFlags, " "))
 
 	// Clang cflags
-	exportedVars.ExportStringListStaticVariable("ArmToolchainCflags", armToolchainCflags)
-	exportedVars.ExportStringListStaticVariable("ArmCflags", armCflags)
-	exportedVars.ExportStringListStaticVariable("ArmCppflags", armCppflags)
+	pctx.StaticVariable("ArmToolchainCflags", strings.Join(armToolchainCflags, " "))
+	pctx.StaticVariable("ArmCflags", strings.Join(armCflags, " "))
+	pctx.StaticVariable("ArmCppflags", strings.Join(armCppflags, " "))
 
 	// Clang ARM vs. Thumb instruction set cflags
-	exportedVars.ExportStringListStaticVariable("ArmArmCflags", armArmCflags)
-	exportedVars.ExportStringListStaticVariable("ArmThumbCflags", armThumbCflags)
-
-	exportedVars.ExportVariableReferenceDict("ArmArchVariantCflags", armArchVariantCflagsVar)
-	exportedVars.ExportVariableReferenceDict("ArmCpuVariantCflags", armCpuVariantCflagsVar)
+	pctx.StaticVariable("ArmArmCflags", strings.Join(armArmCflags, " "))
+	pctx.StaticVariable("ArmThumbCflags", strings.Join(armThumbCflags, " "))
 
 	// Clang arch variant cflags
-	exportedVars.ExportStringListStaticVariable("ArmArmv7ACflags", armArchVariantCflags["armv7-a"])
-	exportedVars.ExportStringListStaticVariable("ArmArmv7ANeonCflags", armArchVariantCflags["armv7-a-neon"])
-	exportedVars.ExportStringListStaticVariable("ArmArmv8ACflags", armArchVariantCflags["armv8-a"])
-	exportedVars.ExportStringListStaticVariable("ArmArmv82ACflags", armArchVariantCflags["armv8-2a"])
+	pctx.StaticVariable("ArmArmv7ACflags", strings.Join(armArchVariantCflags["armv7-a"], " "))
+	pctx.StaticVariable("ArmArmv7ANeonCflags", strings.Join(armArchVariantCflags["armv7-a-neon"], " "))
+	pctx.StaticVariable("ArmArmv8ACflags", strings.Join(armArchVariantCflags["armv8-a"], " "))
+	pctx.StaticVariable("ArmArmv82ACflags", strings.Join(armArchVariantCflags["armv8-2a"], " "))
 
 	// Clang cpu variant cflags
-	exportedVars.ExportStringListStaticVariable("ArmGenericCflags", armCpuVariantCflags[""])
-	exportedVars.ExportStringListStaticVariable("ArmCortexA7Cflags", armCpuVariantCflags["cortex-a7"])
-	exportedVars.ExportStringListStaticVariable("ArmCortexA8Cflags", armCpuVariantCflags["cortex-a8"])
-	exportedVars.ExportStringListStaticVariable("ArmCortexA15Cflags", armCpuVariantCflags["cortex-a15"])
-	exportedVars.ExportStringListStaticVariable("ArmCortexA32Cflags", armCpuVariantCflags["cortex-a32"])
-	exportedVars.ExportStringListStaticVariable("ArmCortexA53Cflags", armCpuVariantCflags["cortex-a53"])
-	exportedVars.ExportStringListStaticVariable("ArmCortexA55Cflags", armCpuVariantCflags["cortex-a55"])
-	exportedVars.ExportStringListStaticVariable("ArmKraitCflags", armCpuVariantCflags["krait"])
-	exportedVars.ExportStringListStaticVariable("ArmKryoCflags", armCpuVariantCflags["kryo"])
+	pctx.StaticVariable("ArmGenericCflags", strings.Join(armCpuVariantCflags[""], " "))
+	pctx.StaticVariable("ArmCortexA7Cflags", strings.Join(armCpuVariantCflags["cortex-a7"], " "))
+	pctx.StaticVariable("ArmCortexA8Cflags", strings.Join(armCpuVariantCflags["cortex-a8"], " "))
+	pctx.StaticVariable("ArmCortexA15Cflags", strings.Join(armCpuVariantCflags["cortex-a15"], " "))
+	pctx.StaticVariable("ArmCortexA32Cflags", strings.Join(armCpuVariantCflags["cortex-a32"], " "))
+	pctx.StaticVariable("ArmCortexA53Cflags", strings.Join(armCpuVariantCflags["cortex-a53"], " "))
+	pctx.StaticVariable("ArmCortexA55Cflags", strings.Join(armCpuVariantCflags["cortex-a55"], " "))
+	pctx.StaticVariable("ArmKraitCflags", strings.Join(armCpuVariantCflags["krait"], " "))
+	pctx.StaticVariable("ArmKryoCflags", strings.Join(armCpuVariantCflags["kryo"], " "))
 }
 
 var (
diff --git a/cc/config/arm_linux_host.go b/cc/config/arm_linux_host.go
index e21c60d..e7c7bc4 100644
--- a/cc/config/arm_linux_host.go
+++ b/cc/config/arm_linux_host.go
@@ -14,7 +14,10 @@
 
 package config
 
-import "android/soong/android"
+import (
+	"android/soong/android"
+	"strings"
+)
 
 var (
 	linuxArmCflags = []string{
@@ -39,15 +42,15 @@
 )
 
 func init() {
-	exportedVars.ExportStringListStaticVariable("LinuxArmCflags", linuxArmCflags)
-	exportedVars.ExportStringListStaticVariable("LinuxArm64Cflags", linuxArm64Cflags)
-	exportedVars.ExportStringListStaticVariable("LinuxArmLdflags", linuxArmLdflags)
-	exportedVars.ExportStringListStaticVariable("LinuxArmLldflags", linuxArmLldflags)
-	exportedVars.ExportStringListStaticVariable("LinuxArm64Ldflags", linuxArm64Ldflags)
-	exportedVars.ExportStringListStaticVariable("LinuxArm64Lldflags", linuxArm64Lldflags)
+	pctx.StaticVariable("LinuxArmCflags", strings.Join(linuxArmCflags, " "))
+	pctx.StaticVariable("LinuxArm64Cflags", strings.Join(linuxArm64Cflags, " "))
+	pctx.StaticVariable("LinuxArmLdflags", strings.Join(linuxArmLdflags, " "))
+	pctx.StaticVariable("LinuxArmLldflags", strings.Join(linuxArmLldflags, " "))
+	pctx.StaticVariable("LinuxArm64Ldflags", strings.Join(linuxArm64Ldflags, " "))
+	pctx.StaticVariable("LinuxArm64Lldflags", strings.Join(linuxArm64Lldflags, " "))
 
-	exportedVars.ExportStringListStaticVariable("LinuxArmYasmFlags", []string{"-f elf32 -m arm"})
-	exportedVars.ExportStringListStaticVariable("LinuxArm64YasmFlags", []string{"-f elf64 -m aarch64"})
+	pctx.StaticVariable("LinuxArmYasmFlags", "-f elf32 -m arm")
+	pctx.StaticVariable("LinuxArm64YasmFlags", "-f elf64 -m aarch64")
 
 }
 
diff --git a/cc/config/global.go b/cc/config/global.go
index b21d56c..08fcb91 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -24,8 +24,7 @@
 )
 
 var (
-	pctx         = android.NewPackageContext("android/soong/cc/config")
-	exportedVars = android.NewExportedVariables(pctx)
+	pctx = android.NewPackageContext("android/soong/cc/config")
 
 	// Flags used by lots of devices.  Putting them in package static variables
 	// will save bytes in build.ninja so they aren't repeated for every file
@@ -401,26 +400,19 @@
 	VisibilityDefaultFlag = "-fvisibility=default"
 )
 
-func ExportStringList(name string, value []string) {
-	exportedVars.ExportStringList(name, value)
-}
-
 func init() {
 	if runtime.GOOS == "linux" {
 		commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
 	}
 
-	exportedVars.ExportStringListStaticVariable("CommonGlobalConlyflags", commonGlobalConlyflags)
-	exportedVars.ExportStringListStaticVariable("CommonGlobalAsflags", commonGlobalAsflags)
-	exportedVars.ExportStringListStaticVariable("DeviceGlobalCppflags", deviceGlobalCppflags)
-	exportedVars.ExportStringListStaticVariable("DeviceGlobalLdflags", deviceGlobalLdflags)
-	exportedVars.ExportStringListStaticVariable("DeviceGlobalLldflags", deviceGlobalLldflags)
-	exportedVars.ExportStringListStaticVariable("HostGlobalCppflags", hostGlobalCppflags)
-	exportedVars.ExportStringListStaticVariable("HostGlobalLdflags", hostGlobalLdflags)
-	exportedVars.ExportStringListStaticVariable("HostGlobalLldflags", hostGlobalLldflags)
-
-	// Export the static default CommonGlobalCflags to Bazel.
-	exportedVars.ExportStringList("CommonGlobalCflags", commonGlobalCflags)
+	pctx.StaticVariable("CommonGlobalConlyflags", strings.Join(commonGlobalConlyflags, " "))
+	pctx.StaticVariable("CommonGlobalAsflags", strings.Join(commonGlobalAsflags, " "))
+	pctx.StaticVariable("DeviceGlobalCppflags", strings.Join(deviceGlobalCppflags, " "))
+	pctx.StaticVariable("DeviceGlobalLdflags", strings.Join(deviceGlobalLdflags, " "))
+	pctx.StaticVariable("DeviceGlobalLldflags", strings.Join(deviceGlobalLldflags, " "))
+	pctx.StaticVariable("HostGlobalCppflags", strings.Join(hostGlobalCppflags, " "))
+	pctx.StaticVariable("HostGlobalLdflags", strings.Join(hostGlobalLdflags, " "))
+	pctx.StaticVariable("HostGlobalLldflags", strings.Join(hostGlobalLldflags, " "))
 
 	pctx.VariableFunc("CommonGlobalCflags", func(ctx android.PackageVarContext) string {
 		flags := slices.Clone(commonGlobalCflags)
@@ -467,16 +459,10 @@
 		return strings.Join(flags, " ")
 	})
 
-	// Export the static default DeviceGlobalCflags to Bazel.
-	// TODO(187086342): handle cflags that are set in VariableFuncs.
-	exportedVars.ExportStringList("DeviceGlobalCflags", deviceGlobalCflags)
-
 	pctx.VariableFunc("DeviceGlobalCflags", func(ctx android.PackageVarContext) string {
 		return strings.Join(deviceGlobalCflags, " ")
 	})
 
-	// Export the static default NoOverrideGlobalCflags to Bazel.
-	exportedVars.ExportStringList("NoOverrideGlobalCflags", noOverrideGlobalCflags)
 	pctx.VariableFunc("NoOverrideGlobalCflags", func(ctx android.PackageVarContext) string {
 		flags := noOverrideGlobalCflags
 		if ctx.Config().IsEnvTrue("LLVM_NEXT") {
@@ -486,21 +472,11 @@
 		return strings.Join(flags, " ")
 	})
 
-	exportedVars.ExportStringListStaticVariable("NoOverride64GlobalCflags", noOverride64GlobalCflags)
-	exportedVars.ExportStringListStaticVariable("HostGlobalCflags", hostGlobalCflags)
-	exportedVars.ExportStringListStaticVariable("NoOverrideExternalGlobalCflags", noOverrideExternalGlobalCflags)
-	exportedVars.ExportStringListStaticVariable("CommonGlobalCppflags", commonGlobalCppflags)
-	exportedVars.ExportStringListStaticVariable("ExternalCflags", extraExternalCflags)
-
-	exportedVars.ExportString("CStdVersion", CStdVersion)
-	exportedVars.ExportString("CppStdVersion", CppStdVersion)
-	exportedVars.ExportString("ExperimentalCStdVersion", ExperimentalCStdVersion)
-	exportedVars.ExportString("ExperimentalCppStdVersion", ExperimentalCppStdVersion)
-
-	exportedVars.ExportString("VersionScriptFlagPrefix", VersionScriptFlagPrefix)
-
-	exportedVars.ExportString("VisibilityHiddenFlag", VisibilityHiddenFlag)
-	exportedVars.ExportString("VisibilityDefaultFlag", VisibilityDefaultFlag)
+	pctx.StaticVariable("NoOverride64GlobalCflags", strings.Join(noOverride64GlobalCflags, " "))
+	pctx.StaticVariable("HostGlobalCflags", strings.Join(hostGlobalCflags, " "))
+	pctx.StaticVariable("NoOverrideExternalGlobalCflags", strings.Join(noOverrideExternalGlobalCflags, " "))
+	pctx.StaticVariable("CommonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
+	pctx.StaticVariable("ExternalCflags", strings.Join(extraExternalCflags, " "))
 
 	// Everything in these lists is a crime against abstraction and dependency tracking.
 	// Do not add anything to this list.
@@ -515,11 +491,10 @@
 		"frameworks/native/opengl/include",
 		"frameworks/av/include",
 	}
-	exportedVars.ExportStringList("CommonGlobalIncludes", commonGlobalIncludes)
 	pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I", commonGlobalIncludes)
 
-	exportedVars.ExportStringStaticVariable("CLANG_DEFAULT_VERSION", ClangDefaultVersion)
-	exportedVars.ExportStringStaticVariable("CLANG_DEFAULT_SHORT_VERSION", ClangDefaultShortVersion)
+	pctx.StaticVariable("CLANG_DEFAULT_VERSION", ClangDefaultVersion)
+	pctx.StaticVariable("CLANG_DEFAULT_SHORT_VERSION", ClangDefaultShortVersion)
 
 	pctx.StaticVariableWithEnvOverride("ClangBase", "LLVM_PREBUILTS_BASE", ClangDefaultBase)
 	pctx.StaticVariableWithEnvOverride("ClangVersion", "LLVM_PREBUILTS_VERSION", ClangDefaultVersion)
@@ -529,7 +504,7 @@
 	pctx.StaticVariableWithEnvOverride("ClangShortVersion", "LLVM_RELEASE_VERSION", ClangDefaultShortVersion)
 	pctx.StaticVariable("ClangAsanLibDir", "${ClangBase}/linux-x86/${ClangVersion}/lib/clang/${ClangShortVersion}/lib/linux")
 
-	exportedVars.ExportStringListStaticVariable("WarningAllowedProjects", WarningAllowedProjects)
+	pctx.StaticVariable("WarningAllowedProjects", strings.Join(WarningAllowedProjects, " "))
 
 	// These are tied to the version of LLVM directly in external/llvm, so they might trail the host prebuilts
 	// being used for the rest of the build process.
@@ -544,7 +519,6 @@
 		"frameworks/rs/script_api/include",
 	}
 	pctx.PrefixedExistentPathsForSourcesVariable("RsGlobalIncludes", "-I", rsGlobalIncludes)
-	exportedVars.ExportStringList("RsGlobalIncludes", rsGlobalIncludes)
 
 	pctx.VariableFunc("CcWrapper", func(ctx android.PackageVarContext) string {
 		if override := ctx.Config().Getenv("CC_WRAPPER"); override != "" {
@@ -562,7 +536,7 @@
 	pctx.StaticVariableWithEnvOverride("REAbiLinkerExecStrategy", "RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
 }
 
-var HostPrebuiltTag = exportedVars.ExportVariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
 
 func ClangPath(ctx android.PathContext, file string) android.SourcePath {
 	type clangToolKey string
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 47f0de1..724676a 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -62,15 +62,11 @@
 
 func init() {
 
-	exportedVars.ExportStringListStaticVariable("Riscv64Ldflags", riscv64Ldflags)
-	exportedVars.ExportStringListStaticVariable("Riscv64Lldflags", riscv64Lldflags)
+	pctx.StaticVariable("Riscv64Ldflags", strings.Join(riscv64Ldflags, " "))
+	pctx.StaticVariable("Riscv64Lldflags", strings.Join(riscv64Lldflags, " "))
 
-	exportedVars.ExportStringListStaticVariable("Riscv64Cflags", riscv64Cflags)
-	exportedVars.ExportStringListStaticVariable("Riscv64Cppflags", riscv64Cppflags)
-
-	exportedVars.ExportVariableReferenceDict("Riscv64ArchVariantCflags", riscv64ArchVariantCflagsVar)
-	exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantCflags", riscv64CpuVariantCflagsVar)
-	exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantLdflags", riscv64CpuVariantLdflags)
+	pctx.StaticVariable("Riscv64Cflags", strings.Join(riscv64Cflags, " "))
+	pctx.StaticVariable("Riscv64Cppflags", strings.Join(riscv64Cppflags, " "))
 }
 
 var (
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index b40557a..46d5d90 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -87,7 +87,7 @@
 	// The global default tidy checks should include clang-tidy
 	// default checks and tested groups, but exclude known noisy checks.
 	// See https://clang.llvm.org/extra/clang-tidy/checks/list.html
-	exportedVars.ExportVariableConfigMethod("TidyDefaultGlobalChecks", func(config android.Config) string {
+	pctx.VariableConfigMethod("TidyDefaultGlobalChecks", func(config android.Config) string {
 		if override := config.Getenv("DEFAULT_GLOBAL_TIDY_CHECKS"); override != "" {
 			return override
 		}
@@ -149,7 +149,7 @@
 	// There are too many clang-tidy warnings in external and vendor projects, so we only
 	// enable some google checks for these projects. Users can add more checks locally with the
 	// "tidy_checks" list in .bp files, or the "Checks" list in .clang-tidy config files.
-	exportedVars.ExportVariableConfigMethod("TidyExternalVendorChecks", func(config android.Config) string {
+	pctx.VariableConfigMethod("TidyExternalVendorChecks", func(config android.Config) string {
 		if override := config.Getenv("DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS"); override != "" {
 			return override
 		}
@@ -163,25 +163,21 @@
 		}, ",")
 	})
 
-	exportedVars.ExportVariableFuncVariable("TidyGlobalNoChecks", func() string {
-		return strings.Join(globalNoCheckList, ",")
-	})
+	pctx.StaticVariable("TidyGlobalNoChecks", strings.Join(globalNoCheckList, ","))
 
-	exportedVars.ExportVariableFuncVariable("TidyGlobalNoErrorChecks", func() string {
-		return strings.Join(globalNoErrorCheckList, ",")
-	})
+	pctx.StaticVariable("TidyGlobalNoErrorChecks", strings.Join(globalNoErrorCheckList, ","))
 
-	exportedVars.ExportStringListStaticVariable("TidyExtraArgFlags", extraArgFlags)
+	pctx.StaticVariable("TidyExtraArgFlags", strings.Join(extraArgFlags, " "))
 
 	// To reduce duplicate warnings from the same header files,
 	// header-filter will contain only the module directory and
 	// those specified by DEFAULT_TIDY_HEADER_DIRS.
-	exportedVars.ExportVariableConfigMethod("TidyDefaultHeaderDirs", func(config android.Config) string {
+	pctx.VariableConfigMethod("TidyDefaultHeaderDirs", func(config android.Config) string {
 		return config.Getenv("DEFAULT_TIDY_HEADER_DIRS")
 	})
 
 	// Use WTIH_TIDY_FLAGS to pass extra global default clang-tidy flags.
-	exportedVars.ExportVariableConfigMethod("TidyWithTidyFlags", func(config android.Config) string {
+	pctx.VariableConfigMethod("TidyWithTidyFlags", func(config android.Config) string {
 		return config.Getenv("WITH_TIDY_FLAGS")
 	})
 }
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 71e98fe..7dc990b 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -16,14 +16,15 @@
 
 import (
 	"fmt"
+	"strings"
 
 	"android/soong/android"
 )
 
 func init() {
-	exportedVars.ExportStringListStaticVariable("DarwinAvailableLibraries", darwinAvailableLibraries)
-	exportedVars.ExportStringListStaticVariable("LinuxAvailableLibraries", linuxAvailableLibraries)
-	exportedVars.ExportStringListStaticVariable("WindowsAvailableLibraries", windowsAvailableLibraries)
+	pctx.StaticVariable("DarwinAvailableLibraries", strings.Join(darwinAvailableLibraries, " "))
+	pctx.StaticVariable("LinuxAvailableLibraries", strings.Join(linuxAvailableLibraries, " "))
+	pctx.StaticVariable("WindowsAvailableLibraries", strings.Join(windowsAvailableLibraries, " "))
 }
 
 type toolchainFactory func(arch android.Arch) Toolchain
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index ca2c2b7..171ab4f 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -97,11 +97,10 @@
 )
 
 func init() {
-	exportedVars.ExportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
-	exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
+	pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
+	pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
 
-	exportedVars.ExportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags)
-	exportedVars.ExportStringList("X86_64Lldflags", X86_64Lldflags)
+	pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
 	pctx.VariableFunc("X86_64Lldflags", func(ctx android.PackageVarContext) string {
 		maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
 		flags := append(X86_64Lldflags, maxPageSizeFlag)
@@ -109,7 +108,6 @@
 	})
 
 	// Clang cflags
-	exportedVars.ExportStringList("X86_64Cflags", x86_64Cflags)
 	pctx.VariableFunc("X86_64Cflags", func(ctx android.PackageVarContext) string {
 		flags := x86_64Cflags
 		if ctx.Config().NoBionicPageSizeMacro() {
@@ -118,18 +116,10 @@
 		return strings.Join(flags, " ")
 	})
 
-	exportedVars.ExportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags)
+	pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
 
 	// Yasm flags
-	exportedVars.ExportStringListStaticVariable("X86_64YasmFlags", []string{
-		"-f elf64",
-		"-m amd64",
-	})
-
-	// Extended cflags
-
-	exportedVars.ExportStringListDict("X86_64ArchVariantCflags", x86_64ArchVariantCflags)
-	exportedVars.ExportStringListDict("X86_64ArchFeatureCflags", x86_64ArchFeatureCflags)
+	pctx.StaticVariable("X86_64YasmFlags", "-f elf64 -m amd64")
 
 	// Architecture variant cflags
 	for variant, cflags := range x86_64ArchVariantCflags {
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 60b8339..4b0041c 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -101,25 +101,18 @@
 )
 
 func init() {
-	exportedVars.ExportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
-	exportedVars.ExportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
+	pctx.StaticVariable("X86ToolchainCflags", "-m32")
+	pctx.StaticVariable("X86ToolchainLdflags", "-m32")
 
-	exportedVars.ExportStringListStaticVariable("X86Ldflags", x86Ldflags)
-	exportedVars.ExportStringListStaticVariable("X86Lldflags", x86Ldflags)
+	pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
+	pctx.StaticVariable("X86Lldflags", strings.Join(x86Ldflags, " "))
 
 	// Clang cflags
-	exportedVars.ExportStringListStaticVariable("X86Cflags", x86Cflags)
-	exportedVars.ExportStringListStaticVariable("X86Cppflags", x86Cppflags)
+	pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
+	pctx.StaticVariable("X86Cppflags", strings.Join(x86Cppflags, " "))
 
 	// Yasm flags
-	exportedVars.ExportStringListStaticVariable("X86YasmFlags", []string{
-		"-f elf32",
-		"-m x86",
-	})
-
-	// Extended cflags
-	exportedVars.ExportStringListDict("X86ArchVariantCflags", x86ArchVariantCflags)
-	exportedVars.ExportStringListDict("X86ArchFeatureCflags", x86ArchFeatureCflags)
+	pctx.StaticVariable("X86YasmFlags", "-f elf32 -m x86")
 
 	// Architecture variant cflags
 	for variant, cflags := range x86ArchVariantCflags {
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 99d4ebb..515cb21 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"strings"
 )
 
 var (
@@ -72,13 +73,13 @@
 )
 
 func init() {
-	exportedVars.ExportStringListStaticVariable("LinuxBionicCflags", linuxBionicCflags)
-	exportedVars.ExportStringListStaticVariable("LinuxBionicLdflags", linuxBionicLdflags)
-	exportedVars.ExportStringListStaticVariable("LinuxBionicLldflags", linuxBionicLldflags)
+	pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
+	pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
+	pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLldflags, " "))
 
 	// Use the device gcc toolchain for now
-	exportedVars.ExportStringStaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
-	exportedVars.ExportSourcePathVariable("LinuxBionicGccRoot",
+	pctx.StaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
+	pctx.SourcePathVariable("LinuxBionicGccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${LinuxBionicGccVersion}")
 }
 
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 9bc54d6..7f22377 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -120,40 +120,40 @@
 )
 
 func init() {
-	exportedVars.ExportStringStaticVariable("LinuxGccVersion", linuxGccVersion)
-	exportedVars.ExportStringStaticVariable("LinuxGlibcVersion", linuxGlibcVersion)
+	pctx.StaticVariable("LinuxGccVersion", linuxGccVersion)
+	pctx.StaticVariable("LinuxGlibcVersion", linuxGlibcVersion)
 
 	// Most places use the full GCC version. A few only use up to the first two numbers.
 	if p := strings.Split(linuxGccVersion, "."); len(p) > 2 {
-		exportedVars.ExportStringStaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], "."))
+		pctx.StaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], "."))
 	} else {
-		exportedVars.ExportStringStaticVariable("ShortLinuxGccVersion", linuxGccVersion)
+		pctx.StaticVariable("ShortLinuxGccVersion", linuxGccVersion)
 	}
 
-	exportedVars.ExportSourcePathVariable("LinuxGccRoot",
+	pctx.SourcePathVariable("LinuxGccRoot",
 		"prebuilts/gcc/linux-x86/host/x86_64-linux-glibc${LinuxGlibcVersion}-${ShortLinuxGccVersion}")
 
-	exportedVars.ExportStringListStaticVariable("LinuxGccTriple", []string{"x86_64-linux"})
+	pctx.StaticVariable("LinuxGccTriple", "x86_64-linux")
 
-	exportedVars.ExportStringListStaticVariable("LinuxCflags", linuxCflags)
-	exportedVars.ExportStringListStaticVariable("LinuxLdflags", linuxLdflags)
-	exportedVars.ExportStringListStaticVariable("LinuxLldflags", linuxLldflags)
-	exportedVars.ExportStringListStaticVariable("LinuxGlibcCflags", linuxGlibcCflags)
-	exportedVars.ExportStringListStaticVariable("LinuxGlibcLdflags", linuxGlibcLdflags)
-	exportedVars.ExportStringListStaticVariable("LinuxGlibcLldflags", linuxGlibcLdflags)
-	exportedVars.ExportStringListStaticVariable("LinuxMuslCflags", linuxMuslCflags)
-	exportedVars.ExportStringListStaticVariable("LinuxMuslLdflags", linuxMuslLdflags)
-	exportedVars.ExportStringListStaticVariable("LinuxMuslLldflags", linuxMuslLdflags)
+	pctx.StaticVariable("LinuxCflags", strings.Join(linuxCflags, " "))
+	pctx.StaticVariable("LinuxLdflags", strings.Join(linuxLdflags, " "))
+	pctx.StaticVariable("LinuxLldflags", strings.Join(linuxLldflags, " "))
+	pctx.StaticVariable("LinuxGlibcCflags", strings.Join(linuxGlibcCflags, " "))
+	pctx.StaticVariable("LinuxGlibcLdflags", strings.Join(linuxGlibcLdflags, " "))
+	pctx.StaticVariable("LinuxGlibcLldflags", strings.Join(linuxGlibcLdflags, " "))
+	pctx.StaticVariable("LinuxMuslCflags", strings.Join(linuxMuslCflags, " "))
+	pctx.StaticVariable("LinuxMuslLdflags", strings.Join(linuxMuslLdflags, " "))
+	pctx.StaticVariable("LinuxMuslLldflags", strings.Join(linuxMuslLdflags, " "))
 
-	exportedVars.ExportStringListStaticVariable("LinuxX86Cflags", linuxX86Cflags)
-	exportedVars.ExportStringListStaticVariable("LinuxX8664Cflags", linuxX8664Cflags)
-	exportedVars.ExportStringListStaticVariable("LinuxX86Ldflags", linuxX86Ldflags)
-	exportedVars.ExportStringListStaticVariable("LinuxX86Lldflags", linuxX86Ldflags)
-	exportedVars.ExportStringListStaticVariable("LinuxX8664Ldflags", linuxX8664Ldflags)
-	exportedVars.ExportStringListStaticVariable("LinuxX8664Lldflags", linuxX8664Ldflags)
+	pctx.StaticVariable("LinuxX86Cflags", strings.Join(linuxX86Cflags, " "))
+	pctx.StaticVariable("LinuxX8664Cflags", strings.Join(linuxX8664Cflags, " "))
+	pctx.StaticVariable("LinuxX86Ldflags", strings.Join(linuxX86Ldflags, " "))
+	pctx.StaticVariable("LinuxX86Lldflags", strings.Join(linuxX86Ldflags, " "))
+	pctx.StaticVariable("LinuxX8664Ldflags", strings.Join(linuxX8664Ldflags, " "))
+	pctx.StaticVariable("LinuxX8664Lldflags", strings.Join(linuxX8664Ldflags, " "))
 	// Yasm flags
-	exportedVars.ExportStringListStaticVariable("LinuxX86YasmFlags", []string{"-f elf32 -m x86"})
-	exportedVars.ExportStringListStaticVariable("LinuxX8664YasmFlags", []string{"-f elf64 -m amd64"})
+	pctx.StaticVariable("LinuxX86YasmFlags", "-f elf32 -m x86")
+	pctx.StaticVariable("LinuxX8664YasmFlags", "-f elf64 -m amd64")
 }
 
 type toolchainLinux struct {
diff --git a/cc/genrule.go b/cc/genrule.go
index 559c155..431a01c 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -101,21 +101,14 @@
 
 func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleContext) []string {
 	var variants []string
-	vndkVersion := ctx.DeviceConfig().VndkVersion()
 	vendorVariantRequired := Bool(g.Vendor_available) || Bool(g.Odm_available) || ctx.SocSpecific() || ctx.DeviceSpecific()
 	productVariantRequired := Bool(g.Product_available) || ctx.ProductSpecific()
 
-	if vndkVersion == "" {
-		if vendorVariantRequired {
-			variants = append(variants, VendorVariation)
-		}
-		if productVariantRequired {
-			variants = append(variants, ProductVariation)
-		}
-	} else {
-		if vendorVariantRequired {
-			variants = append(variants, VendorVariationPrefix+vndkVersion)
-		}
+	if vendorVariantRequired {
+		variants = append(variants, VendorVariation)
+	}
+	if productVariantRequired {
+		variants = append(variants, ProductVariation)
 	}
 
 	return variants
diff --git a/cc/image.go b/cc/image.go
index 76cb09f..f8c5ca5 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -428,17 +428,8 @@
 	var vendorVariants []string
 	var productVariants []string
 
-	boardVndkVersion := mctx.DeviceConfig().VndkVersion()
 	needVndkVersionVendorVariantForLlndk := false
-	if boardVndkVersion != "" {
-		boardVndkApiLevel, err := android.ApiLevelFromUser(mctx, boardVndkVersion)
-		if err == nil && !boardVndkApiLevel.IsPreview() {
-			// VNDK snapshot newer than v30 has LLNDK stub libraries.
-			// Only the VNDK version less than or equal to v30 requires generating the vendor
-			// variant of the VNDK version from the source tree.
-			needVndkVersionVendorVariantForLlndk = boardVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, "30"))
-		}
-	}
+
 	if m.NeedsLlndkVariants() {
 		// This is an LLNDK library.  The implementation of the library will be on /system,
 		// and vendor and product variants will be created with LLNDK stubs.
@@ -449,13 +440,13 @@
 		// Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not
 		// provide the LLNDK stub libraries.
 		if needVndkVersionVendorVariantForLlndk {
-			vendorVariants = append(vendorVariants, boardVndkVersion)
+			vendorVariants = append(vendorVariants, "")
 		}
 	} else if m.NeedsVendorPublicLibraryVariants() {
 		// A vendor public library has the implementation on /vendor, with stub variants
 		// for system and product.
 		coreVariantNeeded = true
-		vendorVariants = append(vendorVariants, boardVndkVersion)
+		vendorVariants = append(vendorVariants, "")
 		productVariants = append(productVariants, "")
 	} else if m.IsSnapshotPrebuilt() {
 		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
@@ -483,21 +474,7 @@
 		}
 	} else if vendorSpecific && m.SdkVersion() == "" {
 		// This will be available in /vendor (or /odm) only
-
-		// kernel_headers is a special module type whose exported headers
-		// are coming from DeviceKernelHeaders() which is always vendor
-		// dependent. They'll always have both vendor variants.
-		// For other modules, we assume that modules under proprietary
-		// paths are compatible for BOARD_VNDK_VERSION. The other modules
-		// are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
-		if m.KernelHeadersDecorator() {
-			vendorVariants = append(vendorVariants,
-				"",
-				boardVndkVersion,
-			)
-		} else {
-			vendorVariants = append(vendorVariants, "")
-		}
+		vendorVariants = append(vendorVariants, "")
 	} else {
 		// This is either in /system (or similar: /data), or is a
 		// module built with the NDK. Modules built with the NDK
@@ -669,14 +646,6 @@
 			m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
 		}
 		squashVendorSrcs(m)
-
-		// Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
-		// Hide other vendor variants to avoid collision.
-		vndkVersion := ctx.DeviceConfig().VndkVersion()
-		if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
-			m.Properties.HideFromMake = true
-			m.HideFromMake()
-		}
 	} else if strings.HasPrefix(variant, ProductVariation) {
 		m.Properties.ImageVariation = ProductVariation
 		if strings.HasPrefix(variant, ProductVariationPrefix) {
diff --git a/cc/library.go b/cc/library.go
index 2677d28..d9754df 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -17,7 +17,6 @@
 import (
 	"fmt"
 	"io"
-	"log"
 	"path/filepath"
 	"regexp"
 	"strconv"
@@ -746,20 +745,6 @@
 func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
 	name := library.getLibNameHelper(ctx.baseModuleName(), ctx.inVendor(), ctx.inProduct())
 
-	// Replace name with VNDK ext as original lib only when VNDK is enabled
-	if ctx.IsVndkExt() {
-		if ctx.DeviceConfig().VndkVersion() != "" {
-			// vndk-ext lib should have the same name with original lib
-			ctx.VisitDirectDepsWithTag(vndkExtDepTag, func(module android.Module) {
-				originalName := module.(*Module).outputFile.Path()
-				name = strings.TrimSuffix(originalName.Base(), originalName.Ext())
-			})
-		} else {
-			// TODO(b/320208784) : Suggest a solution for former VNDK-ext libraries before VNDK deprecation.
-			log.Printf("VNDK Extension on module %s will not be available once VNDK is deprecated", ctx.baseModuleName())
-		}
-	}
-
 	if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
 		if !strings.HasSuffix(name, "-host") {
 			name = name + "-host"
diff --git a/cc/makevars.go b/cc/makevars.go
index 4630330..9251d6a 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -97,8 +97,6 @@
 	ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
 	ctx.Strict("GLOBAL_CLANG_EXTERNAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideExternalGlobalCflags}")
 
-	ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
-
 	// Filter vendor_public_library that are exported to make
 	exportedVendorPublicLibraries := []string{}
 	ctx.VisitAllModules(func(module android.Module) {
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 39dd415..25231fd 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -225,7 +225,7 @@
 }
 
 func init() {
-	config.ExportStringList("StubLibraryCompilerFlags", stubLibraryCompilerFlags)
+	pctx.StaticVariable("StubLibraryCompilerFlags", strings.Join(stubLibraryCompilerFlags, " "))
 }
 
 func addStubLibraryCompilerFlags(flags Flags) Flags {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index a2c9c58..db046ec 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -402,30 +402,8 @@
 
 var _ android.SkipApexAllowedDependenciesCheck = (*libraryDependencyTag)(nil)
 
-var exportedVars = android.NewExportedVariables(pctx)
-
 func init() {
-	exportedVars.ExportStringListStaticVariable("HostOnlySanitizeFlags", hostOnlySanitizeFlags)
-	exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
-
-	exportedVars.ExportStringList("MinimalRuntimeFlags", minimalRuntimeFlags)
-
-	// Leave out "-flto" from the slices exported to bazel, as we will use the
-	// dedicated LTO feature for this. For C Flags and Linker Flags, also leave
-	// out the cross DSO flag which will be added separately under the correct conditions.
-	exportedVars.ExportStringList("CfiCFlags", append(cfiCflags[2:], cfiEnableFlag))
-	exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[2:])
-	exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
-
-	exportedVars.ExportString("SanitizeIgnorelistPrefix", sanitizeIgnorelistPrefix)
-	exportedVars.ExportString("CfiCrossDsoFlag", cfiCrossDsoFlag)
-	exportedVars.ExportString("CfiBlocklistPath", cfiBlocklistPath)
-	exportedVars.ExportString("CfiBlocklistFilename", cfiBlocklistFilename)
-	exportedVars.ExportString("CfiExportsMapPath", cfiExportsMapPath)
-	exportedVars.ExportString("CfiExportsMapFilename", cfiExportsMapFilename)
-	exportedVars.ExportString("CfiAssemblySupportFlag", cfiAssemblySupportFlag)
-
-	exportedVars.ExportString("NoSanitizeLinkRuntimeFlag", noSanitizeLinkRuntimeFlag)
+	pctx.StaticVariable("HostOnlySanitizeFlags", strings.Join(hostOnlySanitizeFlags, " "))
 
 	android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
 	android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
@@ -880,6 +858,7 @@
 
 		flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
 		flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
+		flags.CFlagsDeps = append(flags.CFlagsDeps, android.PathForSource(ctx, cfiBlocklistPath + "/" + cfiBlocklistFilename))
 		if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) {
 			flags.Local.CFlags = append(flags.Local.CFlags, cfiAssemblySupportFlag)
 		}
diff --git a/cc/testing.go b/cc/testing.go
index 2aecd5f..20c435a 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -580,6 +580,7 @@
 		"defaults/cc/common/crtend_so.c":       nil,
 		"defaults/cc/common/crtend.c":          nil,
 		"defaults/cc/common/crtbrand.c":        nil,
+		"external/compiler-rt/lib/cfi/cfi_blocklist.txt":   nil,
 
 		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
 		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a":   nil,
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index f4ba163..4d2412f 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -159,11 +159,6 @@
 
 		p.androidMkSuffix = p.NameSuffix()
 
-		vndkVersion := ctx.DeviceConfig().VndkVersion()
-		if vndkVersion == p.Version() {
-			p.androidMkSuffix = ""
-		}
-
 		android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
 			SharedLibrary: in,
 			Target:        ctx.Target(),
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 18dd553..854a366 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -10,8 +10,9 @@
         "soong",
         "soong-android",
         "soong-bpf", // for testing
-        "soong-phony", // for testing
+        "soong-java", // for testing
         "soong-linkerconfig",
+        "soong-phony", // for testing
     ],
     srcs: [
         "avb_add_hash_footer.go",
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index e640c5d..cadf9c24 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -20,6 +20,7 @@
 	"io"
 	"path/filepath"
 	"slices"
+	"strconv"
 	"strings"
 
 	"android/soong/android"
@@ -35,8 +36,8 @@
 
 func registerBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("android_filesystem", filesystemFactory)
+	ctx.RegisterModuleType("android_filesystem_defaults", filesystemDefaultsFactory)
 	ctx.RegisterModuleType("android_system_image", systemImageFactory)
-	ctx.RegisterModuleType("android_system_image_defaults", systemImageDefaultsFactory)
 	ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
 	ctx.RegisterModuleType("avb_add_hash_footer_defaults", avbAddHashFooterDefaultsFactory)
 	ctx.RegisterModuleType("avb_gen_vbmeta_image", avbGenVbmetaImageFactory)
@@ -46,6 +47,7 @@
 type filesystem struct {
 	android.ModuleBase
 	android.PackagingBase
+	android.DefaultableModuleBase
 
 	properties filesystemProperties
 
@@ -82,6 +84,9 @@
 	// avbtool. Default used by avbtool is sha1.
 	Avb_hash_algorithm *string
 
+	// The index used to prevent rollback of the image. Only used if use_avb is true.
+	Rollback_index *int64
+
 	// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
 	Partition_name *string
 
@@ -140,6 +145,7 @@
 	module.AddProperties(&module.properties)
 	android.InitPackageModule(module)
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 }
 
 var dependencyTag = struct {
@@ -186,9 +192,7 @@
 var pctx = android.NewPackageContext("android/soong/filesystem")
 
 func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	if !android.InList(f.PartitionType(), validPartitions) {
-		ctx.PropertyErrorf("partition_type", "partition_type must be one of %s, found: %s", validPartitions, f.PartitionType())
-	}
+	validatePartitionType(ctx, f)
 	switch f.fsType(ctx) {
 	case ext4Type:
 		f.output = f.buildImageUsingBuildImage(ctx)
@@ -204,6 +208,22 @@
 	ctx.InstallFile(f.installDir, f.installFileName(), f.output)
 }
 
+func validatePartitionType(ctx android.ModuleContext, p partition) {
+	if !android.InList(p.PartitionType(), validPartitions) {
+		ctx.PropertyErrorf("partition_type", "partition_type must be one of %s, found: %s", validPartitions, p.PartitionType())
+	}
+
+	ctx.VisitDirectDepsWithTag(android.DefaultsDepTag, func(m android.Module) {
+		if fdm, ok := m.(*filesystemDefaults); ok {
+			if p.PartitionType() != fdm.PartitionType() {
+				ctx.PropertyErrorf("partition_type",
+					"%s doesn't match with the partition type %s of the filesystem default module %s",
+					p.PartitionType(), fdm.PartitionType(), m.Name())
+			}
+		}
+	})
+}
+
 // Copy extra files/dirs that are not from the `deps` property to `rootDir`, checking for conflicts with files
 // already in `rootDir`.
 func (f *filesystem) buildNonDepsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.OutputPath) {
@@ -352,6 +372,13 @@
 		if hashAlgorithm := proptools.String(f.properties.Avb_hash_algorithm); hashAlgorithm != "" {
 			avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm
 		}
+		if f.properties.Rollback_index != nil {
+			rollbackIndex := proptools.Int(f.properties.Rollback_index)
+			if rollbackIndex < 0 {
+				ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative")
+			}
+			avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex)
+		}
 		securityPatchKey := "com.android.build." + f.partitionName() + ".security_patch"
 		securityPatchValue := ctx.Config().PlatformSecurityPatch()
 		avb_add_hashtree_footer_args += " --prop " + securityPatchKey + ":" + securityPatchValue
@@ -458,10 +485,16 @@
 		Text(android.PathForArbitraryOutput(ctx, stagingDir).String())
 }
 
+type partition interface {
+	PartitionType() string
+}
+
 func (f *filesystem) PartitionType() string {
 	return proptools.StringDefault(f.properties.Partition_type, "system")
 }
 
+var _ partition = (*filesystem)(nil)
+
 var _ android.AndroidMkEntriesProvider = (*filesystem)(nil)
 
 // Implements android.AndroidMkEntriesProvider
@@ -535,3 +568,37 @@
 func (*filesystem) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
 	return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled()
 }
+
+// android_filesystem_defaults
+
+type filesystemDefaults struct {
+	android.ModuleBase
+	android.DefaultsModuleBase
+
+	properties filesystemDefaultsProperties
+}
+
+type filesystemDefaultsProperties struct {
+	// Identifies which partition this is for //visibility:any_system_image (and others) visibility
+	// checks, and will be used in the future for API surface checks.
+	Partition_type *string
+}
+
+// android_filesystem_defaults is a default module for android_filesystem and android_system_image
+func filesystemDefaultsFactory() android.Module {
+	module := &filesystemDefaults{}
+	module.AddProperties(&module.properties)
+	module.AddProperties(&android.PackagingProperties{})
+	android.InitDefaultsModule(module)
+	return module
+}
+
+func (f *filesystemDefaults) PartitionType() string {
+	return proptools.StringDefault(f.properties.Partition_type, "system")
+}
+
+var _ partition = (*filesystemDefaults)(nil)
+
+func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	validatePartitionType(ctx, f)
+}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 5c780f8..f4ecad4 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -23,6 +23,7 @@
 	"android/soong/bpf"
 	"android/soong/cc"
 	"android/soong/etc"
+	"android/soong/java"
 	"android/soong/phony"
 
 	"github.com/google/blueprint/proptools"
@@ -34,9 +35,12 @@
 
 var fixture = android.GroupFixturePreparers(
 	android.PrepareForIntegrationTestWithAndroid,
+	android.PrepareForTestWithAndroidBuildComponents,
 	bpf.PrepareForTestWithBpf,
-	etc.PrepareForTestWithPrebuiltEtc,
 	cc.PrepareForIntegrationTestWithCc,
+	etc.PrepareForTestWithPrebuiltEtc,
+	java.PrepareForTestWithJavaBuildComponents,
+	java.PrepareForTestWithJavaDefaultModules,
 	phony.PrepareForTestWithPhony,
 	PrepareForTestWithFilesystemBuildComponents,
 )
@@ -88,12 +92,21 @@
 
 		phony {
 			name: "phony",
-			required: ["libquz"],
+			required: [
+				"libquz",
+				"myapp",
+			],
 		}
 
 		cc_library {
 			name: "libquz",
 		}
+
+		android_app {
+			name: "myapp",
+			platform_apis: true,
+			installable: true,
+		}
 	`)
 
 	// produces "myfilesystem.img"
@@ -101,6 +114,7 @@
 
 	fs := result.ModuleForTests("myfilesystem", "android_common").Module().(*filesystem)
 	expected := []string{
+		"app/myapp/myapp.apk",
 		"bin/foo",
 		"lib/libbar.so",
 		"lib64/libbar.so",
@@ -367,7 +381,7 @@
 
 func TestSystemImageDefaults(t *testing.T) {
 	result := fixture.RunTestWithBp(t, `
-		android_system_image_defaults {
+		android_filesystem_defaults {
 			name: "defaults",
 			multilib: {
 				common: {
@@ -433,3 +447,25 @@
 		android.AssertStringListContains(t, "missing entry", fs.entries, e)
 	}
 }
+
+func TestInconsistentPartitionTypesInDefaults(t *testing.T) {
+	fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+		"doesn't match with the partition type")).
+		RunTestWithBp(t, `
+		android_filesystem_defaults {
+			name: "system_ext_def",
+			partition_type: "system_ext",
+		}
+
+		android_filesystem_defaults {
+			name: "system_def",
+			partition_type: "system",
+			defaults: ["system_ext_def"],
+		}
+
+		android_system_image {
+			name: "system",
+			defaults: ["system_def"],
+		}
+	`)
+}
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 92bb206..5028a49 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -21,7 +21,6 @@
 
 type systemImage struct {
 	filesystem
-	android.DefaultableModuleBase
 
 	properties systemImageProperties
 }
@@ -40,7 +39,6 @@
 	module.filesystem.buildExtraFiles = module.buildExtraFiles
 	module.filesystem.filterPackagingSpec = module.filterPackagingSpec
 	initFilesystemModule(&module.filesystem)
-	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -102,17 +100,3 @@
 func (s *systemImage) filterPackagingSpec(ps android.PackagingSpec) bool {
 	return ps.Partition() == "system"
 }
-
-type systemImageDefaults struct {
-	android.ModuleBase
-	android.DefaultsModuleBase
-}
-
-// android_system_image_defaults is a default module for android_system_image module.
-func systemImageDefaultsFactory() android.Module {
-	module := &systemImageDefaults{}
-	module.AddProperties(&android.PackagingProperties{})
-	module.AddProperties(&systemImageProperties{})
-	android.InitDefaultsModule(module)
-	return module
-}
diff --git a/java/config/config.go b/java/config/config.go
index d720046..2bb50f6 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -26,8 +26,7 @@
 )
 
 var (
-	pctx         = android.NewPackageContext("android/soong/java/config")
-	exportedVars = android.NewExportedVariables(pctx)
+	pctx = android.NewPackageContext("android/soong/java/config")
 
 	LegacyCorePlatformBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"}
 	LegacyCorePlatformSystemModules          = "legacy-core-platform-api-stubs-system-modules"
@@ -79,30 +78,30 @@
 func init() {
 	pctx.Import("github.com/google/blueprint/bootstrap")
 
-	exportedVars.ExportStringStaticVariable("JavacHeapSize", "4096M")
-	exportedVars.ExportStringStaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
+	pctx.StaticVariable("JavacHeapSize", "4096M")
+	pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
 
 	// ErrorProne can use significantly more memory than javac alone, give it a higher heap
 	// size (b/221480398).
-	exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "8192M")
-	exportedVars.ExportStringStaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
+	pctx.StaticVariable("ErrorProneHeapSize", "8192M")
+	pctx.StaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
 
 	// D8 invocations are shorter lived, so we restrict their JIT tiering relative to R8.
 	// Note that the `-JXX` prefix syntax is specific to the R8/D8 invocation wrappers.
-	exportedVars.ExportStringListStaticVariable("D8Flags", append([]string{
+	pctx.StaticVariable("D8Flags", strings.Join(append([]string{
 		"-JXmx4096M",
 		"-JXX:+TieredCompilation",
 		"-JXX:TieredStopAtLevel=1",
 		"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
 		"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
-	}, dexerJavaVmFlagsList...))
-	exportedVars.ExportStringListStaticVariable("R8Flags", append([]string{
+	}, dexerJavaVmFlagsList...), " "))
+	pctx.StaticVariable("R8Flags", strings.Join(append([]string{
 		"-JXmx4096M",
 		"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
 		"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
-	}, dexerJavaVmFlagsList...))
+	}, dexerJavaVmFlagsList...), " "))
 
-	exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{
+	pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
 		`-Xmaxerrs 9999999`,
 		`-encoding UTF-8`,
 		`-sourcepath ""`,
@@ -116,10 +115,10 @@
 
 		// b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9
 		`-XDstringConcat=inline`,
-	})
+	}, " "))
 
-	exportedVars.ExportStringListStaticVariable("JavaVmFlags", javaVmFlagsList)
-	exportedVars.ExportStringListStaticVariable("JavacVmFlags", javacVmFlagsList)
+	pctx.StaticVariable("JavaVmFlags", strings.Join(javaVmFlagsList, " "))
+	pctx.StaticVariable("JavacVmFlags", strings.Join(javacVmFlagsList, " "))
 
 	pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
 
diff --git a/java/config/droidstubs.go b/java/config/droidstubs.go
index 39eec44..04a3f96 100644
--- a/java/config/droidstubs.go
+++ b/java/config/droidstubs.go
@@ -58,11 +58,7 @@
 )
 
 func init() {
-	exportedVars.ExportStringList("MetalavaFlags", metalavaFlags)
+	pctx.StaticVariable("MetalavaAnnotationsFlags", strings.Join(metalavaAnnotationsFlags, " "))
 
-	exportedVars.ExportString("MetalavaAddOpens", MetalavaAddOpens)
-
-	exportedVars.ExportStringListStaticVariable("MetalavaAnnotationsFlags", metalavaAnnotationsFlags)
-
-	exportedVars.ExportStringListStaticVariable("MetalavaAnnotationWarningsFlags", metalavaAnnotationsWarningsFlags)
+	pctx.StaticVariable("MetalavaAnnotationWarningsFlags", strings.Join(metalavaAnnotationsWarningsFlags, " "))
 }
diff --git a/java/config/error_prone.go b/java/config/error_prone.go
index 5f853c8..767164f 100644
--- a/java/config/error_prone.go
+++ b/java/config/error_prone.go
@@ -15,6 +15,7 @@
 package config
 
 import (
+	"android/soong/android"
 	"strings"
 )
 
@@ -29,23 +30,23 @@
 )
 
 // Wrapper that grabs value of val late so it can be initialized by a later module's init function
-func errorProneVar(val *[]string, sep string) func() string {
-	return func() string {
+func errorProneVar(val *[]string, sep string) func(android.PackageVarContext) string {
+	return func(android.PackageVarContext) string {
 		return strings.Join(*val, sep)
 	}
 }
 
 func init() {
-	exportedVars.ExportVariableFuncVariable("ErrorProneClasspath", errorProneVar(&ErrorProneClasspath, ":"))
-	exportedVars.ExportVariableFuncVariable("ErrorProneChecksError", errorProneVar(&ErrorProneChecksError, " "))
-	exportedVars.ExportVariableFuncVariable("ErrorProneChecksWarning", errorProneVar(&ErrorProneChecksWarning, " "))
-	exportedVars.ExportVariableFuncVariable("ErrorProneChecksDefaultDisabled", errorProneVar(&ErrorProneChecksDefaultDisabled, " "))
-	exportedVars.ExportVariableFuncVariable("ErrorProneChecksOff", errorProneVar(&ErrorProneChecksOff, " "))
-	exportedVars.ExportVariableFuncVariable("ErrorProneFlags", errorProneVar(&ErrorProneFlags, " "))
-	exportedVars.ExportStringListStaticVariable("ErrorProneChecks", []string{
+	pctx.VariableFunc("ErrorProneClasspath", errorProneVar(&ErrorProneClasspath, ":"))
+	pctx.VariableFunc("ErrorProneChecksError", errorProneVar(&ErrorProneChecksError, " "))
+	pctx.VariableFunc("ErrorProneChecksWarning", errorProneVar(&ErrorProneChecksWarning, " "))
+	pctx.VariableFunc("ErrorProneChecksDefaultDisabled", errorProneVar(&ErrorProneChecksDefaultDisabled, " "))
+	pctx.VariableFunc("ErrorProneChecksOff", errorProneVar(&ErrorProneChecksOff, " "))
+	pctx.VariableFunc("ErrorProneFlags", errorProneVar(&ErrorProneFlags, " "))
+	pctx.StaticVariable("ErrorProneChecks", strings.Join([]string{
 		"${ErrorProneChecksOff}",
 		"${ErrorProneChecksError}",
 		"${ErrorProneChecksWarning}",
 		"${ErrorProneChecksDefaultDisabled}",
-	})
+	}, " "))
 }
diff --git a/java/java.go b/java/java.go
index c5bdf9d..fb5bb1c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -800,6 +800,7 @@
 		"android.hardware.security.keymint-V2-java":         true,
 		"android.hardware.security.keymint-V3-java":         true,
 		"android.hardware.security.keymint-V4-java":         true,
+		"android.hardware.security.secretkeeper-V1-java":    true,
 		"android.hardware.security.secureclock-V1-java":     true,
 		"android.hardware.security.secureclock-V2-java":     true,
 		"android.hardware.thermal-V1-java":                  true,
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 6c021c7..9850570 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -54,7 +54,7 @@
 			strings.Join(rustFlags, " "))
 	}
 
-	ExportedVars.ExportStringListStaticVariable("DEVICE_ARM64_RUSTC_FLAGS", Arm64RustFlags)
+	pctx.StaticVariable("DEVICE_ARM64_RUSTC_FLAGS", strings.Join(Arm64RustFlags, " "))
 }
 
 type toolchainArm64 struct {
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
index a5f4afb..5394e8a 100644
--- a/rust/config/arm_device.go
+++ b/rust/config/arm_device.go
@@ -44,7 +44,7 @@
 			strings.Join(rustFlags, " "))
 	}
 
-	ExportedVars.ExportStringListStaticVariable("DEVICE_ARM_RUSTC_FLAGS", ArmRustFlags)
+	pctx.StaticVariable("DEVICE_ARM_RUSTC_FLAGS", strings.Join(ArmRustFlags, " "))
 }
 
 type toolchainArm struct {
diff --git a/rust/config/global.go b/rust/config/global.go
index e28dbaa..2323049 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -22,8 +22,7 @@
 )
 
 var (
-	pctx         = android.NewPackageContext("android/soong/rust/config")
-	ExportedVars = android.NewExportedVariables(pctx)
+	pctx = android.NewPackageContext("android/soong/rust/config")
 
 	RustDefaultVersion = "1.76.0"
 	RustDefaultBase    = "prebuilts/rust/"
@@ -112,17 +111,17 @@
 
 	pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
 
-	ExportedVars.ExportStringStaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion)
-	ExportedVars.ExportStringListStaticVariable("GLOBAL_RUSTC_FLAGS", GlobalRustFlags)
-	ExportedVars.ExportStringListStaticVariable("LINUX_HOST_GLOBAL_LINK_FLAGS", LinuxHostGlobalLinkFlags)
+	pctx.StaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion)
+	pctx.StaticVariable("GLOBAL_RUSTC_FLAGS", strings.Join(GlobalRustFlags, " "))
+	pctx.StaticVariable("LINUX_HOST_GLOBAL_LINK_FLAGS", strings.Join(LinuxHostGlobalLinkFlags, " "))
 
-	ExportedVars.ExportStringListStaticVariable("DEVICE_GLOBAL_RUSTC_FLAGS", deviceGlobalRustFlags)
-	ExportedVars.ExportStringListStaticVariable("DEVICE_GLOBAL_LINK_FLAGS",
-		android.RemoveListFromList(deviceGlobalLinkFlags, []string{
+	pctx.StaticVariable("DEVICE_GLOBAL_RUSTC_FLAGS", strings.Join(deviceGlobalRustFlags, " "))
+	pctx.StaticVariable("DEVICE_GLOBAL_LINK_FLAGS",
+		strings.Join(android.RemoveListFromList(deviceGlobalLinkFlags, []string{
 			// The cc_config flags are retrieved from cc_toolchain by rust rules.
 			"${cc_config.DeviceGlobalLldflags}",
 			"-B${cc_config.ClangBin}",
-		}))
+		}), " "))
 }
 
 func HostPrebuiltTag(config android.Config) string {
diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go
index 49f7c77..fee1923 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -54,7 +54,7 @@
 		pctx.StaticVariable("X86_64"+variant+"VariantRustFlags",
 			strings.Join(rustFlags, " "))
 	}
-	ExportedVars.ExportStringListStaticVariable("DEVICE_X86_64_RUSTC_FLAGS", x86_64RustFlags)
+	pctx.StaticVariable("DEVICE_X86_64_RUSTC_FLAGS", strings.Join(x86_64RustFlags, " "))
 }
 
 type toolchainX86_64 struct {
diff --git a/rust/config/x86_device.go b/rust/config/x86_device.go
index 2a57e73..5d9d88a 100644
--- a/rust/config/x86_device.go
+++ b/rust/config/x86_device.go
@@ -56,7 +56,7 @@
 			strings.Join(rustFlags, " "))
 	}
 
-	ExportedVars.ExportStringListStaticVariable("DEVICE_X86_RUSTC_FLAGS", x86RustFlags)
+	pctx.StaticVariable("DEVICE_X86_RUSTC_FLAGS", strings.Join(x86RustFlags, " "))
 }
 
 type toolchainX86 struct {
diff --git a/rust/image.go b/rust/image.go
index 530c56e..e0d267d 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -208,14 +208,6 @@
 		if strings.HasPrefix(variant, cc.VendorVariationPrefix) {
 			m.Properties.VndkVersion = strings.TrimPrefix(variant, cc.VendorVariationPrefix)
 		}
-
-		// Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
-		// Hide other vendor variants to avoid collision.
-		vndkVersion := ctx.DeviceConfig().VndkVersion()
-		if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
-			m.Properties.HideFromMake = true
-			m.HideFromMake()
-		}
 	} else if strings.HasPrefix(variant, cc.ProductVariation) {
 		m.Properties.ImageVariation = cc.ProductVariation
 		if strings.HasPrefix(variant, cc.ProductVariationPrefix) {