Merge "Drop rust dependency on musl_linker_script"
diff --git a/OWNERS b/OWNERS
index 730db7a..e18eea1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -14,6 +14,7 @@
 eakammer@google.com
 jobredeaux@google.com
 joeo@google.com
+juu@google.com
 lamontjones@google.com
 spandandas@google.com
 tradical@google.com
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 0080067..9bba3c3 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -133,6 +133,7 @@
 		"external/jemalloc_new":                  Bp2BuildDefaultTrueRecursively,
 		"external/jsoncpp":                       Bp2BuildDefaultTrueRecursively,
 		"external/junit":                         Bp2BuildDefaultTrueRecursively,
+		"external/libaom":                        Bp2BuildDefaultTrueRecursively,
 		"external/libavc":                        Bp2BuildDefaultTrueRecursively,
 		"external/libcap":                        Bp2BuildDefaultTrueRecursively,
 		"external/libcxx":                        Bp2BuildDefaultTrueRecursively,
@@ -167,6 +168,7 @@
 
 		"frameworks/av":                                      Bp2BuildDefaultTrue,
 		"frameworks/av/media/codecs":                         Bp2BuildDefaultTrueRecursively,
+		"frameworks/av/media/codec2/components/aom":          Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/liberror":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/services/minijail":                    Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/module/minijail":                Bp2BuildDefaultTrueRecursively,
@@ -370,8 +372,10 @@
 		"code_coverage.policy.other",
 		"codec2_soft_exports",
 		"codecs_g711dec",
+		"com.android.media.swcodec",
 		"com.android.media.swcodec-androidManifest",
 		"com.android.media.swcodec-ld.config.txt",
+		"com.android.media.swcodec-mediaswcodec.32rc",
 		"com.android.media.swcodec-mediaswcodec.rc",
 		"com.android.media.swcodec.certificate",
 		"com.android.media.swcodec.key",
@@ -638,6 +642,7 @@
 		"ndk_headers",
 		"ndk_library",
 		"sysprop_library",
+		"bpf",
 	}
 
 	// Add the names of modules that bp2build should never convert, if it is
diff --git a/android/arch.go b/android/arch.go
index 9bc9d89..75ee922 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -147,10 +147,11 @@
 var (
 	archTypeList []ArchType
 
-	Arm    = newArch("arm", "lib32")
-	Arm64  = newArch("arm64", "lib64")
-	X86    = newArch("x86", "lib32")
-	X86_64 = newArch("x86_64", "lib64")
+	Arm     = newArch("arm", "lib32")
+	Arm64   = newArch("arm64", "lib64")
+	Riscv64 = newArch("riscv64", "lib64")
+	X86     = newArch("x86", "lib32")
+	X86_64  = newArch("x86_64", "lib64")
 
 	Common = ArchType{
 		Name: COMMON_VARIANT,
@@ -318,7 +319,7 @@
 	Windows = newOsType("windows", Host, true, X86, X86_64)
 	// Android is the OS for target devices that run all of Android, including the Linux kernel
 	// and the Bionic libc runtime.
-	Android = newOsType("android", Device, false, Arm, Arm64, X86, X86_64)
+	Android = newOsType("android", Device, false, Arm, Arm64, Riscv64, X86, X86_64)
 
 	// CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which
 	// has dependencies on all the OS variants.
diff --git a/android/arch_test.go b/android/arch_test.go
index 6814f8a..46c018a 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -596,6 +596,7 @@
 				arm64: {
 					a:  ["arm64"],
 				},
+				riscv64: { a: ["riscv64"] },
 				x86: { a:  ["x86"] },
 				x86_64: { a:  ["x86_64"] },
 			},
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 3e490dd..6409292 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -104,9 +104,16 @@
 	configKey   configKey
 }
 
+func makeCqueryKey(label string, cqueryRequest cqueryRequest, cfgKey configKey) cqueryKey {
+	if strings.HasPrefix(label, "//") {
+		// Normalize Bazel labels to specify main repository explicitly.
+		label = "@" + label
+	}
+	return cqueryKey{label, cqueryRequest, cfgKey}
+}
+
 func (c cqueryKey) String() string {
 	return fmt.Sprintf("cquery(%s,%s,%s)", c.label, c.requestType.Name(), c.configKey)
-
 }
 
 // BazelContext is a context object useful for interacting with Bazel during
@@ -261,23 +268,24 @@
 var _ BazelContext = MockBazelContext{}
 
 func (bazelCtx *bazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
-	key := cqueryKey{label, requestType, cfgKey}
+	key := makeCqueryKey(label, requestType, cfgKey)
 	bazelCtx.requestMutex.Lock()
 	defer bazelCtx.requestMutex.Unlock()
 	bazelCtx.requests[key] = true
 }
 
 func (bazelCtx *bazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
-	key := cqueryKey{label, cquery.GetOutputFiles, cfgKey}
+	key := makeCqueryKey(label, cquery.GetOutputFiles, cfgKey)
 	if rawString, ok := bazelCtx.results[key]; ok {
 		bazelOutput := strings.TrimSpace(rawString)
+
 		return cquery.GetOutputFiles.ParseResult(bazelOutput), nil
 	}
 	return nil, fmt.Errorf("no bazel response found for %v", key)
 }
 
 func (bazelCtx *bazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
-	key := cqueryKey{label, cquery.GetCcInfo, cfgKey}
+	key := makeCqueryKey(label, cquery.GetCcInfo, cfgKey)
 	if rawString, ok := bazelCtx.results[key]; ok {
 		bazelOutput := strings.TrimSpace(rawString)
 		return cquery.GetCcInfo.ParseResult(bazelOutput)
@@ -286,7 +294,7 @@
 }
 
 func (bazelCtx *bazelContext) GetPythonBinary(label string, cfgKey configKey) (string, error) {
-	key := cqueryKey{label, cquery.GetPythonBinary, cfgKey}
+	key := makeCqueryKey(label, cquery.GetPythonBinary, cfgKey)
 	if rawString, ok := bazelCtx.results[key]; ok {
 		bazelOutput := strings.TrimSpace(rawString)
 		return cquery.GetPythonBinary.ParseResult(bazelOutput), nil
@@ -295,7 +303,7 @@
 }
 
 func (bazelCtx *bazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexCqueryInfo, error) {
-	key := cqueryKey{label, cquery.GetApexInfo, cfgKey}
+	key := makeCqueryKey(label, cquery.GetApexInfo, cfgKey)
 	if rawString, ok := bazelCtx.results[key]; ok {
 		return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString)), nil
 	}
@@ -755,6 +763,10 @@
 def format(target):
   id_string = str(target.label) + "|" + get_arch(target)
 
+  # TODO(b/248106697): Remove once Bazel is updated to always normalize labels.
+  if id_string.startswith("//"):
+    id_string = "@" + id_string
+
   # Main switch section
   %s
   # This target was not requested via cquery, and thus must be a dependency
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index ec2541b..dc2261c 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -13,10 +13,10 @@
 var testConfig = TestConfig("out", nil, "", nil)
 
 func TestRequestResultsAfterInvokeBazel(t *testing.T) {
-	label := "//foo:bar"
+	label := "@//foo:bar"
 	cfg := configKey{"arm64_armv8-a", Android}
 	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
-		bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
+		bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
 	})
 	bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
 	err := bazelContext.InvokeBazel(testConfig)
diff --git a/android/module.go b/android/module.go
index f63a06d..a150e61 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1523,7 +1523,7 @@
 	return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.UnconvertedDeps)
 }
 
-// GetMissingBp2buildDeps eturns the list of module names that were not found in Android.bp files.
+// GetMissingBp2buildDeps returns the list of module names that were not found in Android.bp files.
 func (m *ModuleBase) GetMissingBp2buildDeps() []string {
 	return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.MissingDeps)
 }
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 4e4fa42..9b5c0e9 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -56,7 +56,9 @@
 var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag
 var _ ExcludeFromApexContentsTag = PrebuiltDepTag
 
-type PrebuiltProperties struct {
+// UserSuppliedPrebuiltProperties contains the prebuilt properties that can be specified in an
+// Android.bp file.
+type UserSuppliedPrebuiltProperties struct {
 	// When prefer is set to true the prebuilt will be used instead of any source module with
 	// a matching name.
 	Prefer *bool `android:"arch_variant"`
@@ -70,6 +72,16 @@
 	// If specified then the prefer property is ignored in favor of the value of the Soong config
 	// variable.
 	Use_source_config_var *ConfigVarProperties
+}
+
+// CopyUserSuppliedPropertiesFromPrebuilt copies the user supplied prebuilt properties from the
+// prebuilt properties.
+func (u *UserSuppliedPrebuiltProperties) CopyUserSuppliedPropertiesFromPrebuilt(p *Prebuilt) {
+	*u = p.properties.UserSuppliedPrebuiltProperties
+}
+
+type PrebuiltProperties struct {
+	UserSuppliedPrebuiltProperties
 
 	SourceExists bool `blueprint:"mutated"`
 	UsePrebuilt  bool `blueprint:"mutated"`
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7ae9ed7..e130fcc 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7235,12 +7235,13 @@
 	ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
 	s := mod.Rule("apexRule").Args["copy_commands"]
 	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
-	if len(copyCmds) != 3 {
-		t.Fatalf("Expected 3 commands, got %d in:\n%s", len(copyCmds), s)
+	if len(copyCmds) != 4 {
+		t.Fatalf("Expected 4 commands, got %d in:\n%s", len(copyCmds), s)
 	}
 	ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet@TEST.BUILD_ID$")
 	ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet@TEST.BUILD_ID$")
-	ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet@TEST.BUILD_ID .*/AppSet.zip$")
+	ensureMatches(t, copyCmds[2], "^cp -f .*/app/AppSet@TEST.BUILD_ID/AppSet.apk$")
+	ensureMatches(t, copyCmds[3], "^unzip .*-d .*/app/AppSet@TEST.BUILD_ID .*/AppSet.zip$")
 
 	// Ensure that canned_fs_config has an entry for the app set zip file
 	generateFsRule := mod.Rule("generateFsConfig")
diff --git a/apex/builder.go b/apex/builder.go
index cb09e35..ad8075b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -459,8 +459,13 @@
 			pathOnDevice := filepath.Join("/system", fi.path())
 			copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
 		} else {
+			// Copy the file into APEX
+			copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+
 			var installedPath android.InstallPath
 			if fi.class == appSet {
+				// In case of AppSet, we need to copy additional APKs as well. They
+				// are zipped. So we need to unzip them.
 				copyCommands = append(copyCommands,
 					fmt.Sprintf("unzip -qDD -d %s %s", destPathDir,
 						fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs().String()))
@@ -469,7 +474,6 @@
 						fi.stem(), fi.builtFile, fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs())
 				}
 			} else {
-				copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
 				if installSymbolFiles {
 					installedPath = ctx.InstallFile(pathWhenActivated.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
 				}
@@ -1086,6 +1090,9 @@
 				executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
 			}
 		} else if f.class == appSet {
+			// base APK
+			readOnlyPaths = append(readOnlyPaths, pathInApex)
+			// Additional APKs
 			appSetDirs = append(appSetDirs, f.installDir)
 			appSetFiles[f.installDir] = f.module.(*java.AndroidAppSet).PackedAdditionalOutputs()
 		} else {
diff --git a/bazel/configurability.go b/bazel/configurability.go
index b6bbd67..a93aa00 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -23,10 +23,11 @@
 
 const (
 	// ArchType names in arch.go
-	archArm    = "arm"
-	archArm64  = "arm64"
-	archX86    = "x86"
-	archX86_64 = "x86_64"
+	archArm     = "arm"
+	archArm64   = "arm64"
+	archRiscv64 = "riscv64"
+	archX86     = "x86"
+	archX86_64  = "x86_64"
 
 	// OsType names in arch.go
 	OsAndroid     = "android"
@@ -39,6 +40,7 @@
 	// Targets in arch.go
 	osArchAndroidArm        = "android_arm"
 	osArchAndroidArm64      = "android_arm64"
+	osArchAndroidRiscv64    = "android_riscv64"
 	osArchAndroidX86        = "android_x86"
 	osArchAndroidX86_64     = "android_x86_64"
 	osArchDarwinArm64       = "darwin_arm64"
@@ -99,6 +101,7 @@
 		"arm64": {
 			"dotprod",
 		},
+		"riscv64": {},
 		"x86": {
 			"ssse3",
 			"sse4",
@@ -164,6 +167,7 @@
 	platformOsArchMap = map[string]string{
 		osArchAndroidArm:           "//build/bazel/platforms/os_arch:android_arm",
 		osArchAndroidArm64:         "//build/bazel/platforms/os_arch:android_arm64",
+		osArchAndroidRiscv64:       "//build/bazel/platforms/os_arch:android_riscv64",
 		osArchAndroidX86:           "//build/bazel/platforms/os_arch:android_x86",
 		osArchAndroidX86_64:        "//build/bazel/platforms/os_arch:android_x86_64",
 		osArchDarwinArm64:          "//build/bazel/platforms/os_arch:darwin_arm64",
@@ -187,7 +191,7 @@
 	// TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
 	// in a cyclic dependency.
 	osToArchMap = map[string][]string{
-		OsAndroid:     {archArm, archArm64, archX86, archX86_64},
+		OsAndroid:     {archArm, archArm64, archRiscv64, archX86, archX86_64},
 		osLinux:       {archX86, archX86_64},
 		osLinuxMusl:   {archX86, archX86_64},
 		osDarwin:      {archArm64, archX86_64},
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 3b06f85..e35b531 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -181,6 +181,9 @@
 	decoder := json.NewDecoder(strings.NewReader(rawString))
 	decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
 	err := decoder.Decode(&ccInfo)
+	if err != nil {
+		return ccInfo, fmt.Errorf("error parsing CcInfo result. %s RAW STRING: %s", err, rawString)
+	}
 	return ccInfo, err
 }
 
diff --git a/bp2build/bpf_conversion_test.go b/bp2build/bpf_conversion_test.go
new file mode 100644
index 0000000..1259f9e
--- /dev/null
+++ b/bp2build/bpf_conversion_test.go
@@ -0,0 +1,65 @@
+// 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/bpf"
+
+	"testing"
+)
+
+func runBpfTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	(&tc).ModuleTypeUnderTest = "bpf"
+	(&tc).ModuleTypeUnderTestFactory = bpf.BpfFactory
+	RunBp2BuildTestCase(t, registerBpfModuleTypes, tc)
+}
+
+func registerBpfModuleTypes(ctx android.RegistrationContext) {}
+
+func TestBpfSupportedAttrs(t *testing.T) {
+	runBpfTestCase(t, Bp2buildTestCase{
+		Description: "Bpf module only converts supported attributes",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+bpf {
+    name: "bpfTestOut.o",
+    srcs: ["bpfTestSrcOne.c",
+           "bpfTestSrcTwo.c"],
+    btf: true,
+    cflags: ["-bpfCflagOne",
+             "-bpfCflagTwo"],
+    include_dirs: ["ia/ib/ic"],
+    sub_dir: "sa/ab",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("bpf", "bpfTestOut.o", AttrNameToString{
+				"absolute_includes": `["ia/ib/ic"]`,
+				"btf":               `True`,
+				"copts": `[
+        "-bpfCflagOne",
+        "-bpfCflagTwo",
+    ]`,
+				"srcs": `[
+        "bpfTestSrcOne.c",
+        "bpfTestSrcTwo.c",
+    ]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index d513d04..c1fb800 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -369,6 +369,7 @@
       x86_64:  { arch_paths: ["x86_64.txt"] },
       arm:  { arch_paths: ["arm.txt"] },
       arm64:  { arch_paths: ["arm64.txt"] },
+      riscv64: { arch_paths: ["riscv64.txt"] },
     },
     target: {
       linux: { arch_paths: ["linux.txt"] },
@@ -401,6 +402,10 @@
             "arm64.txt",
             "lib64.txt",
         ],
+        "//build/bazel/platforms/arch:riscv64": [
+            "riscv64.txt",
+            "lib64.txt",
+        ],
         "//build/bazel/platforms/arch:x86": [
             "x86.txt",
             "lib32.txt",
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index e3ea9a0..b47d1f1 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -836,6 +836,10 @@
             "not-for-lib32.c",
             "for-lib64.c",
         ],
+        "//build/bazel/platforms/arch:riscv64": [
+            "not-for-lib32.c",
+            "for-lib64.c",
+        ],
         "//build/bazel/platforms/arch:x86": [
             "not-for-lib64.c",
             "for-lib32.c",
@@ -867,6 +871,7 @@
 			"for-lib64.c":          "",
 			"not-for-arm.c":        "",
 			"not-for-arm64.c":      "",
+			"not-for-riscv64.c":    "",
 			"not-for-x86.c":        "",
 			"not-for-x86_64.c":     "",
 			"not-for-lib32.c":      "",
@@ -881,6 +886,7 @@
    arch: {
        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
        arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
+       riscv64: { srcs: ["for-riscv64.c"], exclude_srcs: ["not-for-riscv64.c"] },
        x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
        x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
    },
@@ -896,6 +902,7 @@
         "//build/bazel/platforms/arch:arm": [
             "not-for-arm64.c",
             "not-for-lib64.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
             "for-arm.c",
@@ -904,15 +911,26 @@
         "//build/bazel/platforms/arch:arm64": [
             "not-for-arm.c",
             "not-for-lib32.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
             "for-arm64.c",
             "for-lib64.c",
         ],
+        "//build/bazel/platforms/arch:riscv64": [
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-lib32.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+            "for-riscv64.c",
+            "for-lib64.c",
+        ],
         "//build/bazel/platforms/arch:x86": [
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-lib64.c",
+            "not-for-riscv64.c",
             "not-for-x86_64.c",
             "for-x86.c",
             "for-lib32.c",
@@ -921,6 +939,7 @@
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-lib32.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "for-x86_64.c",
             "for-lib64.c",
@@ -930,6 +949,7 @@
             "not-for-arm64.c",
             "not-for-lib32.c",
             "not-for-lib64.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
         ],
diff --git a/bpf/bpf.go b/bpf/bpf.go
index e89cc4e..dbbce50 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -21,6 +21,7 @@
 	"strings"
 
 	"android/soong/android"
+	"android/soong/bazel"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -93,6 +94,7 @@
 
 type bpf struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	properties BpfProperties
 
@@ -260,5 +262,39 @@
 	module.AddProperties(&module.properties)
 
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitBazelModule(module)
 	return module
 }
+
+type bazelBpfAttributes struct {
+	Srcs              bazel.LabelListAttribute
+	Copts             bazel.StringListAttribute
+	Absolute_includes bazel.StringListAttribute
+	Btf               *bool
+	// TODO(b/249528391): Add support for sub_dir
+}
+
+// bpf bp2build converter
+func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	if ctx.ModuleType() != "bpf" {
+		return
+	}
+
+	srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, b.properties.Srcs))
+	copts := bazel.MakeStringListAttribute(b.properties.Cflags)
+	absolute_includes := bazel.MakeStringListAttribute(b.properties.Include_dirs)
+	btf := b.properties.Btf
+
+	attrs := bazelBpfAttributes{
+		Srcs:              srcs,
+		Copts:             copts,
+		Absolute_includes: absolute_includes,
+		Btf:               btf,
+	}
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "bpf",
+		Bzl_load_location: "//build/bazel/rules/bpf:bpf.bzl",
+	}
+
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: b.Name()}, &attrs)
+}
diff --git a/cc/builder.go b/cc/builder.go
index cb21b1f..0bea9da 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -1135,7 +1135,3 @@
 		},
 	})
 }
-
-func mingwCmd(toolchain config.Toolchain, cmd string) string {
-	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
-}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 01ac133..6a22bd0 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3260,6 +3260,102 @@
 	}
 }
 
+func pathsToBase(paths android.Paths) []string {
+	var ret []string
+	for _, p := range paths {
+		ret = append(ret, p.Base())
+	}
+	return ret
+}
+
+func TestStaticLibArchiveArgs(t *testing.T) {
+	ctx := testCc(t, `
+		cc_library_static {
+			name: "foo",
+			srcs: ["foo.c"],
+		}
+
+		cc_library_static {
+			name: "bar",
+			srcs: ["bar.c"],
+		}
+
+		cc_library_shared {
+			name: "qux",
+			srcs: ["qux.c"],
+		}
+
+		cc_library_static {
+			name: "baz",
+			srcs: ["baz.c"],
+			static_libs: ["foo"],
+			shared_libs: ["qux"],
+			whole_static_libs: ["bar"],
+		}`)
+
+	variant := "android_arm64_armv8-a_static"
+	arRule := ctx.ModuleForTests("baz", variant).Rule("ar")
+
+	// For static libraries, the object files of a whole static dep are included in the archive
+	// directly
+	if g, w := pathsToBase(arRule.Inputs), []string{"bar.o", "baz.o"}; !reflect.DeepEqual(w, g) {
+		t.Errorf("Expected input objects %q, got %q", w, g)
+	}
+
+	// non whole static dependencies are not linked into the archive
+	if len(arRule.Implicits) > 0 {
+		t.Errorf("Expected 0 additional deps, got %q", arRule.Implicits)
+	}
+}
+
+func TestSharedLibLinkingArgs(t *testing.T) {
+	ctx := testCc(t, `
+		cc_library_static {
+			name: "foo",
+			srcs: ["foo.c"],
+		}
+
+		cc_library_static {
+			name: "bar",
+			srcs: ["bar.c"],
+		}
+
+		cc_library_shared {
+			name: "qux",
+			srcs: ["qux.c"],
+		}
+
+		cc_library_shared {
+			name: "baz",
+			srcs: ["baz.c"],
+			static_libs: ["foo"],
+			shared_libs: ["qux"],
+			whole_static_libs: ["bar"],
+		}`)
+
+	variant := "android_arm64_armv8-a_shared"
+	linkRule := ctx.ModuleForTests("baz", variant).Rule("ld")
+	libFlags := linkRule.Args["libFlags"]
+	// When dynamically linking, we expect static dependencies to be found on the command line
+	if expected := "foo.a"; !strings.Contains(libFlags, expected) {
+		t.Errorf("Static lib %q was not found in %q", expected, libFlags)
+	}
+	// When dynamically linking, we expect whole static dependencies to be found on the command line
+	if expected := "bar.a"; !strings.Contains(libFlags, expected) {
+		t.Errorf("Static lib %q was not found in %q", expected, libFlags)
+	}
+
+	// When dynamically linking, we expect shared dependencies to be found on the command line
+	if expected := "qux.so"; !strings.Contains(libFlags, expected) {
+		t.Errorf("Shared lib %q was not found in %q", expected, libFlags)
+	}
+
+	// We should only have the objects from the shared library srcs, not the whole static dependencies
+	if g, w := pathsToBase(linkRule.Inputs), []string{"baz.o"}; !reflect.DeepEqual(w, g) {
+		t.Errorf("Expected input objects %q, got %q", w, g)
+	}
+}
+
 func TestStaticExecutable(t *testing.T) {
 	ctx := testCc(t, `
 		cc_binary {
@@ -3543,14 +3639,6 @@
 			defaults: ["defaults"],
 		}`)
 
-	pathsToBase := func(paths android.Paths) []string {
-		var ret []string
-		for _, p := range paths {
-			ret = append(ret, p.Base())
-		}
-		return ret
-	}
-
 	shared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared").Rule("ld")
 	if g, w := pathsToBase(shared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
 		t.Errorf("libshared ld rule wanted %q, got %q", w, g)
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index 64a121e..fdc94ad 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -21,6 +21,7 @@
 
         "arm_device.go",
         "arm64_device.go",
+        "riscv64_device.go",
         "x86_device.go",
         "x86_64_device.go",
 
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 66087e6..d7f9618 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -74,7 +74,7 @@
 			"-mcpu=kryo",
 		},
 		"kryo385": []string{
-			// Use cortex-a53 because kryo385 is not supported in GCC/clang.
+			// Use cortex-a53 because kryo385 is not supported in clang.
 			"-mcpu=cortex-a53",
 		},
 		"exynos-m1": []string{
@@ -86,16 +86,7 @@
 	}
 )
 
-const (
-	arm64GccVersion = "4.9"
-)
-
 func init() {
-	pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
-
-	pctx.SourcePathVariable("Arm64GccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
-
 	exportedVars.ExportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
 	exportedVars.ExportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
 
@@ -164,24 +155,12 @@
 	return "arm64"
 }
 
-func (t *toolchainArm64) GccRoot() string {
-	return "${config.Arm64GccRoot}"
-}
-
-func (t *toolchainArm64) GccTriple() string {
-	return "aarch64-linux-android"
-}
-
-func (t *toolchainArm64) GccVersion() string {
-	return arm64GccVersion
-}
-
 func (t *toolchainArm64) IncludeFlags() string {
 	return ""
 }
 
 func (t *toolchainArm64) ClangTriple() string {
-	return t.GccTriple()
+	return "aarch64-linux-android"
 }
 
 func (t *toolchainArm64) Cflags() string {
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index d702c61..b53a097 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -79,7 +79,7 @@
 		"cortex-a7": []string{
 			"-mcpu=cortex-a7",
 			"-mfpu=neon-vfpv4",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -91,7 +91,7 @@
 		"cortex-a15": []string{
 			"-mcpu=cortex-a15",
 			"-mfpu=neon-vfpv4",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -100,7 +100,7 @@
 		"cortex-a53": []string{
 			"-mcpu=cortex-a53",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -109,7 +109,7 @@
 		"cortex-a55": []string{
 			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -118,7 +118,7 @@
 		"cortex-a75": []string{
 			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -127,7 +127,7 @@
 		"cortex-a76": []string{
 			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -136,7 +136,7 @@
 		"krait": []string{
 			"-mcpu=krait",
 			"-mfpu=neon-vfpv4",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -147,16 +147,16 @@
 			// even though clang does.
 			"-mcpu=cortex-a53",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
 			"-D__ARM_FEATURE_LPAE=1",
 		},
 		"kryo385": []string{
-			// Use cortex-a53 because kryo385 is not supported in GCC/clang.
+			// Use cortex-a53 because kryo385 is not supported in clang.
 			"-mcpu=cortex-a53",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -166,17 +166,12 @@
 )
 
 const (
-	name          = "arm"
-	armGccVersion = "4.9"
-	gccTriple     = "arm-linux-androideabi"
-	clangTriple   = "armv7a-linux-androideabi"
+	name        = "arm"
+	ndkTriple   = "arm-linux-androideabi"
+	clangTriple = "armv7a-linux-androideabi"
 )
 
 func init() {
-	pctx.StaticVariable("armGccVersion", armGccVersion)
-
-	pctx.SourcePathVariable("ArmGccRoot", "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
-
 	// Just exported. Not created as a Ninja static variable.
 	exportedVars.ExportString("ArmClangTriple", clangTriple)
 
@@ -255,18 +250,6 @@
 	return name
 }
 
-func (t *toolchainArm) GccRoot() string {
-	return "${config.ArmGccRoot}"
-}
-
-func (t *toolchainArm) GccTriple() string {
-	return gccTriple
-}
-
-func (t *toolchainArm) GccVersion() string {
-	return armGccVersion
-}
-
 func (t *toolchainArm) IncludeFlags() string {
 	return ""
 }
@@ -278,7 +261,7 @@
 
 func (t *toolchainArm) ndkTriple() string {
 	// Use current NDK include path, while ClangTriple is changed.
-	return t.GccTriple()
+	return ndkTriple
 }
 
 func (t *toolchainArm) ToolchainCflags() string {
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 01b1e63..2cabdc8 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -75,10 +75,6 @@
 	)
 )
 
-const (
-	darwinGccVersion = "4.2.1"
-)
-
 func init() {
 	pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
 		return getMacTools(ctx).sdkRoot
@@ -100,12 +96,6 @@
 		return getMacTools(ctx).toolPath
 	})
 
-	pctx.StaticVariable("DarwinGccVersion", darwinGccVersion)
-	pctx.SourcePathVariable("DarwinGccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${DarwinGccVersion}")
-
-	pctx.StaticVariable("DarwinGccTriple", "i686-apple-darwin11")
-
 	pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
 	pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
 	pctx.StaticVariable("DarwinLldflags", strings.Join(darwinLdflags, " "))
@@ -196,30 +186,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainDarwinArm) GccRoot() string {
-	panic("unimplemented")
-}
-
-func (t *toolchainDarwinArm) GccTriple() string {
-	panic("unimplemented")
-}
-
-func (t *toolchainDarwinArm) GccVersion() string {
-	panic("unimplemented")
-}
-
-func (t *toolchainDarwinX86) GccRoot() string {
-	return "${config.DarwinGccRoot}"
-}
-
-func (t *toolchainDarwinX86) GccTriple() string {
-	return "${config.DarwinGccTriple}"
-}
-
-func (t *toolchainDarwinX86) GccVersion() string {
-	return darwinGccVersion
-}
-
 func (t *toolchainDarwin) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
new file mode 100644
index 0000000..d8918f1
--- /dev/null
+++ b/cc/config/riscv64_device.go
@@ -0,0 +1,140 @@
+// 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 config
+
+import (
+	"fmt"
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	riscv64Cflags = []string{
+		// Help catch common 32/64-bit errors.
+		"-Werror=implicit-function-declaration",
+	}
+
+	riscv64ArchVariantCflags = map[string][]string{}
+
+	riscv64Ldflags = []string{
+		"-Wl,--hash-style=gnu",
+		"-Wl,-z,separate-code",
+	}
+
+	riscv64Lldflags = append(riscv64Ldflags,
+		"-Wl,-z,max-page-size=4096")
+
+	riscv64Cppflags = []string{}
+
+	riscv64CpuVariantCflags = map[string][]string{}
+)
+
+const ()
+
+func init() {
+
+	exportedVars.ExportStringListStaticVariable("Riscv64Ldflags", riscv64Ldflags)
+	exportedVars.ExportStringListStaticVariable("Riscv64Lldflags", riscv64Lldflags)
+
+	exportedVars.ExportStringListStaticVariable("Riscv64Cflags", riscv64Cflags)
+	exportedVars.ExportStringListStaticVariable("Riscv64Cppflags", riscv64Cppflags)
+
+	exportedVars.ExportVariableReferenceDict("Riscv64ArchVariantCflags", riscv64ArchVariantCflagsVar)
+	exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantCflags", riscv64CpuVariantCflagsVar)
+	exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantLdflags", riscv64CpuVariantLdflags)
+}
+
+var (
+	riscv64ArchVariantCflagsVar = map[string]string{}
+
+	riscv64CpuVariantCflagsVar = map[string]string{}
+
+	riscv64CpuVariantLdflags = map[string]string{}
+)
+
+type toolchainRiscv64 struct {
+	toolchainBionic
+	toolchain64Bit
+
+	ldflags         string
+	lldflags        string
+	toolchainCflags string
+}
+
+func (t *toolchainRiscv64) Name() string {
+	return "riscv64"
+}
+
+func (t *toolchainRiscv64) IncludeFlags() string {
+	return ""
+}
+
+func (t *toolchainRiscv64) ClangTriple() string {
+	return "riscv64-linux-android"
+}
+
+func (t *toolchainRiscv64) Cflags() string {
+	return "${config.Riscv64Cflags}"
+}
+
+func (t *toolchainRiscv64) Cppflags() string {
+	return "${config.Riscv64Cppflags}"
+}
+
+func (t *toolchainRiscv64) Ldflags() string {
+	return t.ldflags
+}
+
+func (t *toolchainRiscv64) Lldflags() string {
+	return t.lldflags
+}
+
+func (t *toolchainRiscv64) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (toolchainRiscv64) LibclangRuntimeLibraryArch() string {
+	return "riscv64"
+}
+
+func riscv64ToolchainFactory(arch android.Arch) Toolchain {
+	switch arch.ArchVariant {
+	case "":
+	default:
+		panic(fmt.Sprintf("Unknown Riscv64 architecture version: %q", arch.ArchVariant))
+	}
+
+	toolchainCflags := []string{riscv64ArchVariantCflagsVar[arch.ArchVariant]}
+	toolchainCflags = append(toolchainCflags,
+		variantOrDefault(riscv64CpuVariantCflagsVar, arch.CpuVariant))
+
+	extraLdflags := variantOrDefault(riscv64CpuVariantLdflags, arch.CpuVariant)
+	return &toolchainRiscv64{
+		ldflags: strings.Join([]string{
+			"${config.Riscv64Ldflags}",
+			extraLdflags,
+		}, " "),
+		lldflags: strings.Join([]string{
+			"${config.Riscv64Lldflags}",
+			extraLdflags,
+		}, " "),
+		toolchainCflags: strings.Join(toolchainCflags, " "),
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.Riscv64, riscv64ToolchainFactory)
+}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index d9eaf53..eb71aa1 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -63,11 +63,6 @@
 type Toolchain interface {
 	Name() string
 
-	GccRoot() string
-	GccTriple() string
-	// GccVersion should return a real value, not a ninja reference
-	GccVersion() string
-
 	IncludeFlags() string
 
 	ClangTriple() string
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index aebda0b..e2b0f06 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -80,17 +80,7 @@
 	}
 )
 
-const (
-	x86_64GccVersion = "4.9"
-)
-
 func init() {
-
-	pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
-
-	pctx.SourcePathVariable("X86_64GccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
-
 	exportedVars.ExportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
 	exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
 
@@ -128,24 +118,12 @@
 	return "x86_64"
 }
 
-func (t *toolchainX86_64) GccRoot() string {
-	return "${config.X86_64GccRoot}"
-}
-
-func (t *toolchainX86_64) GccTriple() string {
-	return "x86_64-linux-android"
-}
-
-func (t *toolchainX86_64) GccVersion() string {
-	return x86_64GccVersion
-}
-
 func (t *toolchainX86_64) IncludeFlags() string {
 	return ""
 }
 
 func (t *toolchainX86_64) ClangTriple() string {
-	return t.GccTriple()
+	return "x86_64-linux-android"
 }
 
 func (t *toolchainX86_64) ToolchainLdflags() string {
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 421b083..3001ab4 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -88,16 +88,7 @@
 	}
 )
 
-const (
-	x86GccVersion = "4.9"
-)
-
 func init() {
-	pctx.StaticVariable("x86GccVersion", x86GccVersion)
-
-	pctx.SourcePathVariable("X86GccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
-
 	exportedVars.ExportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
 	exportedVars.ExportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
 
@@ -134,18 +125,6 @@
 	return "x86"
 }
 
-func (t *toolchainX86) GccRoot() string {
-	return "${config.X86GccRoot}"
-}
-
-func (t *toolchainX86) GccTriple() string {
-	return "x86_64-linux-android"
-}
-
-func (t *toolchainX86) GccVersion() string {
-	return x86GccVersion
-}
-
 func (t *toolchainX86) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 976cc25..96a53bf 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -66,13 +66,20 @@
 		"host_bionic_linker_script")
 )
 
+const (
+	x86_64GccVersion = "4.9"
+)
+
 func init() {
+
 	pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
 	pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
 	pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLdflags, " "))
 
 	// Use the device gcc toolchain for now
-	pctx.StaticVariable("LinuxBionicGccRoot", "${X86_64GccRoot}")
+	pctx.StaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
+	pctx.SourcePathVariable("LinuxBionicGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${LinuxBionicGccVersion}")
 }
 
 type toolchainLinuxBionic struct {
@@ -84,18 +91,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainLinuxBionic) GccRoot() string {
-	return "${config.LinuxBionicGccRoot}"
-}
-
-func (t *toolchainLinuxBionic) GccTriple() string {
-	return "x86_64-linux-android"
-}
-
-func (t *toolchainLinuxBionic) GccVersion() string {
-	return "4.9"
-}
-
 func (t *toolchainLinuxBionic) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 07b95e1..740405e 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -180,18 +180,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainLinux) GccRoot() string {
-	return "${config.LinuxGccRoot}"
-}
-
-func (t *toolchainLinux) GccTriple() string {
-	return "${config.LinuxGccTriple}"
-}
-
-func (t *toolchainLinux) GccVersion() string {
-	return linuxGccVersion
-}
-
 func (t *toolchainLinux) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index a33606f..561c500 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -175,24 +175,12 @@
 	return "x86_64"
 }
 
-func (t *toolchainWindows) GccRoot() string {
-	return "${config.WindowsGccRoot}"
-}
-
-func (t *toolchainWindows) GccTriple() string {
-	return "${config.WindowsGccTriple}"
-}
-
 func (t *toolchainWindows) ToolchainCflags() string {
-	return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin")
+	return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin")
 }
 
 func (t *toolchainWindows) ToolchainLdflags() string {
-	return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin")
-}
-
-func (t *toolchainWindows) GccVersion() string {
-	return windowsGccVersion
+	return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin")
 }
 
 func (t *toolchainWindows) IncludeFlags() string {
diff --git a/cc/makevars.go b/cc/makevars.go
index de8a8f2..c70d4a6 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -314,8 +314,6 @@
 		ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld")
 		ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain))
 		ctx.Strict(makePrefix+"TOOLS_PREFIX", "${config.ClangBin}/llvm-")
-		// TODO: GCC version is obsolete now that GCC has been removed.
-		ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion())
 	}
 
 	if target.Os.Class == android.Host {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 436b149..0b47f0e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -881,8 +881,12 @@
 	switch t {
 	case Asan:
 		sanitize.Properties.Sanitize.Address = bPtr
+		// For ASAN variant, we need to disable Memtag_stack
+		sanitize.Properties.Sanitize.Memtag_stack = nil
 	case Hwasan:
 		sanitize.Properties.Sanitize.Hwaddress = bPtr
+		// For HWAsan variant, we need to disable Memtag_stack
+		sanitize.Properties.Sanitize.Memtag_stack = nil
 	case tsan:
 		sanitize.Properties.Sanitize.Thread = bPtr
 	case intOverflow:
@@ -895,6 +899,7 @@
 		sanitize.Properties.Sanitize.Memtag_heap = bPtr
 	case Memtag_stack:
 		sanitize.Properties.Sanitize.Memtag_stack = bPtr
+		// We do not need to disable ASAN or HWASan here, as there is no Memtag_stack variant.
 	case Fuzzer:
 		sanitize.Properties.Sanitize.Fuzzer = bPtr
 	default:
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index d4a57bf..0e8ad05 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -150,6 +150,7 @@
 var defaultMinSdkVersion string
 var useVersion string
 var staticDeps bool
+var writeCmd bool
 var jetifier bool
 
 func InList(s string, list []string) bool {
@@ -810,6 +811,9 @@
   -use-version <version>
      If the maven directory contains multiple versions of artifacts and their pom files,
      -use-version can be used to only write Android.bp files for a specific version of those artifacts.
+  -write-cmd
+     Whether to write the command line arguments used to generate the build file as a comment at
+     the top of the build file itself.
   -jetifier
      Sets jetifier: true for all modules.
   <dir>
@@ -837,6 +841,7 @@
 	flag.StringVar(&defaultMinSdkVersion, "default-min-sdk-version", "24", "Default min_sdk_version to use, if one is not available from AndroidManifest.xml. Default: 24")
 	flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version")
 	flag.BoolVar(&staticDeps, "static-deps", false, "Statically include direct dependencies")
+	flag.BoolVar(&writeCmd, "write-cmd", true, "Write command line arguments as a comment")
 	flag.BoolVar(&jetifier, "jetifier", false, "Sets jetifier: true on all modules")
 	flag.StringVar(&regen, "regen", "", "Rewrite specified file")
 	flag.BoolVar(&pom2build, "pom2build", false, "If true, will generate a Bazel BUILD file *instead* of a .bp file")
@@ -964,8 +969,13 @@
 	if pom2build {
 		commentString = "#"
 	}
-	fmt.Fprintln(buf, commentString, "Automatically generated with:")
-	fmt.Fprintln(buf, commentString, "pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
+
+	fmt.Fprintln(buf, commentString, "This is a generated file. Do not modify directly.")
+
+	if writeCmd {
+		fmt.Fprintln(buf, commentString, "Automatically generated with:")
+		fmt.Fprintln(buf, commentString, "pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
+	}
 
 	if prepend != "" {
 		contents, err := ioutil.ReadFile(prepend)
diff --git a/java/aar.go b/java/aar.go
index 3aa95d4..6261f29 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -440,7 +440,7 @@
 		switch depTag {
 		case instrumentationForTag:
 			// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
-		case libTag:
+		case sdkLibTag, libTag:
 			if exportPackage != nil {
 				sharedLibs = append(sharedLibs, exportPackage)
 			}
diff --git a/java/base.go b/java/base.go
index 23b4d46..656a080 100644
--- a/java/base.go
+++ b/java/base.go
@@ -530,7 +530,7 @@
 		// TODO(satayev): cover other types as well, e.g. imports
 		case *Library, *AndroidLibrary:
 			switch tag {
-			case bootClasspathTag, libTag, staticLibTag, java9LibTag:
+			case bootClasspathTag, sdkLibTag, libTag, staticLibTag, java9LibTag:
 				j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag))
 			}
 		}
@@ -1955,7 +1955,7 @@
 
 		if dep, ok := module.(SdkLibraryDependency); ok {
 			switch tag {
-			case libTag:
+			case sdkLibTag, libTag:
 				depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))
 				deps.classpath = append(deps.classpath, depHeaderJars...)
 				deps.dexClasspath = append(deps.dexClasspath, depHeaderJars...)
@@ -1975,7 +1975,7 @@
 			switch tag {
 			case bootClasspathTag:
 				deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
-			case libTag, instrumentationForTag:
+			case sdkLibTag, libTag, instrumentationForTag:
 				if _, ok := module.(*Plugin); ok {
 					ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName)
 				}
@@ -2048,7 +2048,7 @@
 			}
 		} else if dep, ok := module.(android.SourceFileProducer); ok {
 			switch tag {
-			case libTag:
+			case sdkLibTag, libTag:
 				checkProducesJars(ctx, dep)
 				deps.classpath = append(deps.classpath, dep.Srcs()...)
 				deps.dexClasspath = append(deps.classpath, dep.Srcs()...)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 15585f1..2173dae 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -267,7 +267,7 @@
 			ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
 			ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
 			ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
-			ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...)
+			ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
 		}
 	}
 
@@ -367,7 +367,7 @@
 			} else {
 				panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
 			}
-		case libTag:
+		case libTag, sdkLibTag:
 			if dep, ok := module.(SdkLibraryDependency); ok {
 				deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
 			} else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
diff --git a/java/java.go b/java/java.go
index d04e52a..fc2af3b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -348,6 +348,7 @@
 	dataDeviceBinsTag       = dependencyTag{name: "dataDeviceBins"}
 	staticLibTag            = dependencyTag{name: "staticlib"}
 	libTag                  = dependencyTag{name: "javalib", runtimeLinked: true}
+	sdkLibTag               = dependencyTag{name: "sdklib", runtimeLinked: true}
 	java9LibTag             = dependencyTag{name: "java9lib", runtimeLinked: true}
 	pluginTag               = dependencyTag{name: "plugin", toolchain: true}
 	errorpronePluginTag     = dependencyTag{name: "errorprone-plugin", toolchain: true}
@@ -374,7 +375,7 @@
 )
 
 func IsLibDepTag(depTag blueprint.DependencyTag) bool {
-	return depTag == libTag
+	return depTag == libTag || depTag == sdkLibTag
 }
 
 func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -427,7 +428,7 @@
 	if sdkDep.useModule {
 		ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
 		ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
-		ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...)
+		ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
 		if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
 			ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...)
 		}
@@ -1654,7 +1655,7 @@
 		if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
 			dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
 			switch tag {
-			case libTag:
+			case libTag, sdkLibTag:
 				flags.classpath = append(flags.classpath, dep.HeaderJars...)
 				flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
 			case staticLibTag:
@@ -1664,7 +1665,7 @@
 			}
 		} else if dep, ok := module.(SdkLibraryDependency); ok {
 			switch tag {
-			case libTag:
+			case libTag, sdkLibTag:
 				flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
 			}
 		}
@@ -2178,7 +2179,7 @@
 	}
 
 	depTag := ctx.OtherModuleDependencyTag(depModule)
-	if depTag == libTag {
+	if IsLibDepTag(depTag) {
 		// Ok, propagate <uses-library> through non-static library dependencies.
 	} else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion {
 		// Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies.
diff --git a/java/lint_test.go b/java/lint_test.go
index 456e6ba..62450d5 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -271,7 +271,7 @@
 				"a.java",
 			],
 			min_sdk_version: "29",
-			sdk_version: "module_current",
+			sdk_version: "XXX",
 			lint: {
 				strict_updatability_linting: true,
 			},
diff --git a/java/robolectric.go b/java/robolectric.go
index 71ffdb1..7f2981f 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -23,6 +23,7 @@
 	"android/soong/android"
 	"android/soong/java/config"
 	"android/soong/tradefed"
+
 	"github.com/google/blueprint/proptools"
 )
 
@@ -166,7 +167,7 @@
 		instrumentedApp.implementationAndResourcesJar,
 	}
 
-	for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
+	handleLibDeps := func(dep android.Module) {
 		m := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
 		r.libs = append(r.libs, ctx.OtherModuleName(dep))
 		if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
@@ -174,6 +175,13 @@
 		}
 	}
 
+	for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
+		handleLibDeps(dep)
+	}
+	for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) {
+		handleLibDeps(dep)
+	}
+
 	r.combinedJar = android.PathForModuleOut(ctx, "robolectric_combined", r.outputFile.Base())
 	TransformJarsToJar(ctx, r.combinedJar, "combine jars", combinedJarJars, android.OptionalPath{},
 		false, nil, nil)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d188133..59ffff5 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2236,8 +2236,9 @@
 		Sdk_version *string
 		Libs        []string
 		Jars        []string
-		Prefer      *bool
 		Compile_dex *bool
+
+		android.UserSuppliedPrebuiltProperties
 	}{}
 	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
 	props.Sdk_version = scopeProperties.Sdk_version
@@ -2247,7 +2248,7 @@
 	props.Jars = scopeProperties.Jars
 
 	// The imports are preferred if the java_sdk_library_import is preferred.
-	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
+	props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
 
 	// The imports need to be compiled to dex if the java_sdk_library_import requests it.
 	compileDex := module.properties.Compile_dex
@@ -2261,16 +2262,18 @@
 
 func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
 	props := struct {
-		Name   *string
-		Srcs   []string
-		Prefer *bool
+		Name *string
+		Srcs []string
+
+		android.UserSuppliedPrebuiltProperties
 	}{}
 	props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
 	props.Srcs = scopeProperties.Stub_srcs
-	mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
 
 	// The stubs source is preferred if the java_sdk_library_import is preferred.
-	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
+	props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
+
+	mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
 }
 
 // Add the dependencies on the child module in the component deps mutator so that it
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 805bc22..ea7b2f7 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -875,11 +875,12 @@
 	})
 }
 
-func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
+func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer android.FixturePreparer) {
 	result := android.GroupFixturePreparers(
 		prepareForJavaTest,
 		PrepareForTestWithJavaSdkLibraryFiles,
 		FixtureWithLastReleaseApis("sdklib"),
+		preparer,
 	).RunTestWithBp(t, `
 		java_sdk_library {
 			name: "sdklib",
@@ -893,11 +894,37 @@
 
 		java_sdk_library_import {
 			name: "sdklib",
-			prefer: true,
+			`+prefer+`
 			public: {
 				jars: ["a.jar"],
+				stub_srcs: ["a.java"],
+				current_api: "current.txt",
+				removed_api: "removed.txt",
+				annotations: "annotations.zip",
 			},
 		}
+
+		java_library {
+			name: "combined",
+			static_libs: [
+				"sdklib.stubs",
+			],
+			java_resources: [
+				":sdklib.stubs.source",
+				":sdklib{.public.api.txt}",
+				":sdklib{.public.removed-api.txt}",
+				":sdklib{.public.annotations.zip}",
+			],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+
+		java_library {
+			name: "public",
+			srcs: ["a.java"],
+			libs: ["sdklib"],
+			sdk_version: "current",
+		}
 		`)
 
 	CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
@@ -913,9 +940,48 @@
 	CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
 		`dex2oatd`,
 		`prebuilt_sdklib.stubs`,
+		`prebuilt_sdklib.stubs.source`,
 		`sdklib.impl`,
 		`sdklib.xml`,
 	})
+
+	// Make sure that dependencies on child modules use the prebuilt when preferred.
+	CheckModuleDependencies(t, result.TestContext, "combined", "android_common", []string{
+		// Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib.
+		`prebuilt_sdklib`,
+		`prebuilt_sdklib`,
+		`prebuilt_sdklib`,
+		`prebuilt_sdklib.stubs`,
+		`prebuilt_sdklib.stubs.source`,
+	})
+
+	// Make sure that dependencies on sdklib that resolve to one of the child libraries use the
+	// prebuilt library.
+	public := result.ModuleForTests("public", "android_common")
+	rule := public.Output("javac/public.jar")
+	inputs := rule.Implicits.Strings()
+	expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/combined/sdklib.stubs.jar"
+	if !android.InList(expected, inputs) {
+		t.Errorf("expected %q to contain %q", inputs, expected)
+	}
+}
+
+func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
+	t.Run("prefer", func(t *testing.T) {
+		testJavaSdkLibraryImport_Preferred(t, "prefer: true,", android.NullFixturePreparer)
+	})
+
+	t.Run("use_source_config_var", func(t *testing.T) {
+		testJavaSdkLibraryImport_Preferred(t,
+			"use_source_config_var: {config_namespace: \"acme\", var_name: \"use_source\"},",
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				variables.VendorVars = map[string]map[string]string{
+					"acme": {
+						"use_source": "false",
+					},
+				}
+			}))
+	})
 }
 
 func TestJavaSdkLibraryEnforce(t *testing.T) {
diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp
index fc62813..ea5076e 100644
--- a/python/tests/dont_import_folder_of_entrypoint/Android.bp
+++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp
@@ -1,3 +1,7 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 python_test_host {
     name: "py_dont_import_folder_of_entrypoint_test",
     main: "mypkg/main.py",
diff --git a/python/tests/top_level_dirs/Android.bp b/python/tests/top_level_dirs/Android.bp
index 0b15ce7..fe13d4f 100644
--- a/python/tests/top_level_dirs/Android.bp
+++ b/python/tests/top_level_dirs/Android.bp
@@ -1,3 +1,7 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 python_test_host {
     name: "py_dont_add_top_level_dirs_test",
     main: "main.py",
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index be73d69..79ea7a1 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -15,6 +15,7 @@
         "arm64_device.go",
         "global.go",
         "lints.go",
+        "riscv64_device.go",
         "toolchain.go",
         "darwin_host.go",
         "x86_linux_bionic_host.go",
diff --git a/rust/config/riscv64_device.go b/rust/config/riscv64_device.go
new file mode 100644
index 0000000..3b41a10
--- /dev/null
+++ b/rust/config/riscv64_device.go
@@ -0,0 +1,91 @@
+// Copyright 2022 The Android Open Source Project
+//
+// 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 config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	Riscv64RustFlags            = []string{}
+	Riscv64ArchFeatureRustFlags = map[string][]string{"": {}}
+	Riscv64LinkFlags            = []string{}
+
+	Riscv64ArchVariantRustFlags = map[string][]string{}
+)
+
+func init() {
+	registerToolchainFactory(android.Android, android.Riscv64, Riscv64ToolchainFactory)
+
+	pctx.StaticVariable("Riscv64ToolchainRustFlags", strings.Join(Riscv64RustFlags, " "))
+	pctx.StaticVariable("Riscv64ToolchainLinkFlags", strings.Join(Riscv64LinkFlags, " "))
+
+	for variant, rustFlags := range Riscv64ArchVariantRustFlags {
+		pctx.StaticVariable("Riscv64"+variant+"VariantRustFlags",
+			strings.Join(rustFlags, " "))
+	}
+
+}
+
+type toolchainRiscv64 struct {
+	toolchain64Bit
+	toolchainRustFlags string
+}
+
+func (t *toolchainRiscv64) RustTriple() string {
+	return "riscv64-linux-android"
+}
+
+func (t *toolchainRiscv64) ToolchainLinkFlags() string {
+	// Prepend the lld flags from cc_config so we stay in sync with cc
+	return "${config.DeviceGlobalLinkFlags} ${cc_config.Riscv64Lldflags} ${config.Riscv64ToolchainLinkFlags}"
+}
+
+func (t *toolchainRiscv64) ToolchainRustFlags() string {
+	return t.toolchainRustFlags
+}
+
+func (t *toolchainRiscv64) RustFlags() string {
+	return "${config.Riscv64ToolchainRustFlags}"
+}
+
+func (t *toolchainRiscv64) Supported() bool {
+	return true
+}
+
+func (toolchainRiscv64) LibclangRuntimeLibraryArch() string {
+	return "riscv64"
+}
+
+func Riscv64ToolchainFactory(arch android.Arch) Toolchain {
+	archVariant := arch.ArchVariant
+
+	toolchainRustFlags := []string{
+		"${config.Riscv64ToolchainRustFlags}",
+		"${config.Riscv64" + archVariant + "VariantRustFlags}",
+	}
+
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainRustFlags = append(toolchainRustFlags, Riscv64ArchFeatureRustFlags[feature]...)
+	}
+
+	return &toolchainRiscv64{
+		toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+	}
+}
diff --git a/rust/rust.go b/rust/rust.go
index 1517e62..7342a14 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1615,7 +1615,7 @@
 		}
 	}
 
-	if depTag == procMacroDepTag {
+	if depTag == procMacroDepTag || depTag == customBindgenDepTag {
 		return false
 	}
 
diff --git a/sdk/build_release.go b/sdk/build_release.go
index ac57a32..6bb05a3 100644
--- a/sdk/build_release.go
+++ b/sdk/build_release.go
@@ -100,6 +100,7 @@
 	// Add the dessert build releases from oldest to newest.
 	buildReleaseS = initBuildRelease("S")
 	buildReleaseT = initBuildRelease("Tiramisu")
+	buildReleaseU = initBuildRelease("UpsideDownCake")
 
 	// Add the current build release which is always treated as being more recent than any other
 	// build release, including those added in tests.
diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go
index 13730cb..5bf57b5 100644
--- a/sdk/build_release_test.go
+++ b/sdk/build_release_test.go
@@ -42,7 +42,7 @@
 		android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release)
 		// Uses a wildcard in the error message to allow for additional build releases to be added to
 		// the supported set without breaking this test.
-		android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,F1,F2,current\]`, []error{err})
+		android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,UpsideDownCake,F1,F2,current\]`, []error{err})
 	})
 }
 
@@ -60,7 +60,7 @@
 	t.Run("closed range", func(t *testing.T) {
 		set, err := parseBuildReleaseSet("S-F1")
 		android.AssertDeepEquals(t, "errors", nil, err)
-		android.AssertStringEquals(t, "set", "[S,Tiramisu,F1]", set.String())
+		android.AssertStringEquals(t, "set", "[S,Tiramisu,UpsideDownCake,F1]", set.String())
 	})
 	invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String()
 	t.Run("invalid release", func(t *testing.T) {
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 3ef77c7..ac00fe6 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -381,7 +381,9 @@
 	soongBuildEnv.Set("TOP", os.Getenv("TOP"))
 	// For Bazel mixed builds.
 	soongBuildEnv.Set("BAZEL_PATH", "./tools/bazel")
-	soongBuildEnv.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
+	// Bazel's HOME var is set to an output subdirectory which doesn't exist. This
+	// prevents Bazel from file I/O in the actual user HOME directory.
+	soongBuildEnv.Set("BAZEL_HOME", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazelhome")))
 	soongBuildEnv.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
 	soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
 	soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())