Merge "Move env var config loading to be within the config package."
diff --git a/android/bazel.go b/android/bazel.go
index 528c7b1..0940205 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -217,7 +217,6 @@
 		"external/bazelbuild-rules_android":/* recursive = */ true,
 		"external/bazel-skylib":/* recursive = */ true,
 		"external/guava":/* recursive = */ true,
-		"external/error_prone":/* recursive = */ true,
 		"external/jsr305":/* recursive = */ true,
 		"frameworks/ex/common":/* recursive = */ true,
 
@@ -292,6 +291,7 @@
 		"external/bouncycastle":                              Bp2BuildDefaultTrue,
 		"external/brotli":                                    Bp2BuildDefaultTrue,
 		"external/conscrypt":                                 Bp2BuildDefaultTrue,
+		"external/error_prone":                               Bp2BuildDefaultTrue,
 		"external/fmtlib":                                    Bp2BuildDefaultTrueRecursively,
 		"external/google-benchmark":                          Bp2BuildDefaultTrueRecursively,
 		"external/googletest":                                Bp2BuildDefaultTrueRecursively,
@@ -341,6 +341,7 @@
 		"packages/screensavers/Basic":                        Bp2BuildDefaultTrue,
 		"packages/services/Car/tests/SampleRearViewCamera":   Bp2BuildDefaultTrue,
 		"prebuilts/clang/host/linux-x86":                     Bp2BuildDefaultTrueRecursively,
+		"prebuilts/tools/common/m2":                          Bp2BuildDefaultTrue,
 		"system/apex":                                        Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
 		"system/apex/proto":                                  Bp2BuildDefaultTrueRecursively,
 		"system/apex/libs":                                   Bp2BuildDefaultTrueRecursively,
@@ -469,10 +470,11 @@
 		"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
 
 		// go deps:
-		"apex-protos",               // depends on soong_zip, a go binary
-		"robolectric_tzdata",        // depends on soong_zip, a go binary
-		"host_bionic_linker_asm",    // depends on extract_linker, a go binary.
-		"host_bionic_linker_script", // depends on extract_linker, a go binary.
+		"apex-protos",                    // depends on soong_zip, a go binary
+		"robolectric_tzdata",             // depends on soong_zip, a go binary
+		"robolectric-sqlite4java-native", // depends on soong_zip, a go binary
+		"host_bionic_linker_asm",         // depends on extract_linker, a go binary.
+		"host_bionic_linker_script",      // depends on extract_linker, a go binary.
 
 		// java deps
 		"bin2c_fastdeployagent", // depends on deployagent, a java binary
diff --git a/android/config.go b/android/config.go
index 4472036..10e074c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -24,6 +24,7 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"reflect"
 	"runtime"
 	"strconv"
 	"strings"
@@ -273,15 +274,45 @@
 		return fmt.Errorf("Could not create dir %s: %s", dir, err)
 	}
 
-	data, err := json.MarshalIndent(&config, "", "    ")
+	nonArchVariantProductVariables := []string{}
+	archVariantProductVariables := []string{}
+	p := variableProperties{}
+	t := reflect.TypeOf(p.Product_variables)
+	for i := 0; i < t.NumField(); i++ {
+		f := t.Field(i)
+		nonArchVariantProductVariables = append(nonArchVariantProductVariables, strings.ToLower(f.Name))
+		if proptools.HasTag(f, "android", "arch_variant") {
+			archVariantProductVariables = append(archVariantProductVariables, strings.ToLower(f.Name))
+		}
+	}
+
+	//TODO(b/216168792) should use common function to print Starlark code
+	nonArchVariantProductVariablesJson, err := json.MarshalIndent(&nonArchVariantProductVariables, "", "    ")
+	if err != nil {
+		return fmt.Errorf("cannot marshal product variable data: %s", err.Error())
+	}
+
+	//TODO(b/216168792) should use common function to print Starlark code
+	archVariantProductVariablesJson, err := json.MarshalIndent(&archVariantProductVariables, "", "    ")
+	if err != nil {
+		return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error())
+	}
+
+	configJson, err := json.MarshalIndent(&config, "", "    ")
 	if err != nil {
 		return fmt.Errorf("cannot marshal config data: %s", err.Error())
 	}
 
 	bzl := []string{
 		bazel.GeneratedBazelFileWarning,
-		fmt.Sprintf(`_product_vars = json.decode("""%s""")`, data),
-		"product_vars = _product_vars\n",
+		fmt.Sprintf(`_product_vars = json.decode("""%s""")`, configJson),
+		fmt.Sprintf(`_product_var_constraints = %s`, nonArchVariantProductVariablesJson),
+		fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
+		"\n", `
+product_vars = _product_vars
+product_var_constraints = _product_var_constraints
+arch_variant_product_var_constraints = _arch_variant_product_var_constraints
+`,
 	}
 	err = ioutil.WriteFile(filepath.Join(dir, "product_variables.bzl"), []byte(strings.Join(bzl, "\n")), 0644)
 	if err != nil {
diff --git a/android/module.go b/android/module.go
index 3c8c777..666732f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -267,7 +267,7 @@
 	//
 	// The Modules passed to the visit function should not be retained outside of the visit function, they may be
 	// invalidated by future mutators.
-	WalkDeps(visit func(Module, Module) bool)
+	WalkDeps(visit func(child, parent Module) bool)
 
 	// WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
 	// tree in top down order.  visit may be called multiple times for the same (child, parent)
@@ -2620,7 +2620,7 @@
 	}
 
 	if aModule == nil {
-		b.ModuleErrorf("module %q not an android module", b.OtherModuleName(module))
+		b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
 		return nil
 	}
 
@@ -2742,8 +2742,8 @@
 
 func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
 	b.bp.VisitDirectDeps(func(module blueprint.Module) {
-		if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
-			if b.bp.OtherModuleDependencyTag(aModule) == tag {
+		if b.bp.OtherModuleDependencyTag(module) == tag {
+			if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
 				visit(aModule)
 			}
 		}
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 3c36197..abdbf53 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -699,7 +699,7 @@
 		expected: `
 			android_library {
 				srcs: ["test.java"],
-				resource_dirs: ["res"],
+
 				jacoco: {
 					include_filter: ["foo.*"],
 				},
@@ -1458,7 +1458,7 @@
 runtime_resource_overlay {
 	name: "foo",
 	product_specific: true,
-	resource_dirs: ["res"],
+
 	sdk_version: "current",
 	theme: "FooTheme",
 
@@ -1604,6 +1604,22 @@
 }
 `,
 	},
+	{
+		desc: "Drop default resource and asset dirs from bp",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+include $(BUILD_PACKAGE)
+`,
+		expected: `
+android_app {
+		name: "foo",
+
+}
+`,
+	},
 }
 
 func TestEndToEnd(t *testing.T) {
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
new file mode 100644
index 0000000..2f7211c
--- /dev/null
+++ b/bp2build/java_import_conversion_test.go
@@ -0,0 +1,52 @@
+// Copyright 2022 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 bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/java"
+
+	"testing"
+)
+
+func runJavaImportTestCase(t *testing.T, tc bp2buildTestCase) {
+	t.Helper()
+	runBp2BuildTestCase(t, registerJavaImportModuleTypes, tc)
+}
+
+func registerJavaImportModuleTypes(ctx android.RegistrationContext) {
+}
+
+func TestMinimalJavaImport(t *testing.T) {
+	runJavaImportTestCase(t, bp2buildTestCase{
+		description:                "Java import - simple example",
+		moduleTypeUnderTest:        "java_import",
+		moduleTypeUnderTestFactory: java.ImportFactory,
+		filesystem: map[string]string{
+			"import.jar": "",
+		},
+		blueprint: `
+java_import {
+        name: "example_import",
+        jars: ["import.jar"],
+        bazel_module: { bp2build_available: true },
+}
+`,
+		expectedBazelTargets: []string{
+			makeBazelTarget("java_import", "example_import", attrNameToString{
+				"jars": `["import.jar"]`,
+			}),
+		}})
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 187b4db..a4999e5 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -23,6 +23,7 @@
 	_ "android/soong/cc/config"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -41,6 +42,14 @@
 			CommandDeps: []string{"$ccCmd"},
 		},
 		"ccCmd", "cFlags")
+
+	stripRule = pctx.AndroidStaticRule("stripRule",
+		blueprint.RuleParams{
+			Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
+				`--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
+			CommandDeps: []string{"$stripCmd"},
+		},
+		"stripCmd")
 )
 
 func registerBpfBuildComponents(ctx android.RegistrationContext) {
@@ -64,6 +73,8 @@
 	Cflags       []string
 	Include_dirs []string
 	Sub_dir      string
+	// If set to true, generate BTF debug info for maps & programs
+	Btf          *bool
 }
 
 type bpf struct {
@@ -99,10 +110,14 @@
 
 	cflags = append(cflags, bpf.properties.Cflags...)
 
+	if proptools.Bool(bpf.properties.Btf) {
+		cflags = append(cflags, "-g")
+	}
+
 	srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
 
 	for _, src := range srcs {
-		obj := android.ObjPathWithExt(ctx, "", src, "o")
+		obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
 
 		ctx.Build(pctx, android.BuildParams{
 			Rule:   ccRule,
@@ -114,7 +129,21 @@
 			},
 		})
 
-		bpf.objs = append(bpf.objs, obj.WithoutRel())
+		if proptools.Bool(bpf.properties.Btf) {
+			objStripped := android.ObjPathWithExt(ctx, "", src, "o")
+			ctx.Build(pctx, android.BuildParams{
+				Rule: stripRule,
+				Input: obj,
+				Output: objStripped,
+				Args: map[string]string{
+					"stripCmd": "${config.ClangBin}/llvm-strip",
+				},
+			})
+			bpf.objs = append(bpf.objs, objStripped.WithoutRel())
+		} else {
+			bpf.objs = append(bpf.objs, obj.WithoutRel())
+		}
+
 	}
 }
 
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index a9a0b1f..4f7d88c 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -158,6 +158,10 @@
 		Name: "formatFlagProperties",
 		Fix:  runPatchListMod(formatFlagProperties),
 	},
+	{
+		Name: "removeResourcesAndAssetsIfDefault",
+		Fix:  removeResourceAndAssetsIfDefault,
+	},
 }
 
 // for fix that only need to run once
@@ -886,6 +890,24 @@
 	return nil
 }
 
+func removeResourceAndAssetsIfDefault(f *Fixer) error {
+	for _, def := range f.tree.Defs {
+		mod, ok := def.(*parser.Module)
+		if !ok {
+			continue
+		}
+		resourceDirList, resourceDirFound := getLiteralListPropertyValue(mod, "resource_dirs")
+		if resourceDirFound && len(resourceDirList) == 1 && resourceDirList[0] == "res" {
+			removeProperty(mod, "resource_dirs")
+		}
+		assetDirList, assetDirFound := getLiteralListPropertyValue(mod, "asset_dirs")
+		if assetDirFound && len(assetDirList) == 1 && assetDirList[0] == "assets" {
+			removeProperty(mod, "asset_dirs")
+		}
+	}
+	return nil
+}
+
 // Converts the default source list property, 'srcs', to a single source property with a given name.
 // "LOCAL_MODULE" reference is also resolved during the conversion process.
 func convertToSingleSource(mod *parser.Module, srcPropertyName string) {
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 1941837..17b3c24 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -19,11 +19,10 @@
 import (
 	"bytes"
 	"fmt"
+	"reflect"
 	"strings"
 	"testing"
 
-	"reflect"
-
 	"github.com/google/blueprint/parser"
 	"github.com/google/blueprint/pathtools"
 )
@@ -2063,3 +2062,124 @@
 		})
 	}
 }
+
+func TestRemoveResourceAndAssetsIfDefault(t *testing.T) {
+	tests := []struct {
+		name string
+		in   string
+		out  string
+	}{
+		{
+			name: "resource_dirs default",
+			in: `
+			android_app {
+				name: "foo",
+				resource_dirs: ["res"],
+			}
+			`,
+			out: `
+			android_app {
+				name: "foo",
+
+			}
+			`,
+		},
+		{
+			name: "resource_dirs not default",
+			in: `
+			android_app {
+				name: "foo",
+				resource_dirs: ["reso"],
+			}
+			`,
+			out: `
+			android_app {
+				name: "foo",
+				resource_dirs: ["reso"],
+			}
+			`,
+		},
+		{
+			name: "resource_dirs includes not default",
+			in: `
+			android_app {
+				name: "foo",
+				resource_dirs: ["res", "reso"],
+			}
+			`,
+			out: `
+			android_app {
+				name: "foo",
+				resource_dirs: ["res", "reso"],
+			}
+			`,
+		}, {
+			name: "asset_dirs default",
+			in: `
+			android_app {
+				name: "foo",
+				asset_dirs: ["assets"],
+			}
+			`,
+			out: `
+			android_app {
+				name: "foo",
+
+			}
+			`,
+		},
+		{
+			name: "asset_dirs not default",
+			in: `
+			android_app {
+				name: "foo",
+				asset_dirs: ["assety"],
+			}
+			`,
+			out: `
+			android_app {
+				name: "foo",
+				asset_dirs: ["assety"],
+			}
+			`,
+		},
+		{
+			name: "asset_dirs includes not default",
+			in: `
+			android_app {
+				name: "foo",
+				asset_dirs: ["assets", "assety"],
+			}
+			`,
+			out: `
+			android_app {
+				name: "foo",
+				asset_dirs: ["assets", "assety"],
+			}
+			`,
+		},
+		{
+			name: "resource_dirs and asset_dirs both default",
+			in: `
+			android_app {
+				name: "foo",
+				asset_dirs: ["assets"],
+				resource_dirs: ["res"],
+			}
+			`,
+			out: `
+			android_app {
+				name: "foo",
+
+			}
+			`,
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			runPassOnce(t, test.in, test.out, func(fixer *Fixer) error {
+				return removeResourceAndAssetsIfDefault(fixer)
+			})
+		})
+	}
+}
diff --git a/cc/Android.bp b/cc/Android.bp
index cf45630..9103a48 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -88,6 +88,7 @@
         "stub_library.go",
     ],
     testSrcs: [
+        "afdo_test.go",
         "cc_test.go",
         "compiler_test.go",
         "gen_test.go",
diff --git a/cc/OWNERS b/cc/OWNERS
index 811d881..a438b15 100644
--- a/cc/OWNERS
+++ b/cc/OWNERS
@@ -1,4 +1,4 @@
 per-file ndk_*.go = danalbert@google.com
 per-file tidy.go = srhines@google.com, chh@google.com
-per-file afdo.go,lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
-
+per-file afdo.go,afdo_test.go,lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+per-file coverage.go = pirama@google.com, srhines@google.com, allenhair@google.com
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
new file mode 100644
index 0000000..5515464
--- /dev/null
+++ b/cc/afdo_test.go
@@ -0,0 +1,70 @@
+// Copyright 2022 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 cc
+
+import (
+	"testing"
+
+	"android/soong/android"
+	"github.com/google/blueprint"
+)
+
+func TestAfdoDeps(t *testing.T) {
+	bp := `
+	cc_library {
+		name: "libTest",
+		srcs: ["foo.c"],
+		static_libs: ["libFoo"],
+		afdo: true,
+	}
+
+	cc_library {
+		name: "libFoo",
+		static_libs: ["libBar"],
+	}
+
+	cc_library {
+		name: "libBar",
+	}
+	`
+	prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
+
+	result := android.GroupFixturePreparers(
+		prepareForCcTest,
+		prepareForAfdoTest,
+	).RunTestWithBp(t, bp)
+
+	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
+	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest").Module()
+	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest").Module()
+
+	hasDep := func(m android.Module, wantDep android.Module) bool {
+		var found bool
+		result.VisitDirectDeps(m, func(dep blueprint.Module) {
+			if dep == wantDep {
+				found = true
+			}
+		})
+		return found
+	}
+
+	if !hasDep(libTest, libFoo) {
+		t.Errorf("libTest missing dependency on afdo variant of libFoo")
+	}
+
+	if !hasDep(libFoo, libBar) {
+		t.Errorf("libTest missing dependency on afdo variant of libBar")
+	}
+}
diff --git a/cc/coverage.go b/cc/coverage.go
index 8dd2db1..f2b5425 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -98,6 +98,9 @@
 		} else if clangCoverage {
 			flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag,
 				"-fcoverage-mapping", "-Wno-pass-failed", "-D__ANDROID_CLANG_COVERAGE__")
+			// Override -Wframe-larger-than.  We can expect frame size increase after
+			// coverage instrumentation.
+			flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=")
 		}
 	}
 
diff --git a/cc/pgo.go b/cc/pgo.go
index cd017c4..aa0feae 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -208,6 +208,10 @@
 		ctx.ModuleErrorf("Instrumentation PGO specification is missing benchmark property")
 	}
 
+	if isSampling {
+		ctx.ModuleErrorf("Sampling PGO is deprecated, use AFDO instead")
+	}
+
 	if isSampling && isInstrumentation {
 		ctx.PropertyErrorf("pgo", "Exactly one of \"instrumentation\" and \"sampling\" properties must be set")
 	}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index a054c91..6c68822 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -42,7 +42,6 @@
 		"-fno-omit-frame-pointer",
 		"-Wno-frame-larger-than=",
 		"-fsanitize-hwaddress-abi=platform",
-		"-mllvm", "-hwasan-use-after-scope=1",
 	}
 
 	// ThinLTO performs codegen during link time, thus these flags need to
diff --git a/cc/tidy.go b/cc/tidy.go
index 97418fe..1f5f56d 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -156,6 +156,9 @@
 	// Too many existing functions trigger this rule, and fixing it requires large code
 	// refactoring. The cost of maintaining this tidy rule outweighs the benefit it brings.
 	tidyChecks = tidyChecks + ",-bugprone-easily-swappable-parameters"
+	// http://b/216364337 - TODO: Follow-up after compiler update to
+	// disable or fix individual instances.
+	tidyChecks = tidyChecks + ",-cert-err33-c"
 	flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
 
 	if ctx.Config().IsEnvTrue("WITH_TIDY") {
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index f07eafa..b3a6ee0 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -48,6 +48,7 @@
 	delvePath   string
 
 	moduleGraphFile   string
+	moduleActionsFile string
 	docFile           string
 	bazelQueryViewDir string
 	bp2buildMarker    string
@@ -76,6 +77,7 @@
 
 	// Flags representing various modes soong_build can run in
 	flag.StringVar(&moduleGraphFile, "module_graph_file", "", "JSON module graph file to output")
+	flag.StringVar(&moduleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
 	flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
 	flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
 	flag.StringVar(&bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
@@ -176,15 +178,17 @@
 	}
 }
 
-func writeJsonModuleGraph(ctx *android.Context, path string) {
-	f, err := os.Create(shared.JoinPath(topDir, path))
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "%s", err)
+func writeJsonModuleGraphAndActions(ctx *android.Context, graphPath string, actionsPath string) {
+	graphFile, graphErr := os.Create(shared.JoinPath(topDir, graphPath))
+	actionsFile, actionsErr := os.Create(shared.JoinPath(topDir, actionsPath))
+	if graphErr != nil || actionsErr != nil {
+		fmt.Fprintf(os.Stderr, "Graph err: %s, actions err: %s", graphErr, actionsErr)
 		os.Exit(1)
 	}
 
-	defer f.Close()
-	ctx.Context.PrintJSONGraph(f)
+	defer graphFile.Close()
+	defer actionsFile.Close()
+	ctx.Context.PrintJSONGraphAndActions(graphFile, actionsFile)
 }
 
 func writeBuildGlobsNinjaFile(srcDir, buildDir string, globs func() pathtools.MultipleGlobResults, config interface{}) []string {
@@ -254,7 +258,7 @@
 			writeDepFile(queryviewMarkerFile, ninjaDeps)
 			return queryviewMarkerFile
 		} else if generateModuleGraphFile {
-			writeJsonModuleGraph(ctx, moduleGraphFile)
+			writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
 			writeDepFile(moduleGraphFile, ninjaDeps)
 			return moduleGraphFile
 		} else if generateDocFile {
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index e3ccb6c..13b20f4 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -61,7 +61,7 @@
 }
 
 // list of supported commands (flags) supported by soong ui
-var commands []command = []command{
+var commands = []command{
 	{
 		flag:        "--make-mode",
 		description: "build the modules by the target name (i.e. soong_docs)",
@@ -523,7 +523,11 @@
 	}
 
 	// command not found
-	return nil, nil, fmt.Errorf("Command not found: %q", args)
+	flags := make([]string, len(commands))
+	for i, c := range commands {
+		flags[i] = c.flag
+	}
+	return nil, nil, fmt.Errorf("Command not found: %q\nDid you mean one of these: %q", args, flags)
 }
 
 // For Bazel support, this moves files and directories from e.g. out/dist/$f to DIST_DIR/$f if necessary.
diff --git a/docs/OWNERS b/docs/OWNERS
index d143317..2d71271 100644
--- a/docs/OWNERS
+++ b/docs/OWNERS
@@ -1 +1,3 @@
 per-file map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
+per-file native_code_coverage.md = pirama@google.com, srhines@google.com, allenhair@google.com
+per-file tidy.md = chh@google.com, srhines@google.com
diff --git a/docs/native_code_coverage.md b/docs/native_code_coverage.md
new file mode 100644
index 0000000..fabbfa0
--- /dev/null
+++ b/docs/native_code_coverage.md
@@ -0,0 +1,241 @@
+## Native Code Coverage for Android
+
+## Scope
+
+These instructions are for Android developers to collect and inspect code
+coverage for C++ and Rust code on the Android platform.
+
+## Building with Native Code Coverage Instrumentation
+
+Identify the paths where native code-coverage instrumentation should be enabled
+and set up the following environment variables.
+
+```
+    export CLANG_COVERAGE=true
+    export NATIVE_COVERAGE_PATHS="<paths-to-instrument-for-coverage>"
+```
+
+`NATIVE_COVERAGE_PATHS` should be a list of paths. Any Android.bp module defined
+under these paths is instrumented for code-coverage. E.g:
+
+```
+export NATIVE_COVERAGE_PATHS="external/libcxx system/core/adb"
+```
+
+### Additional Notes
+
+-   Native Code coverage is not supported for host modules or `Android.mk`
+    modules.
+-   `NATIVE_COVERAGE_PATHS="*"` enables coverage instrumentation for all paths.
+-   Set `native_coverage: false` blueprint property to always disable code
+    coverage instrumentation for a module. This is useful if this module has
+    issues when building or running with coverage.
+-   `NATIVE_COVERAGE_EXCLUDE_PATHS` can be set to exclude subdirs under
+    `NATIVE_COVERAGE_PATHS` from coverage instrumentation. E.g.
+    `NATIVE_COVERAGE_PATHS=frameworks/native
+    NATIVE_COVERAGE_PATHS=frameworks/native/vulkan` will instrument all native
+    code under `frameworks/native` except`frameworks/native/vulkan`.
+
+## Running Tests
+
+### Collecting Profiles
+
+When an instrumented program is run, the profiles are stored to the path and
+name specified in the `LLVM_PROFILE_FILE` environment variable. On Android
+coverage builds it is set to `/data/misc/trace/clang-%p-%20m.profraw`.
+
+*   `%`p is replaced by the pid of the process
+*   `%m` by the hash of the library/binary
+*   The `20` in`%20m` creates a pool of 20 profraw files and "online" profile
+    merging is used to merge coverage to profiles onto this pool.
+
+Reference:`LLVM_PROFILE_FILE` can include additional specifiers as described
+[here](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program).
+
+For this and following steps, use the `acov-llvm.py` script:
+`$ANDROID_BUILD_TOP/development/scripts/acov-llvm.py`.
+
+There may be profiles in `/data/misc/trace` collected before the test is run.
+Clear this data before running the test.
+
+```
+    # Clear any coverage that's already written to /data/misc/trace
+    # and reset coverage for all daemons.
+    <host>$ acov-llvm.py clean-device
+
+    # Run the test.  The exact command depends on the nature of the test.
+    <device>$ /data/local/tmp/$MY_TEST
+```
+
+For tests that exercise a daemon/service running in another process, write out
+the coverage for those processes as well.
+
+```
+    # Flush coverage of all daemons/processes running on the device.
+    <host>$ acov-llvm.py flush
+
+    # Flush coverage for a particular daemon, say adbd.
+    <host>$ acov-llvm.py flush adbd
+```
+
+## Viewing Coverage Data (acov-llvm.py)
+
+To post-process and view coverage information we use the `acov-llvm.py report`
+command. It invokes two LLVM utilities `llvm-profdata` and `llvm-cov`. An
+advanced user can manually invoke these utilities for fine-grained control. This
+is discussed [below](#viewing-coverage-data-manual).
+
+To generate coverage report need the following parameters. These are dependent
+on the test/module:
+
+1.  One or more binaries and shared libraries from which coverage was collected.
+    E.g.:
+
+    1.  ART mainline module contains a few libraries such as `libart.so`,
+        `libart-compiler.so`.
+    2.  Bionic tests exercise code in `libc.so` and `libm.so`.
+
+    We need the *unstripped* copies of these binaries. Source information
+    included in the debuginfo is used to process the coverage data.
+
+2.  One or more source directories under `$ANDROID_BUILD_TOP` for which coverage
+    needs to be reported.
+
+Invoke the report subcommand of acov-llvm.py to produce a html coverage summary:
+
+```
+    $ acov-llvm.py report \
+        -s <one-or-more-source-paths-in-$ANDROID_BUILD_TOP \
+        -b <one-or-more-(unstripped)-binaries-in-$OUT>
+```
+
+E.g.:
+
+```
+    $ acov-llvm.py report \
+        -s bionic \
+        -b \
+        $OUT/symbols/apex/com.android.runtime/lib/bionic/libc.so \
+        $OUT/symbols/apex/com.android.runtime/lib/bionic/libm.so
+```
+
+The script will produce a report in a temporary directory under
+`$ANDROID_BUILD_TOP`. It'll produce a log as below:
+
+```
+    generating coverage report in covreport-xxxxxx
+```
+
+A html report would be generated under `covreport-xxxxxx/html`.
+
+## Viewing Coverage Data (manual)
+
+`acov-llvm.py report` does a few operations under the hood which we can also
+manually invoke for flexibility.
+
+### Post-processing Coverage Files
+
+Fetch coverage files from the device and post-process them to a `.profdata` file
+as follows:
+
+```
+    # Fetch the coverage data from the device.
+    <host>$ cd coverage_data
+    <host>$ adb pull /data/misc/trace/ $TRACE_DIR_HOST
+
+    # Convert from .profraw format to the .profdata format.
+    <host>$ llvm-profdata merge --output=$MY_TEST.profdata \
+    $TRACE_DIR_HOST/clang-*.profraw
+```
+
+For added specificity, restrict the above command to just the <PID>s of the
+daemon or test processes of interest.
+
+```
+    <host>$ llvm-profdata merge --output=$MY_TEST.profdata \
+    $MY_TEST.profraw \
+    trace/clang-<pid1>.profraw trace/clang-<pid2>.profraw ...
+```
+
+### Generating Coverage report
+
+Documentation on Clang source-instrumentation-based coverage is available
+[here](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#creating-coverage-reports).
+The `llvm-cov` utility is used to show coverage from a `.profdata` file. The
+documentation for commonly used `llvm-cov` command-line arguments is available
+[here](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report). (Try
+`llvm-cov show --help` for a complete list).
+
+#### `show` subcommand
+
+The `show` command displays the function and line coverage for each source file
+in the binary.
+
+```
+    <host>$ llvm-cov show \
+        --show-region-summary=false
+        --format=html --output-dir=coverage-html \
+        --instr-profile=$MY_TEST.profdata \
+        $MY_BIN \
+```
+
+*   In the above command, `$MY_BIN` should be the unstripped binary (i.e. with
+    debuginfo) since `llvm-cov` reads some debuginfo to process the coverage
+    data.
+
+    E.g.:
+
+    ~~~
+    ```
+    <host>$ llvm-cov report \
+        --instr-profile=adbd.profdata \
+        $LOCATION_OF_UNSTRIPPED_ADBD/adbd \
+        --show-region-summary=false
+    ```
+    ~~~
+
+*   The `-ignore-filename-regex=<regex>` option can be used to ignore files that
+    are not of interest. E.g: `-ignore-filename-regex="external/*"`
+
+*   Use the `--object=<BIN>` argument to specify additional binaries and shared
+    libraries whose coverage is included in this profdata. See the earlier
+    [section](#viewing-coverage-data-acov-llvm-py) for examples where more than
+    one binary may need to be used.
+
+    E.g., the following command is used for `bionic-unit-tests`, which tests
+    both `libc.so` and `libm.so`:
+
+    ~~~
+    ```
+    <host>$ llvm-cov report \
+        --instr-profile=bionic.profdata \
+        $OUT/.../libc.so \
+        --object=$OUT/.../libm.so
+    ```
+    ~~~
+
+*   `llvm-cov` also takes positional SOURCES argument to consider/display only
+    particular paths of interest. E.g:
+
+    ~~~
+    ```
+    <host>$ llvm-cov report \
+        --instr-profile=adbd.profdata \
+        $LOCATION_OF_ADBD/adbd \
+        --show-region-summary=false \
+        /proc/self/cwd/system/core/adb
+    ```
+    ~~~
+
+Note that the paths for the sources need to be prepended with
+'`/proc/self/cwd/`'. This is because Android C/C++ compilations run with
+`PWD=/proc/self/cwd` and consequently the source names are recorded with that
+prefix. Alternatively, the
+[`--path-equivalence`](https://llvm.org/docs/CommandGuide/llvm-cov.html#cmdoption-llvm-cov-show-path-equivalence)
+option to `llvm-cov` can be used.
+
+#### `report` subcommand
+
+The [`report`](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report)
+subcommand summarizes the percentage of covered lines to the console. It takes
+options similar to the `show` subcommand.
diff --git a/docs/tidy.md b/docs/tidy.md
new file mode 100644
index 0000000..3140198
--- /dev/null
+++ b/docs/tidy.md
@@ -0,0 +1,244 @@
+# Clang-Tidy Rules and Checks
+
+Android C/C++ source files can be checked by clang-tidy for issues like
+coding style, error-prone/performance patterns, and static flow analysis.
+See the official
+[clang-tidy document](https://clang.llvm.org/extra/clang-tidy)
+and list of
+[clang-tidy checks](https://clang.llvm.org/extra/clang-tidy/checks/list.html).
+
+## Global defaults for Android builds
+
+The simplest way to enable clang-tidy checks is
+to set environment variable `WITH_TIDY`.
+```
+$ WITH_TIDY=1 make
+```
+
+This will turn on the global default to run clang-tidy for every required
+C/C++ source file compilation. The global default clang-tidy checks
+do not include time-consuming static analyzer checks. To enable those
+checks, set the `CLANG_ANALYZER_CHECKS` variable.
+```
+$ WITH_TIDY=1 CLANG_ANALYZER_CHECKS=1 make
+```
+
+The default global clang-tidy checks and flags are defined in
+[build/soong/cc/config/tidy.go](https://android.googlesource.com/platform/build/soong/+/refs/heads/master/cc/config/tidy.go).
+
+
+## Module clang-tidy properties
+
+The global default can be overwritten by module properties in Android.bp.
+
+### `tidy` and `tidy_checks`
+
+For example, in
+[system/bpf/Android.bp](https://android.googlesource.com/platform/system/bpf/+/refs/heads/master/Android.bp),
+clang-tidy is enabled explicitly and with a different check list:
+```
+cc_defaults {
+    name: "bpf_defaults",
+    // snipped
+    tidy: true,
+    tidy_checks: [
+        "android-*",
+        "cert-*",
+        "-cert-err34-c",
+        "clang-analyzer-security*",
+        // Disabling due to many unavoidable warnings from POSIX API usage.
+        "-google-runtime-int",
+    ],
+}
+```
+That means in normal builds, even without `WITH_TIDY=1`,
+the modules that use `bpf_defaults` will run clang-tidy
+over C/C++ source files with the given `tidy_checks`.
+Note that `clang-analyzer-security*` is included in `tidy_checks`
+but not all `clang-analyzer-*` checks. Check `cert-err34-c` is
+disabled, although `cert-*` is selected.
+
+Some modules might want to disable clang-tidy even when
+environment variable `WITH_TIDY=1` is set.
+Examples can be found in
+[system/netd/tests/Android.bp](https://android.googlesource.com/platform/system/netd/+/refs/heads/master/tests/Android.bp)
+```
+cc_test {
+    name: "netd_integration_test",
+    // snipped
+    defaults: ["netd_defaults"],
+    tidy: false,  // cuts test build time by almost 1 minute
+```
+and in
+[bionic/tests/Android.bp](https://android.googlesource.com/platform/bionic/+/refs/heads/master/tests/Android.bp).
+```
+cc_test_library {
+    name: "fortify_disabled_for_tidy",
+    // snipped
+    srcs: ["clang_fortify_tests.cpp"],
+    tidy: false,
+}
+```
+
+### `tidy_checks_as_errors`
+
+The global tidy checks are enabled as warnings.
+If a C/C++ module wants to be free of certain clang-tidy warnings,
+it can chose those checks to be treated as errors.
+For example
+[system/core/libsysutils/Android.bp](https://android.googlesource.com/platform/system/core/+/refs/heads/master/libsysutils/Android.bp)
+has enabled clang-tidy explicitly, selected its own tidy checks,
+and set three groups of tidy checks as errors:
+```
+cc_library {
+    name: "libsysutils",
+    // snipped
+    tidy: true,
+    tidy_checks: [
+        "-*",
+        "cert-*",
+        "clang-analyzer-security*",
+        "android-*",
+    ],
+    tidy_checks_as_errors: [
+        "cert-*",
+        "clang-analyzer-security*",
+        "android-*",
+    ],
+    // snipped
+}
+```
+
+### `tidy_flags` and `tidy_disabled_srcs`
+
+Extra clang-tidy flags can be passed with the `tidy_flags` property.
+
+Some Android modules use the `tidy_flags` to pass "-warnings-as-errors="
+to clang-tidy. This usage should now be replaced with the
+`tidy_checks_as_errors` property.
+
+Some other tidy flags examples are `-format-style=` and `-header-filter=`
+For example, in
+[art/odrefresh/Android.bp](https://android.googlesource.com/platform/art/+/refs/heads/master/odrefresh/Android.bp),
+we found
+```
+cc_defaults {
+    name: "odrefresh-defaults",
+    srcs: [
+        "odrefresh.cc",
+        "odr_common.cc",
+        "odr_compilation_log.cc",
+        "odr_fs_utils.cc",
+        "odr_metrics.cc",
+        "odr_metrics_record.cc",
+    ],
+    // snipped
+    generated_sources: [
+        "apex-info-list-tinyxml",
+        "art-apex-cache-info",
+        "art-odrefresh-operator-srcs",
+    ],
+    // snipped
+    tidy: true,
+    tidy_disabled_srcs: [":art-apex-cache-info"],
+    tidy_flags: [
+        "-format-style=file",
+        "-header-filter=(art/odrefresh/|system/apex/)",
+    ],
+}
+```
+That means all modules with the `odrefresh-defaults` will
+have clang-tidy enabled, but not for generated source
+files in `art-apex-cache-info`.
+The clang-tidy is called with extra flags to specify the
+format-style and header-filter.
+
+Note that the globally set default for header-filter is to
+include only the module directory. So, the default clang-tidy
+warnings for `art/odrefresh` modules will include source files
+under that directory. Now `odrefresh-defaults` is interested
+in seeing warnings from both `art/odrefresh/` and `system/apex/`
+and it redefines `-header-filter` in its `tidy_flags`.
+
+
+## Phony tidy-* targets
+
+### The tidy-*directory* targets
+
+Setting `WITH_TIDY=1` is easy to enable clang-tidy globally for any build.
+However, it adds extra compilation time.
+
+For developers focusing on just one directory, they only want to compile
+their files with clang-tidy and wish to build other Android components as
+fast as possible. Changing the `WITH_TIDY=1` variable setting is also expensive
+since the build.ninja file will be regenerated due to any such variable change.
+
+To manually select only some directories or modules to compile with clang-tidy,
+do not set the `WITH_TIDY=1` variable, but use the special `tidy-<directory>`
+phony target. For example, a person working on `system/libbase` can build
+Android quickly with
+```
+unset WITH_TIDY # Optional, not if you haven't set WITH_TIDY
+make droid tidy-system-libbase
+```
+
+For any directory `d1/d2/d3`, a phony target tidy-d1-d2-d3 is generated
+if there is any C/C++ source file under `d1/d2/d3`.
+
+Note that with `make droid tidy-system-libbase`, some C/C++ files
+that are not needed by the `droid` target will be passed to clang-tidy
+if they are under `system/libbase`. This is like a `checkbuild`
+under `system/libbase` to include all modules, but only C/C++
+files of those modules are compiled with clang-tidy.
+
+### The tidy-soong target
+
+A special `tidy-soong` target is defined to include all C/C++
+source files in *all* directories. This phony target is sometimes
+used to test if all source files compile with a new clang-tidy release.
+
+### The tidy-*_subset targets
+
+A *subset* of each tidy-* phony target is defined to reduce test time.
+Since any Android module, a C/C++ library or binary, can be built
+for many different *variants*, one C/C++ source file is usually
+compiled multiple times with different compilation flags.
+Many of such *variant* flags have little or no effect on clang-tidy
+checks. To reduce clang-tidy check time, a *subset* target like
+`tidy-soong_subset` or `tidy-system-libbase_subset` is generated
+to include only a subset, the first variant, of each module in
+the directory.
+
+Hence, for C/C++ source code quality, instead of a long
+"make checkbuild", we can use "make tidy-soong_subset".
+
+
+## Limit clang-tidy runtime
+
+Some Android modules have large files that take a long time to compile
+with clang-tidy, with or without the clang-analyzer checks.
+To limit clang-tidy time, an environment variable can be set as
+```base
+WITH_TIDY=1 TIDY_TIMEOUT=90 make
+```
+This 90-second limit is actually the default time limit
+in several Android continuous builds where `WITH_TIDY=1` and
+`CLANG_ANALYZER_CHECKS=1` are set.
+
+## Capabilities for Android.bp and Android.mk
+
+Some of the previously mentioned features are defined only
+for modules in Android.bp files, not for Android.mk modules yet.
+
+* The global `WITH_TIDY=1` variable will enable clang-tidy for all C/C++
+  modules in Android.bp or Android.mk files.
+
+* The global `TIDY_TIMEOUT` variable is recognized by Android prebuilt
+  clang-tidy, so it should work for any clang-tidy invocation.
+
+* The clang-tidy module level properties are defined for Android.bp modules.
+  For Android.mk modules, old `LOCAL_TIDY`, `LOCAL_TIDY_CHECKS`,
+  `LOCAL_TIDY_FLAGS` work similarly, but it would be better to convert
+  those modules to use Android.bp files.
+
+* The `tidy-*` phony targets are only generated for Android.bp modules.
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index fee51d7..4794180 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -669,6 +669,8 @@
 	// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
 	if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
 		jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
+	} else if android.InList("AddNewActivity", possibleUpdatableModules) {
+		jars = jars.Append("test_com.android.cts.frameworkresapkplits", "AddNewActivity")
 	} else if android.InList("test_framework-apexd", possibleUpdatableModules) {
 		jars = jars.Append("com.android.apex.test_package", "test_framework-apexd")
 	} else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
diff --git a/java/config/config.go b/java/config/config.go
index 30c6f91..ea2f934 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -60,7 +60,7 @@
 
 const (
 	JavaVmFlags  = `-XX:OnError="cat hs_err_pid%p.log" -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads`
-	JavacVmFlags = `-J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads`
+	JavacVmFlags = `-J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1`
 )
 
 func init() {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 5a84e05..7ad316f 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -19,7 +19,6 @@
 	"path/filepath"
 	"strings"
 
-	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
@@ -807,8 +806,7 @@
 
 	properties PrebuiltStubsSourcesProperties
 
-	stubsSrcJar     android.Path
-	jsonDataActions []blueprint.JSONDataAction
+	stubsSrcJar android.Path
 }
 
 func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
@@ -824,13 +822,6 @@
 	return d.stubsSrcJar
 }
 
-// AddJSONData is a temporary solution for droidstubs module to put action
-// related data into the module json graph.
-func (p *PrebuiltStubsSources) AddJSONData(d *map[string]interface{}) {
-	p.ModuleBase.AddJSONData(d)
-	(*d)["Actions"] = blueprint.FormatJSONDataActions(p.jsonDataActions)
-}
-
 func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	if len(p.properties.Srcs) != 1 {
 		ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs))
@@ -838,12 +829,9 @@
 	}
 
 	src := p.properties.Srcs[0]
-	var jsonDataAction blueprint.JSONDataAction
 	if filepath.Ext(src) == ".srcjar" {
 		// This is a srcjar. We can use it directly.
 		p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
-		jsonDataAction.Inputs = []string{src}
-		jsonDataAction.Outputs = []string{src}
 	} else {
 		outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
 
@@ -867,10 +855,7 @@
 		rule.Restat()
 		rule.Build("zip src", "Create srcjar from prebuilt source")
 		p.stubsSrcJar = outPath
-		jsonDataAction.Inputs = srcPaths.Strings()
-		jsonDataAction.Outputs = []string{outPath.String()}
 	}
-	p.jsonDataActions = []blueprint.JSONDataAction{jsonDataAction}
 }
 
 func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 82ebba7..10d99f3 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -21,8 +21,6 @@
 	"strings"
 	"testing"
 
-	"github.com/google/blueprint"
-
 	"android/soong/android"
 )
 
@@ -234,27 +232,6 @@
 	checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar")
 }
 
-func TestAddJSONData(t *testing.T) {
-	prebuiltStubsSources := PrebuiltStubsSources{}
-	prebuiltStubsSources.jsonDataActions = []blueprint.JSONDataAction{
-		blueprint.JSONDataAction{
-			Inputs:  []string{},
-			Outputs: []string{},
-		},
-	}
-	jsonData := map[string]interface{}{}
-	prebuiltStubsSources.AddJSONData(&jsonData)
-	expectedOut := []map[string]interface{}{
-		map[string]interface{}{
-			"Inputs":  []string{},
-			"Outputs": []string{},
-		},
-	}
-	if !reflect.DeepEqual(jsonData["Actions"], expectedOut) {
-		t.Errorf("The JSON action data %#v isn't as expected %#v.", jsonData["Actions"], expectedOut)
-	}
-}
-
 func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
 	metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
 	var systemJars []string
diff --git a/java/java.go b/java/java.go
index e3e9721..ca4b3cf 100644
--- a/java/java.go
+++ b/java/java.go
@@ -325,6 +325,7 @@
 
 var (
 	dataNativeBinsTag       = dependencyTag{name: "dataNativeBins"}
+	dataDeviceBinsTag       = dependencyTag{name: "dataDeviceBins"}
 	staticLibTag            = dependencyTag{name: "staticlib"}
 	libTag                  = dependencyTag{name: "javalib", runtimeLinked: true}
 	java9LibTag             = dependencyTag{name: "java9lib", runtimeLinked: true}
@@ -831,6 +832,9 @@
 type hostTestProperties struct {
 	// list of native binary modules that should be installed alongside the test
 	Data_native_bins []string `android:"arch_variant"`
+
+	// list of device binary modules that should be installed alongside the test
+	Data_device_bins []string `android:"arch_variant"`
 }
 
 type testHelperLibraryProperties struct {
@@ -904,6 +908,11 @@
 		}
 	}
 
+	if len(j.testHostProperties.Data_device_bins) > 0 {
+		deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
+		ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins...)
+	}
+
 	if len(j.testProperties.Jni_libs) > 0 {
 		for _, target := range ctx.MultiTargets() {
 			sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
@@ -918,14 +927,35 @@
 	j.extraResources = append(j.extraResources, p)
 }
 
+func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	var configs []tradefed.Config
+	if len(j.testHostProperties.Data_device_bins) > 0 {
+		// add Tradefed configuration to push device bins to device for testing
+		remoteDir := filepath.Join("/data/local/tests/unrestricted/", j.Name())
+		options := []tradefed.Option{{Name: "cleanup", Value: "true"}}
+		for _, bin := range j.testHostProperties.Data_device_bins {
+			fullPath := filepath.Join(remoteDir, bin)
+			options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: fullPath})
+		}
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options})
+	}
+
+	j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
+}
+
 func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	j.generateAndroidBuildActionsWithConfig(ctx, nil)
+}
+
+func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
 	if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
 		// TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
 		defaultUnitTest := !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
 		j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
 	}
+
 	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
-		j.testProperties.Test_suites, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
+		j.testProperties.Test_suites, configs, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
 
 	j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
 
@@ -935,6 +965,10 @@
 		j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
 	})
 
+	ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) {
+		j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
+	})
+
 	ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
 		sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
 		if sharedLibInfo.SharedLibrary != nil {
@@ -967,7 +1001,7 @@
 
 func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
-		j.prebuiltTestProperties.Test_suites, nil, nil)
+		j.prebuiltTestProperties.Test_suites, nil, nil, nil)
 
 	j.Import.GenerateAndroidBuildActions(ctx)
 }
@@ -1294,6 +1328,7 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 	android.ApexModuleBase
+	android.BazelModuleBase
 	prebuilt android.Prebuilt
 	android.SdkBase
 
@@ -1649,6 +1684,7 @@
 	android.InitPrebuiltModule(module, &module.properties.Jars)
 	android.InitApexModule(module)
 	android.InitSdkAwareModule(module)
+	android.InitBazelModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 	return module
 }
@@ -2067,3 +2103,21 @@
 	// Create the BazelTargetModule.
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
 }
+
+type bazelJavaImportAttributes struct {
+	Jars bazel.LabelListAttribute
+}
+
+// java_import bp2Build converter.
+func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	//TODO(b/209577426): Support multiple arch variants
+	jars := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, i.properties.Jars, []string(nil)))
+
+	attrs := &bazelJavaImportAttributes{
+		Jars: jars,
+	}
+	props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs)
+
+}
diff --git a/java/java_test.go b/java/java_test.go
index 3a51981..21c76b6 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1460,3 +1460,64 @@
 		t.Errorf("expected errorprone to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
 	}
 }
+
+func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
+	bp := `
+		java_test_host {
+			name: "foo",
+			srcs: ["test.java"],
+			data_device_bins: ["bar"],
+		}
+
+		cc_binary {
+			name: "bar",
+		}
+	`
+
+	ctx := android.GroupFixturePreparers(
+		PrepareForIntegrationTestWithJava,
+	).RunTestWithBp(t, bp)
+
+	buildOS := ctx.Config.BuildOS.String()
+	fooVariant := ctx.ModuleForTests("foo", buildOS+"_common")
+	barVariant := ctx.ModuleForTests("bar", "android_arm64_armv8-a")
+	fooMod := fooVariant.Module().(*TestHost)
+
+	relocated := barVariant.Output("bar")
+	expectedInput := "out/soong/.intermediates/bar/android_arm64_armv8-a/unstripped/bar"
+	android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
+
+	entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
+	expectedData := []string{
+		"out/soong/.intermediates/bar/android_arm64_armv8-a/bar:bar",
+	}
+	actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
+	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData)
+}
+
+func TestDataDeviceBinsAutogenTradefedConfig(t *testing.T) {
+	bp := `
+		java_test_host {
+			name: "foo",
+			srcs: ["test.java"],
+			data_device_bins: ["bar"],
+		}
+
+		cc_binary {
+			name: "bar",
+		}
+	`
+
+	ctx := android.GroupFixturePreparers(
+		PrepareForIntegrationTestWithJava,
+	).RunTestWithBp(t, bp)
+
+	buildOS := ctx.Config.BuildOS.String()
+	fooModule := ctx.ModuleForTests("foo", buildOS+"_common")
+	expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
+
+	autogen := fooModule.Rule("autogen")
+	if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) {
+		t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig)
+	}
+}
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 5b764dc..8db001f 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -18,6 +18,11 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+filegroup {
+    name: "Apache-2.0-License-Text",
+    srcs: ["LICENSE"],
+}
+
 license {
     name: "Android-Apache-2.0",
     package_name: "Android",
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index d62882d..c4f7da3 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -1048,8 +1048,8 @@
   cfg = rblf.cfg(handle)
   g["MY_PATH"] = "foo"
   _entry = {
-    "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
-    "vendor/bar/baz/cfg.mk": ("_cfg1", _cfg1_init),
+    "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
+    "vendor/bar/baz/cfg.mk": ("vendor/bar/baz/cfg", _cfg1_init),
   }.get("vendor/%s/cfg.mk" % g["MY_PATH"])
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
@@ -1073,7 +1073,7 @@
   g["MY_PATH"] = "foo"
   #RBC# include_top vendor/foo1
   _entry = {
-    "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+    "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
   }.get("%s/cfg.mk" % g["MY_PATH"])
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
@@ -1099,7 +1099,7 @@
   g["MY_PATH"] = "foo"
   #RBC# include_top vendor/foo1
   _entry = {
-    "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+    "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
   }.get("%s/cfg.mk" % g["MY_PATH"])
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
@@ -1107,7 +1107,7 @@
   rblf.inherit(handle, _varmod, _varmod_init)
   #RBC# include_top vendor/foo1
   _entry = {
-    "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+    "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
   }.get("%s/cfg.mk" % g["MY_PATH"])
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
@@ -1137,7 +1137,7 @@
 def init(g, handle):
   cfg = rblf.cfg(handle)
   _entry = {
-    "foo/font.mk": ("_font", _font_init),
+    "foo/font.mk": ("foo/font", _font_init),
   }.get("%s/font.mk" % g.get("MY_VAR", ""))
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
@@ -1146,7 +1146,7 @@
   #RBC# include_top foo
   # There's some space and even this comment between the include_top and the inherit-product
   _entry = {
-    "foo/font.mk": ("_font", _font_init),
+    "foo/font.mk": ("foo/font", _font_init),
   }.get("%s/font.mk" % g.get("MY_VAR", ""))
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
diff --git a/mk2rbc/node.go b/mk2rbc/node.go
index 333a8da..4f7c4f0 100644
--- a/mk2rbc/node.go
+++ b/mk2rbc/node.go
@@ -54,6 +54,10 @@
 	return im.moduleLocalName + "_init"
 }
 
+func (mi moduleInfo) name() string {
+	return fmt.Sprintf("%q", MakePath2ModuleName(mi.originalPath))
+}
+
 type inheritedModule interface {
 	name() string
 	entryName() string
@@ -67,10 +71,6 @@
 	loadAlways bool
 }
 
-func (im inheritedStaticModule) name() string {
-	return fmt.Sprintf("%q", MakePath2ModuleName(im.originalPath))
-}
-
 func (im inheritedStaticModule) emitSelect(_ *generationContext) {
 }
 
@@ -102,7 +102,7 @@
 	gctx.indentLevel++
 	for _, mi := range i.candidateModules {
 		gctx.newLine()
-		gctx.writef(`"%s": (%q, %s),`, mi.originalPath, mi.moduleLocalName, mi.entryName())
+		gctx.writef(`"%s": (%s, %s),`, mi.originalPath, mi.name(), mi.entryName())
 	}
 	gctx.indentLevel--
 	gctx.newLine()
diff --git a/rust/binary.go b/rust/binary.go
index db91ccb..0dc320e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -92,14 +92,23 @@
 func (binary *binaryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps = binary.baseCompiler.compilerDeps(ctx, deps)
 
+	static := Bool(binary.Properties.Static_executable)
 	if ctx.toolchain().Bionic() {
-		deps = bionicDeps(ctx, deps, Bool(binary.Properties.Static_executable))
-		if Bool(binary.Properties.Static_executable) {
-			deps.CrtBegin = "crtbegin_static"
+		deps = bionicDeps(ctx, deps, static)
+		if static {
+			deps.CrtBegin = []string{"crtbegin_static"}
 		} else {
-			deps.CrtBegin = "crtbegin_dynamic"
+			deps.CrtBegin = []string{"crtbegin_dynamic"}
 		}
-		deps.CrtEnd = "crtend_android"
+		deps.CrtEnd = []string{"crtend_android"}
+	} else if ctx.Os() == android.LinuxMusl {
+		deps = muslDeps(ctx, deps, static)
+		if static {
+			deps.CrtBegin = []string{"libc_musl_crtbegin_static"}
+		} else {
+			deps.CrtBegin = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}
+		}
+		deps.CrtEnd = []string{"libc_musl_crtend"}
 	}
 
 	return deps
diff --git a/rust/bindgen.go b/rust/bindgen.go
index ef5702b..f4c337d 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -288,6 +288,8 @@
 	deps = b.BaseSourceProvider.SourceProviderDeps(ctx, deps)
 	if ctx.toolchain().Bionic() {
 		deps = bionicDeps(ctx, deps, false)
+	} else if ctx.Os() == android.LinuxMusl {
+		deps = muslDeps(ctx, deps, false)
 	}
 
 	deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
diff --git a/rust/builder.go b/rust/builder.go
index e66a6f0..00035b9 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -247,9 +247,8 @@
 	implicits = append(implicits, deps.srcProviderFiles...)
 	implicits = append(implicits, deps.AfdoProfiles...)
 
-	if deps.CrtBegin.Valid() {
-		implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
-	}
+	implicits = append(implicits, deps.CrtBegin...)
+	implicits = append(implicits, deps.CrtEnd...)
 
 	if len(deps.SrcDeps) > 0 {
 		moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
@@ -319,8 +318,8 @@
 			"rustcFlags": strings.Join(rustcFlags, " "),
 			"linkFlags":  strings.Join(linkFlags, " "),
 			"libFlags":   strings.Join(libFlags, " "),
-			"crtBegin":   deps.CrtBegin.String(),
-			"crtEnd":     deps.CrtEnd.String(),
+			"crtBegin":   strings.Join(deps.CrtBegin.Strings(), " "),
+			"crtEnd":     strings.Join(deps.CrtEnd.Strings(), " "),
 			"envVars":    strings.Join(envVars, " "),
 		},
 	})
diff --git a/rust/compiler.go b/rust/compiler.go
index 3040e5d..c5d40f4 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -364,7 +364,7 @@
 	if !Bool(compiler.Properties.No_stdlibs) {
 		for _, stdlib := range config.Stdlibs {
 			// If we're building for the build host, use the prebuilt stdlibs
-			if ctx.Target().Os == ctx.Config().BuildOS {
+			if ctx.Target().Os == android.Linux || ctx.Target().Os == android.Darwin {
 				stdlib = "prebuilt_" + stdlib
 			}
 			deps.Stdlibs = append(deps.Stdlibs, stdlib)
@@ -394,6 +394,20 @@
 	return deps
 }
 
+func muslDeps(ctx DepsContext, deps Deps, static bool) Deps {
+	muslLibs := []string{"libc_musl"}
+	if static {
+		deps.StaticLibs = append(deps.StaticLibs, muslLibs...)
+	} else {
+		deps.SharedLibs = append(deps.SharedLibs, muslLibs...)
+	}
+	if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" {
+		deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins)
+	}
+
+	return deps
+}
+
 func (compiler *baseCompiler) crateName() string {
 	return compiler.Properties.Crate_name
 }
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index f318507..0962168 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -19,6 +19,7 @@
 		"frameworks/native/libs/binder/rust",
 		"frameworks/proto_logging/stats",
 		"hardware/interfaces/security",
+		"hardware/interfaces/uwb",
 		"packages/modules/Bluetooth",
 		"packages/modules/DnsResolver",
 		"packages/modules/Uwb",
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index c10afd8..7608349 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -22,12 +22,29 @@
 
 var (
 	LinuxRustFlags     = []string{}
+	LinuxMuslRustFlags = []string{
+		// disable rustc's builtin fallbacks for crt objects
+		"-C link_self_contained=no",
+		// force rustc to use a dynamic musl libc
+		"-C target-feature=-crt-static",
+		"-Z link-native-libraries=no",
+	}
 	LinuxRustLinkFlags = []string{
 		"-B${cc_config.ClangBin}",
 		"-fuse-ld=lld",
 		"-Wl,--undefined-version",
+	}
+	LinuxRustGlibcLinkFlags = []string{
 		"--sysroot ${cc_config.LinuxGccRoot}/sysroot",
 	}
+	LinuxRustMuslLinkFlags = []string{
+		"--sysroot /dev/null",
+		"-nodefaultlibs",
+		"-nostdlib",
+		"-Wl,--no-dynamic-linker",
+		// for unwind
+		"-lgcc", "-lgcc_eh",
+	}
 	linuxX86Rustflags   = []string{}
 	linuxX86Linkflags   = []string{}
 	linuxX8664Rustflags = []string{}
@@ -35,15 +52,17 @@
 )
 
 func init() {
-	registerToolchainFactory(android.Linux, android.X86_64, linuxX8664ToolchainFactory)
-	registerToolchainFactory(android.Linux, android.X86, linuxX86ToolchainFactory)
+	registerToolchainFactory(android.Linux, android.X86_64, linuxGlibcX8664ToolchainFactory)
+	registerToolchainFactory(android.Linux, android.X86, linuxGlibcX86ToolchainFactory)
 
-	// TODO: musl rust support
-	registerToolchainFactory(android.LinuxMusl, android.X86_64, linuxX8664ToolchainFactory)
-	registerToolchainFactory(android.LinuxMusl, android.X86, linuxX86ToolchainFactory)
+	registerToolchainFactory(android.LinuxMusl, android.X86_64, linuxMuslX8664ToolchainFactory)
+	registerToolchainFactory(android.LinuxMusl, android.X86, linuxMuslX86ToolchainFactory)
 
 	pctx.StaticVariable("LinuxToolchainRustFlags", strings.Join(LinuxRustFlags, " "))
+	pctx.StaticVariable("LinuxMuslToolchainRustFlags", strings.Join(LinuxMuslRustFlags, " "))
 	pctx.StaticVariable("LinuxToolchainLinkFlags", strings.Join(LinuxRustLinkFlags, " "))
+	pctx.StaticVariable("LinuxGlibcToolchainLinkFlags", strings.Join(LinuxRustGlibcLinkFlags, " "))
+	pctx.StaticVariable("LinuxMuslToolchainLinkFlags", strings.Join(LinuxRustMuslLinkFlags, " "))
 	pctx.StaticVariable("LinuxToolchainX86RustFlags", strings.Join(linuxX86Rustflags, " "))
 	pctx.StaticVariable("LinuxToolchainX86LinkFlags", strings.Join(linuxX86Linkflags, " "))
 	pctx.StaticVariable("LinuxToolchainX8664RustFlags", strings.Join(linuxX8664Rustflags, " "))
@@ -51,19 +70,9 @@
 
 }
 
-type toolchainLinux struct {
-	toolchainRustFlags string
-	toolchainLinkFlags string
-}
-
-type toolchainLinuxX86 struct {
-	toolchain32Bit
-	toolchainLinux
-}
-
+// Base 64-bit linux rust toolchain
 type toolchainLinuxX8664 struct {
 	toolchain64Bit
-	toolchainLinux
 }
 
 func (toolchainLinuxX8664) Supported() bool {
@@ -78,10 +87,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainLinuxX8664) RustTriple() string {
-	return "x86_64-unknown-linux-gnu"
-}
-
 func (t *toolchainLinuxX8664) ToolchainLinkFlags() string {
 	// Prepend the lld flags from cc_config so we stay in sync with cc
 	return "${cc_config.LinuxLldflags} ${cc_config.LinuxX8664Lldflags} " +
@@ -92,8 +97,49 @@
 	return "${config.LinuxToolchainRustFlags} ${config.LinuxToolchainX8664RustFlags}"
 }
 
-func linuxX8664ToolchainFactory(arch android.Arch) Toolchain {
-	return toolchainLinuxX8664Singleton
+// Specialization of the 64-bit linux rust toolchain for glibc.  Adds the gnu rust triple and
+// sysroot linker flags.
+type toolchainLinuxGlibcX8664 struct {
+	toolchainLinuxX8664
+}
+
+func (t *toolchainLinuxX8664) RustTriple() string {
+	return "x86_64-unknown-linux-gnu"
+}
+
+func (t *toolchainLinuxGlibcX8664) ToolchainLinkFlags() string {
+	return t.toolchainLinuxX8664.ToolchainLinkFlags() + " " + "${config.LinuxGlibcToolchainLinkFlags}"
+}
+
+func linuxGlibcX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxGlibcX8664Singleton
+}
+
+// Specialization of the 64-bit linux rust toolchain for musl.  Adds the musl rust triple and
+// linker flags to avoid using the host sysroot.
+type toolchainLinuxMuslX8664 struct {
+	toolchainLinuxX8664
+}
+
+func (t *toolchainLinuxMuslX8664) RustTriple() string {
+	return "x86_64-unknown-linux-musl"
+}
+
+func (t *toolchainLinuxMuslX8664) ToolchainLinkFlags() string {
+	return t.toolchainLinuxX8664.ToolchainLinkFlags() + " " + "${config.LinuxMuslToolchainLinkFlags}"
+}
+
+func (t *toolchainLinuxMuslX8664) ToolchainRustFlags() string {
+	return t.toolchainLinuxX8664.ToolchainRustFlags() + " " + "${config.LinuxMuslToolchainRustFlags}"
+}
+
+func linuxMuslX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxMuslX8664Singleton
+}
+
+// Base 32-bit linux rust toolchain
+type toolchainLinuxX86 struct {
+	toolchain32Bit
 }
 
 func (toolchainLinuxX86) Supported() bool {
@@ -116,10 +162,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainLinuxX86) RustTriple() string {
-	return "i686-unknown-linux-gnu"
-}
-
 func (t *toolchainLinuxX86) ToolchainLinkFlags() string {
 	// Prepend the lld flags from cc_config so we stay in sync with cc
 	return "${cc_config.LinuxLldflags} ${cc_config.LinuxX86Lldflags} " +
@@ -130,9 +172,47 @@
 	return "${config.LinuxToolchainRustFlags} ${config.LinuxToolchainX86RustFlags}"
 }
 
-func linuxX86ToolchainFactory(arch android.Arch) Toolchain {
-	return toolchainLinuxX86Singleton
+// Specialization of the 32-bit linux rust toolchain for glibc.  Adds the gnu rust triple and
+// sysroot linker flags.
+type toolchainLinuxGlibcX86 struct {
+	toolchainLinuxX86
 }
 
-var toolchainLinuxX8664Singleton Toolchain = &toolchainLinuxX8664{}
-var toolchainLinuxX86Singleton Toolchain = &toolchainLinuxX86{}
+func (t *toolchainLinuxGlibcX86) RustTriple() string {
+	return "i686-unknown-linux-gnu"
+}
+
+func (t *toolchainLinuxGlibcX86) ToolchainLinkFlags() string {
+	return t.toolchainLinuxX86.ToolchainLinkFlags() + " " + "${config.LinuxGlibcToolchainLinkFlags}"
+}
+
+func linuxGlibcX86ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxGlibcX86Singleton
+}
+
+// Specialization of the 32-bit linux rust toolchain for musl.  Adds the musl rust triple and
+// linker flags to avoid using the host sysroot.
+type toolchainLinuxMuslX86 struct {
+	toolchainLinuxX86
+}
+
+func (t *toolchainLinuxMuslX86) RustTriple() string {
+	return "i686-unknown-linux-musl"
+}
+
+func (t *toolchainLinuxMuslX86) ToolchainLinkFlags() string {
+	return t.toolchainLinuxX86.ToolchainLinkFlags() + " " + "${config.LinuxMuslToolchainLinkFlags}"
+}
+
+func (t *toolchainLinuxMuslX86) ToolchainRustFlags() string {
+	return t.toolchainLinuxX86.ToolchainRustFlags() + " " + "${config.LinuxMuslToolchainRustFlags}"
+}
+
+func linuxMuslX86ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxMuslX86Singleton
+}
+
+var toolchainLinuxGlibcX8664Singleton Toolchain = &toolchainLinuxGlibcX8664{}
+var toolchainLinuxGlibcX86Singleton Toolchain = &toolchainLinuxGlibcX86{}
+var toolchainLinuxMuslX8664Singleton Toolchain = &toolchainLinuxMuslX8664{}
+var toolchainLinuxMuslX86Singleton Toolchain = &toolchainLinuxMuslX86{}
diff --git a/rust/coverage.go b/rust/coverage.go
index 8fdfa23..050b811 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -57,18 +57,7 @@
 		flags.RustFlags = append(flags.RustFlags,
 			"-Z instrument-coverage", "-g")
 		flags.LinkFlags = append(flags.LinkFlags,
-			profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open",
-			// Upstream LLVM change 6d2d3bd0a6 made
-			// -z,start-stop-gc the default.  It drops metadata
-			// sections like __llvm_prf_data unless they are marked
-			// SHF_GNU_RETAIN.  https://reviews.llvm.org/D97448
-			// marks generated sections, including __llvm_prf_data
-			// as SHF_GNU_RETAIN.  However this change is not in
-			// the Rust toolchain.  Since we link Rust libs with
-			// new lld, we should use nostart-stop-gc until the
-			// Rust toolchain updates past D97448.
-			"-Wl,-z,nostart-stop-gc",
-		)
+			profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
 		deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
 	}
 
diff --git a/rust/library.go b/rust/library.go
index bb2e83f..baac3f0 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -426,10 +426,16 @@
 func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps = library.baseCompiler.compilerDeps(ctx, deps)
 
-	if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
-		deps = bionicDeps(ctx, deps, false)
-		deps.CrtBegin = "crtbegin_so"
-		deps.CrtEnd = "crtend_so"
+	if library.dylib() || library.shared() {
+		if ctx.toolchain().Bionic() {
+			deps = bionicDeps(ctx, deps, false)
+			deps.CrtBegin = []string{"crtbegin_so"}
+			deps.CrtEnd = []string{"crtend_so"}
+		} else if ctx.Os() == android.LinuxMusl {
+			deps = muslDeps(ctx, deps, false)
+			deps.CrtBegin = []string{"libc_musl_crtbegin_so"}
+			deps.CrtEnd = []string{"libc_musl_crtend_so"}
+		}
 	}
 
 	return deps
diff --git a/rust/rust.go b/rust/rust.go
index 0f7b768..018d1dd 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -394,7 +394,7 @@
 	DataLibs []string
 	DataBins []string
 
-	CrtBegin, CrtEnd string
+	CrtBegin, CrtEnd []string
 }
 
 type PathDeps struct {
@@ -421,8 +421,8 @@
 	depGeneratedHeaders   android.Paths
 	depSystemIncludePaths android.Paths
 
-	CrtBegin android.OptionalPath
-	CrtEnd   android.OptionalPath
+	CrtBegin android.Paths
+	CrtEnd   android.Paths
 
 	// Paths to generated source files
 	SrcDeps          android.Paths
@@ -1224,9 +1224,9 @@
 				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
 				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
 			case depTag == cc.CrtBeginDepTag:
-				depPaths.CrtBegin = linkObject
+				depPaths.CrtBegin = append(depPaths.CrtBegin, linkObject.Path())
 			case depTag == cc.CrtEndDepTag:
-				depPaths.CrtEnd = linkObject
+				depPaths.CrtEnd = append(depPaths.CrtEnd, linkObject.Path())
 			}
 
 			// Make sure these dependencies are propagated
@@ -1234,6 +1234,13 @@
 				lib.exportLinkDirs(linkPath)
 				lib.exportLinkObjects(linkObject.String())
 			}
+		} else {
+			switch {
+			case depTag == cc.CrtBeginDepTag:
+				depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, ""))
+			case depTag == cc.CrtEndDepTag:
+				depPaths.CrtEnd = append(depPaths.CrtEnd, android.OutputFileForModule(ctx, dep, ""))
+			}
 		}
 
 		if srcDep, ok := dep.(android.SourceFileProducer); ok {
@@ -1432,13 +1439,13 @@
 	actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)
 
 	crtVariations := cc.GetCrtVariations(ctx, mod)
-	if deps.CrtBegin != "" {
+	for _, crt := range deps.CrtBegin {
 		actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag,
-			cc.RewriteSnapshotLib(deps.CrtBegin, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
+			cc.RewriteSnapshotLib(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
 	}
-	if deps.CrtEnd != "" {
+	for _, crt := range deps.CrtEnd {
 		actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag,
-			cc.RewriteSnapshotLib(deps.CrtEnd, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
+			cc.RewriteSnapshotLib(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
 	}
 
 	if mod.sourceProvider != nil {
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 28b6fb9..7fe1d85 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -4,6 +4,7 @@
 	"os"
 	"path/filepath"
 	"strconv"
+	"strings"
 	"testing"
 
 	"android/soong/android"
@@ -215,3 +216,40 @@
 	actualData := entries.EntryMap["LOCAL_TEST_DATA"]
 	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData)
 }
+
+func TestShTestHost_dataDeviceModulesAutogenTradefedConfig(t *testing.T) {
+	ctx, config := testShBinary(t, `
+		sh_test_host {
+			name: "foo",
+			src: "test.sh",
+			data_device_bins: ["bar"],
+			data_device_libs: ["libbar"],
+		}
+
+		cc_binary {
+			name: "bar",
+			shared_libs: ["libbar"],
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "libbar",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	buildOS := config.BuildOS.String()
+	fooModule := ctx.ModuleForTests("foo", buildOS+"_x86_64")
+
+	expectedBinAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
+	autogen := fooModule.Rule("autogen")
+	if !strings.Contains(autogen.Args["extraConfigs"], expectedBinAutogenConfig) {
+		t.Errorf("foo extraConfings %v does not contain %q", autogen.Args["extraConfigs"], expectedBinAutogenConfig)
+	}
+}
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index da55829..c2429ab 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -188,20 +188,20 @@
 }
 
 func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
-	testSuites []string, autoGenConfig *bool, unitTest *bool) android.Path {
+	testSuites []string, config []Config, autoGenConfig *bool, unitTest *bool) android.Path {
 	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), nil, "")
+			autogenTemplate(ctx, autogenPath, templatePath.String(), config, "")
 		} else {
 			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", nil, "")
+				autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", config, "")
 			} else {
 				if Bool(unitTest) {
-					autogenTemplate(ctx, autogenPath, "${JavaHostUnitTestConfigTemplate}", nil, "")
+					autogenTemplate(ctx, autogenPath, "${JavaHostUnitTestConfigTemplate}", config, "")
 				} else {
-					autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", nil, "")
+					autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", config, "")
 				}
 			}
 		}
diff --git a/ui/build/config.go b/ui/build/config.go
index a731932..d1714a4 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -868,6 +868,10 @@
 	return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
 }
 
+func (c *configImpl) ModuleActionsFile() string {
+	return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
+}
+
 func (c *configImpl) TempDir() string {
 	return shared.TempDirForOutDir(c.SoongOutDir())
 }
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 8133762..117a2a5 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -284,6 +284,7 @@
 		config.ModuleGraphFile(),
 		[]string{
 			"--module_graph_file", config.ModuleGraphFile(),
+			"--module_actions_file", config.ModuleActionsFile(),
 		},
 		fmt.Sprintf("generating the Soong module graph at %s", config.ModuleGraphFile()),
 	)