Merge "Define product_available property"
diff --git a/android/Android.bp b/android/Android.bp
index 2de0ca9..7bd1450 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -16,7 +16,6 @@
         "api_levels.go",
         "arch.go",
         "bazel_handler.go",
-        "bazel_overlay.go",
         "config.go",
         "csuite_config.go",
         "defaults.go",
@@ -44,6 +43,7 @@
         "prebuilt.go",
         "prebuilt_build_tool.go",
         "proto.go",
+        "queryview.go",
         "register.go",
         "rule_builder.go",
         "sandbox.go",
diff --git a/android/bazel_overlay.go b/android/bazel_overlay.go
deleted file mode 100644
index a034282..0000000
--- a/android/bazel_overlay.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2020 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-import (
-	"fmt"
-	"os"
-	"strings"
-
-	"github.com/google/blueprint"
-)
-
-// The Bazel Overlay singleton is responsible for generating the Ninja actions
-// for calling the soong_build primary builder in the main build.ninja file.
-func init() {
-	RegisterSingletonType("bazel_overlay", BazelOverlaySingleton)
-}
-
-func BazelOverlaySingleton() Singleton {
-	return &bazelOverlaySingleton{}
-}
-
-type bazelOverlaySingleton struct{}
-
-func (c *bazelOverlaySingleton) GenerateBuildActions(ctx SingletonContext) {
-	// Create a build and rule statement, using the Bazel overlay's WORKSPACE
-	// file as the output file marker.
-	var deps Paths
-	moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
-	deps = append(deps, moduleListFilePath)
-	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
-
-	bazelOverlayDirectory := PathForOutput(ctx, "bazel_overlay")
-	bazelOverlayWorkspaceFile := bazelOverlayDirectory.Join(ctx, "WORKSPACE")
-	primaryBuilder := primaryBuilderPath(ctx)
-	bazelOverlay := ctx.Rule(pctx, "bazelOverlay",
-		blueprint.RuleParams{
-			Command: fmt.Sprintf(
-				"rm -rf ${outDir}/* && %s --bazel_overlay_dir ${outDir} %s && echo WORKSPACE: `cat %s` > ${outDir}/.overlay-depfile.d",
-				primaryBuilder.String(),
-				strings.Join(os.Args[1:], " "),
-				moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
-			),
-			CommandDeps: []string{primaryBuilder.String()},
-			Description: fmt.Sprintf(
-				"Creating the Bazel overlay workspace with %s at $outDir",
-				primaryBuilder.Base()),
-			Deps:    blueprint.DepsGCC,
-			Depfile: "${outDir}/.overlay-depfile.d",
-		},
-		"outDir")
-
-	ctx.Build(pctx, BuildParams{
-		Rule:   bazelOverlay,
-		Output: bazelOverlayWorkspaceFile,
-		Inputs: deps,
-		Args: map[string]string{
-			"outDir": bazelOverlayDirectory.String(),
-		},
-	})
-
-	// Add a phony target for building the bazel overlay
-	ctx.Phony("bazel_overlay", bazelOverlayWorkspaceFile)
-}
diff --git a/android/env.go b/android/env.go
index c7c96d5..c2a09aa 100644
--- a/android/env.go
+++ b/android/env.go
@@ -41,7 +41,10 @@
 	// access originalEnv with dependencies.  Store the value where soong_build can find it, it will manually
 	// ensure the dependencies are created.
 	soongDelveListen = os.Getenv("SOONG_DELVE")
-	soongDelvePath, _ = exec.LookPath("dlv")
+	soongDelvePath = os.Getenv("SOONG_DELVE_PATH")
+	if soongDelvePath == "" {
+		soongDelvePath, _ = exec.LookPath("dlv")
+	}
 
 	originalEnv = make(map[string]string)
 	soongDelveEnv = []string{}
@@ -49,7 +52,7 @@
 		idx := strings.IndexRune(env, '=')
 		if idx != -1 {
 			originalEnv[env[:idx]] = env[idx+1:]
-			if env[:idx] != "SOONG_DELVE" {
+			if env[:idx] != "SOONG_DELVE" && env[:idx] != "SOONG_DELVE_PATH" {
 				soongDelveEnv = append(soongDelveEnv, env)
 			}
 		}
diff --git a/android/queryview.go b/android/queryview.go
new file mode 100644
index 0000000..dff00f6
--- /dev/null
+++ b/android/queryview.go
@@ -0,0 +1,76 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/google/blueprint"
+)
+
+// The Bazel QueryView singleton is responsible for generating the Ninja actions
+// for calling the soong_build primary builder in the main build.ninja file.
+func init() {
+	RegisterSingletonType("bazel_queryView", BazelQueryViewSingleton)
+}
+
+func BazelQueryViewSingleton() Singleton {
+	return &bazelQueryViewSingleton{}
+}
+
+type bazelQueryViewSingleton struct{}
+
+func (c *bazelQueryViewSingleton) GenerateBuildActions(ctx SingletonContext) {
+	// Create a build and rule statement, using the Bazel QueryView's WORKSPACE
+	// file as the output file marker.
+	var deps Paths
+	moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
+	deps = append(deps, moduleListFilePath)
+	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
+
+	bazelQueryViewDirectory := PathForOutput(ctx, "queryview")
+	bazelQueryViewWorkspaceFile := bazelQueryViewDirectory.Join(ctx, "WORKSPACE")
+	primaryBuilder := primaryBuilderPath(ctx)
+	bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
+		blueprint.RuleParams{
+			Command: fmt.Sprintf(
+				"rm -rf ${outDir}/* && %s --bazel_queryview_dir ${outDir} %s && echo WORKSPACE: `cat %s` > ${outDir}/.queryview-depfile.d",
+				primaryBuilder.String(),
+				strings.Join(os.Args[1:], " "),
+				moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+			),
+			CommandDeps: []string{primaryBuilder.String()},
+			Description: fmt.Sprintf(
+				"Creating the Bazel QueryView workspace with %s at $outDir",
+				primaryBuilder.Base()),
+			Deps:    blueprint.DepsGCC,
+			Depfile: "${outDir}/.queryview-depfile.d",
+		},
+		"outDir")
+
+	ctx.Build(pctx, BuildParams{
+		Rule:   bazelQueryView,
+		Output: bazelQueryViewWorkspaceFile,
+		Inputs: deps,
+		Args: map[string]string{
+			"outDir": bazelQueryViewDirectory.String(),
+		},
+	})
+
+	// Add a phony target for building the Bazel QueryView
+	ctx.Phony("queryview", bazelQueryViewWorkspaceFile)
+}
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 8c70a56..5b8563d 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -172,6 +172,7 @@
 framework-sdkextensions(minSdkVersion:30)
 framework-sdkextensions(minSdkVersion:current)
 framework-statsd(minSdkVersion:current)
+framework-tethering(minSdkVersion:30)
 framework-tethering(minSdkVersion:current)
 gemmlowp_headers(minSdkVersion:(no version))
 GoogleCellBroadcastApp(minSdkVersion:29)
@@ -183,6 +184,7 @@
 i18n.module.public.api.stubs(minSdkVersion:(no version))
 iconloader(minSdkVersion:21)
 ike-internals(minSdkVersion:current)
+InProcessTethering(minSdkVersion:30)
 InProcessTethering(minSdkVersion:current)
 ipmemorystore-aidl-interfaces-java(minSdkVersion:29)
 ipmemorystore-aidl-interfaces-unstable-java(minSdkVersion:29)
@@ -390,6 +392,7 @@
 libstatssocket_headers(minSdkVersion:29)
 libsystem_headers(minSdkVersion:apex_inherit)
 libsysutils(minSdkVersion:apex_inherit)
+libtetherutilsjni(minSdkVersion:30)
 libtetherutilsjni(minSdkVersion:current)
 libtextclassifier(minSdkVersion:(no version))
 libtextclassifier-java(minSdkVersion:current)
@@ -540,7 +543,9 @@
 statsd-aidl-ndk_platform(minSdkVersion:(no version))
 statsprotos(minSdkVersion:29)
 tensorflow_headers(minSdkVersion:(no version))
+Tethering(minSdkVersion:30)
 Tethering(minSdkVersion:current)
+TetheringApiCurrentLib(minSdkVersion:30)
 TetheringApiCurrentLib(minSdkVersion:current)
 TetheringGoogle(minSdkVersion:current)
 textclassifier-statsd(minSdkVersion:current)
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index bb86717..c0320eb 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -53,7 +53,7 @@
 	// VNDK snapshot version.
 	Version *string
 
-	// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
+	// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
 	Target_arch *string
 
 	// If the prebuilt snapshot lib is built with 32 bit binder, this must be set to true.
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index 4ebbe68..680c00a 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -26,10 +26,10 @@
     srcs: [
         "main.go",
         "writedocs.go",
-        "bazel_overlay.go",
+        "queryview.go",
     ],
     testSrcs: [
-        "bazel_overlay_test.go",
+        "queryview_test.go",
     ],
     primaryBuilder: true,
 }
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 7ae1c37..9d7dddd 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -26,13 +26,13 @@
 )
 
 var (
-	docFile         string
-	bazelOverlayDir string
+	docFile           string
+	bazelQueryViewDir string
 )
 
 func init() {
 	flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
-	flag.StringVar(&bazelOverlayDir, "bazel_overlay_dir", "", "path to the bazel overlay directory")
+	flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory")
 }
 
 func newNameResolver(config android.Config) *android.NameResolver {
@@ -113,8 +113,8 @@
 		ctx = newContext(srcDir, configuration)
 		bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
 	}
-	if bazelOverlayDir != "" {
-		if err := createBazelOverlay(ctx, bazelOverlayDir); err != nil {
+	if bazelQueryViewDir != "" {
+		if err := createBazelQueryView(ctx, bazelQueryViewDir); err != nil {
 			fmt.Fprintf(os.Stderr, "%s", err)
 			os.Exit(1)
 		}
@@ -140,7 +140,7 @@
 }
 
 func shouldPrepareBuildActions() bool {
-	// If we're writing soong_docs or bazel_overlay, don't write build.ninja or
+	// If we're writing soong_docs or queryview, don't write build.ninja or
 	// collect metrics.
-	return docFile == "" && bazelOverlayDir == ""
+	return docFile == "" && bazelQueryViewDir == ""
 }
diff --git a/cmd/soong_build/bazel_overlay.go b/cmd/soong_build/queryview.go
similarity index 94%
rename from cmd/soong_build/bazel_overlay.go
rename to cmd/soong_build/queryview.go
index fc1b492..27856b5 100644
--- a/cmd/soong_build/bazel_overlay.go
+++ b/cmd/soong_build/queryview.go
@@ -31,7 +31,7 @@
 const (
 	// The default `load` preamble for every generated BUILD file.
 	soongModuleLoad = `package(default_visibility = ["//visibility:public"])
-load("//build/bazel/overlay_rules:soong_module.bzl", "soong_module")
+load("//build/bazel/queryview_rules:soong_module.bzl", "soong_module")
 
 `
 
@@ -62,7 +62,7 @@
 	soongModuleBzl = `
 %s
 
-load("//build/bazel/overlay_rules:providers.bzl", "SoongModuleInfo")
+load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
 
 def _generic_soong_module_impl(ctx):
     return [
@@ -396,7 +396,7 @@
 
 	ruleShims := map[string]RuleShim{}
 	for _, pkg := range packages {
-		content := "load(\"//build/bazel/overlay_rules:providers.bzl\", \"SoongModuleInfo\")\n"
+		content := "load(\"//build/bazel/queryview_rules:providers.bzl\", \"SoongModuleInfo\")\n"
 
 		bzlFileName := strings.ReplaceAll(pkg.Path, "android/soong/", "")
 		bzlFileName = strings.ReplaceAll(bzlFileName, ".", "_")
@@ -441,10 +441,10 @@
 	return ruleShims, nil
 }
 
-func createBazelOverlay(ctx *android.Context, bazelOverlayDir string) error {
+func createBazelQueryView(ctx *android.Context, bazelQueryViewDir string) error {
 	blueprintCtx := ctx.Context
 	blueprintCtx.VisitAllModules(func(module blueprint.Module) {
-		buildFile, err := buildFileForModule(blueprintCtx, module)
+		buildFile, err := buildFileForModule(blueprintCtx, module, bazelQueryViewDir)
 		if err != nil {
 			panic(err)
 		}
@@ -455,12 +455,12 @@
 	var err error
 
 	// Write top level files: WORKSPACE and BUILD. These files are empty.
-	if err = writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil {
+	if err = writeReadOnlyFile(bazelQueryViewDir, "WORKSPACE", ""); err != nil {
 		return err
 	}
 
 	// Used to denote that the top level directory is a package.
-	if err = writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil {
+	if err = writeReadOnlyFile(bazelQueryViewDir, "BUILD", ""); err != nil {
 		return err
 	}
 
@@ -474,7 +474,7 @@
 	}
 
 	// Write .bzl Starlark files into the bazel_rules top level directory (provider and rule definitions)
-	bazelRulesDir := bazelOverlayDir + "/build/bazel/overlay_rules"
+	bazelRulesDir := bazelQueryViewDir + "/build/bazel/queryview_rules"
 	if err = writeReadOnlyFile(bazelRulesDir, "BUILD", ""); err != nil {
 		return err
 	}
@@ -497,7 +497,7 @@
 	var loadStmts string
 	var moduleRuleMap string
 	for bzlFileName, ruleShim := range bzlLoads {
-		loadStmt := "load(\"//build/bazel/overlay_rules:"
+		loadStmt := "load(\"//build/bazel/queryview_rules:"
 		loadStmt += bzlFileName
 		loadStmt += ".bzl\""
 		for _, rule := range ruleShim.rules {
@@ -563,9 +563,10 @@
 		attributes)
 }
 
-func buildFileForModule(ctx *blueprint.Context, module blueprint.Module) (*os.File, error) {
+func buildFileForModule(
+	ctx *blueprint.Context, module blueprint.Module, bazelQueryViewDir string) (*os.File, error) {
 	// Create nested directories for the BUILD file
-	dirPath := filepath.Join(bazelOverlayDir, packagePath(ctx, module))
+	dirPath := filepath.Join(bazelQueryViewDir, packagePath(ctx, module))
 	createDirectoryIfNonexistent(dirPath)
 	// Open the file for appending, and create it if it doesn't exist
 	f, err := os.OpenFile(
@@ -594,7 +595,7 @@
 	}
 }
 
-// The overlay directory should be read-only, sufficient for bazel query. The files
+// The QueryView directory should be read-only, sufficient for bazel query. The files
 // are not intended to be edited by end users.
 func writeReadOnlyFile(dir string, baseName string, content string) error {
 	createDirectoryIfNonexistent(dir)
diff --git a/cmd/soong_build/bazel_overlay_test.go b/cmd/soong_build/queryview_test.go
similarity index 96%
rename from cmd/soong_build/bazel_overlay_test.go
rename to cmd/soong_build/queryview_test.go
index 548888e..675b532 100644
--- a/cmd/soong_build/bazel_overlay_test.go
+++ b/cmd/soong_build/queryview_test.go
@@ -28,7 +28,7 @@
 
 func setUp() {
 	var err error
-	buildDir, err = ioutil.TempDir("", "bazel_overlay_test")
+	buildDir, err = ioutil.TempDir("", "bazel_queryview_test")
 	if err != nil {
 		panic(err)
 	}
@@ -63,7 +63,7 @@
 	return module
 }
 
-func TestGenerateBazelOverlayFromBlueprint(t *testing.T) {
+func TestGenerateBazelQueryViewFromBlueprint(t *testing.T) {
 	testCases := []struct {
 		bp                  string
 		expectedBazelTarget string
@@ -362,7 +362,7 @@
 		}
 	}
 
-	expectedBzl := `load("//build/bazel/overlay_rules:providers.bzl", "SoongModuleInfo")
+	expectedBzl := `load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
 
 def _foo_binary_impl(ctx):
     return [SoongModuleInfo()]
@@ -440,7 +440,7 @@
 	}
 	actualSoongModuleBzl := generateSoongModuleBzl(ruleShims)
 
-	expectedLoad := "load(\"//build/bazel/overlay_rules:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")"
+	expectedLoad := "load(\"//build/bazel/queryview_rules:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")"
 	expectedRuleMap := `soong_module_rule_map = {
     "foo_binary": foo_binary,
     "foo_library": foo_library,
diff --git a/python/python.go b/python/python.go
index 479c729..945e264 100644
--- a/python/python.go
+++ b/python/python.go
@@ -101,6 +101,13 @@
 	// this property name is hidden from users' perspectives, and soong will populate it during
 	// runtime.
 	Actual_version string `blueprint:"mutated"`
+
+	// true, if the module is required to be built with actual_version.
+	Enabled *bool `blueprint:"mutated"`
+
+	// true, if the binary is required to be built with embedded launcher.
+	// TODO(nanzhang): Remove this flag when embedded Python3 is supported later.
+	Embedded_launcher *bool `blueprint:"mutated"`
 }
 
 type pathMapping struct {
@@ -228,15 +235,18 @@
 	return func(mctx android.BottomUpMutatorContext) {
 		if base, ok := mctx.Module().(*Module); ok {
 			versionNames := []string{}
+			versionProps := []VersionProperties{}
 			// PY3 is first so that we alias the PY3 variant rather than PY2 if both
 			// are available
 			if !(base.properties.Version.Py3.Enabled != nil &&
 				*(base.properties.Version.Py3.Enabled) == false) {
 				versionNames = append(versionNames, pyVersion3)
+				versionProps = append(versionProps, base.properties.Version.Py3)
 			}
 			if base.properties.Version.Py2.Enabled != nil &&
 				*(base.properties.Version.Py2.Enabled) == true {
 				versionNames = append(versionNames, pyVersion2)
+				versionProps = append(versionProps, base.properties.Version.Py2)
 			}
 			modules := mctx.CreateVariations(versionNames...)
 			if len(versionNames) > 0 {
@@ -245,6 +255,11 @@
 			for i, v := range versionNames {
 				// set the actual version for Python module.
 				modules[i].(*Module).properties.Actual_version = v
+				// append versioned properties for the Python module
+				err := proptools.AppendMatchingProperties([]interface{}{&modules[i].(*Module).properties}, &versionProps[i], nil)
+				if err != nil {
+					panic(err)
+				}
 			}
 		}
 	}
@@ -270,15 +285,8 @@
 	}
 }
 
-func (p *Module) isEmbeddedLauncherEnabled(actual_version string) bool {
-	switch actual_version {
-	case pyVersion2:
-		return Bool(p.properties.Version.Py2.Embedded_launcher)
-	case pyVersion3:
-		return Bool(p.properties.Version.Py3.Embedded_launcher)
-	}
-
-	return false
+func (p *Module) isEmbeddedLauncherEnabled() bool {
+	return Bool(p.properties.Embedded_launcher)
 }
 
 func hasSrcExt(srcs []string, ext string) bool {
@@ -292,18 +300,7 @@
 }
 
 func (p *Module) hasSrcExt(ctx android.BottomUpMutatorContext, ext string) bool {
-	if hasSrcExt(p.properties.Srcs, protoExt) {
-		return true
-	}
-	switch p.properties.Actual_version {
-	case pyVersion2:
-		return hasSrcExt(p.properties.Version.Py2.Srcs, protoExt)
-	case pyVersion3:
-		return hasSrcExt(p.properties.Version.Py3.Srcs, protoExt)
-	default:
-		panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
-			p.properties.Actual_version, ctx.ModuleName()))
-	}
+	return hasSrcExt(p.properties.Srcs, protoExt)
 }
 
 func (p *Module) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -312,13 +309,12 @@
 	if p.hasSrcExt(ctx, protoExt) && p.Name() != "libprotobuf-python" {
 		ctx.AddVariationDependencies(nil, pythonLibTag, "libprotobuf-python")
 	}
+	ctx.AddVariationDependencies(nil, pythonLibTag, android.LastUniqueStrings(p.properties.Libs)...)
+
 	switch p.properties.Actual_version {
 	case pyVersion2:
-		ctx.AddVariationDependencies(nil, pythonLibTag,
-			uniqueLibs(ctx, p.properties.Libs, "version.py2.libs",
-				p.properties.Version.Py2.Libs)...)
 
-		if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled(pyVersion2) {
+		if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled() {
 			ctx.AddVariationDependencies(nil, pythonLibTag, "py2-stdlib")
 
 			launcherModule := "py2-launcher"
@@ -340,11 +336,8 @@
 		}
 
 	case pyVersion3:
-		ctx.AddVariationDependencies(nil, pythonLibTag,
-			uniqueLibs(ctx, p.properties.Libs, "version.py3.libs",
-				p.properties.Version.Py3.Libs)...)
 
-		if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled(pyVersion3) {
+		if p.bootstrapper != nil && p.isEmbeddedLauncherEnabled() {
 			ctx.AddVariationDependencies(nil, pythonLibTag, "py3-stdlib")
 
 			launcherModule := "py3-launcher"
@@ -375,34 +368,6 @@
 	}
 }
 
-// check "libs" duplicates from current module dependencies.
-func uniqueLibs(ctx android.BottomUpMutatorContext,
-	commonLibs []string, versionProp string, versionLibs []string) []string {
-	set := make(map[string]string)
-	ret := []string{}
-
-	// deps from "libs" property.
-	for _, l := range commonLibs {
-		if _, found := set[l]; found {
-			ctx.PropertyErrorf("libs", "%q has duplicates within libs.", l)
-		} else {
-			set[l] = "libs"
-			ret = append(ret, l)
-		}
-	}
-	// deps from "version.pyX.libs" property.
-	for _, l := range versionLibs {
-		if _, found := set[l]; found {
-			ctx.PropertyErrorf(versionProp, "%q has duplicates within %q.", set[l])
-		} else {
-			set[l] = versionProp
-			ret = append(ret, l)
-		}
-	}
-
-	return ret
-}
-
 func (p *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	p.GeneratePythonBuildActions(ctx)
 
@@ -410,11 +375,7 @@
 	if p.bootstrapper != nil {
 		p.walkTransitiveDeps(ctx)
 		embeddedLauncher := false
-		if p.properties.Actual_version == pyVersion2 {
-			embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion2)
-		} else {
-			embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion3)
-		}
+		embeddedLauncher = p.isEmbeddedLauncherEnabled()
 		p.installSource = p.bootstrapper.bootstrap(ctx, p.properties.Actual_version,
 			embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips)
 	}
@@ -439,17 +400,6 @@
 	// expand python files from "srcs" property.
 	srcs := p.properties.Srcs
 	exclude_srcs := p.properties.Exclude_srcs
-	switch p.properties.Actual_version {
-	case pyVersion2:
-		srcs = append(srcs, p.properties.Version.Py2.Srcs...)
-		exclude_srcs = append(exclude_srcs, p.properties.Version.Py2.Exclude_srcs...)
-	case pyVersion3:
-		srcs = append(srcs, p.properties.Version.Py3.Srcs...)
-		exclude_srcs = append(exclude_srcs, p.properties.Version.Py3.Exclude_srcs...)
-	default:
-		panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
-			p.properties.Actual_version, ctx.ModuleName()))
-	}
 	expandedSrcs := android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs)
 	requiresSrcs := true
 	if p.bootstrapper != nil && !p.bootstrapper.autorun() {
diff --git a/python/python_test.go b/python/python_test.go
index 23db24e..10b565a 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -395,10 +395,11 @@
 
 	if !reflect.DeepEqual(actualPyRunfiles, expectedPyRunfiles) {
 		testErrs = append(testErrs, errors.New(fmt.Sprintf(
-			`binary "%s" variant "%s" has unexpected pyRunfiles: %q!`,
+			`binary "%s" variant "%s" has unexpected pyRunfiles: %q! (expected: %q)`,
 			base.Name(),
 			base.properties.Actual_version,
-			actualPyRunfiles)))
+			actualPyRunfiles,
+			expectedPyRunfiles)))
 	}
 
 	if base.srcsZip.String() != strings.Replace(expectedSrcsZip, "@prefix@", buildDir, 1) {
diff --git a/rust/builder.go b/rust/builder.go
index 654b1e6..3e082dc 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -22,6 +22,7 @@
 
 	"android/soong/android"
 	"android/soong/cc"
+	"android/soong/rust/config"
 )
 
 var (
@@ -138,6 +139,13 @@
 	crate_name := ctx.RustModule().CrateName()
 	targetTriple := ctx.toolchain().RustTriple()
 
+	// libstd requires a specific environment variable to be set. This is
+	// not officially documented and may be removed in the future. See
+	// https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
+	if crate_name == "std" {
+		envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.RustModule().Arch().ArchType])
+	}
+
 	inputs = append(inputs, main)
 
 	// Collect rustc flags
diff --git a/rust/config/global.go b/rust/config/global.go
index 71c4240..6e268a0 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.46.0"
+	RustDefaultVersion = "1.47.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2018"
 	Stdlibs            = []string{
@@ -32,6 +32,15 @@
 		"libtest",
 	}
 
+	// Mapping between Soong internal arch types and std::env constants.
+	// Required as Rust uses aarch64 when Soong uses arm64.
+	StdEnvArch = map[android.ArchType]string{
+		android.Arm:    "arm",
+		android.Arm64:  "aarch64",
+		android.X86:    "x86",
+		android.X86_64: "x86_64",
+	}
+
 	GlobalRustFlags = []string{
 		"--remap-path-prefix $$(pwd)=",
 		"-C codegen-units=1",
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 28a4597..ca40154 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -55,17 +55,17 @@
 
 func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
 	var protoFlags android.ProtoFlags
-	var pluginPath android.Path
+	var pluginPaths android.Paths
 
 	protoFlags.OutTypeFlag = "--rust_out"
 	outDir := android.PathForModuleOut(ctx)
 
-	pluginPath, protoFlags = proto.setupPlugin(ctx, protoFlags, outDir)
+	pluginPaths, protoFlags = proto.setupPlugin(ctx, protoFlags, outDir)
 
 	protoFlags.Flags = append(protoFlags.Flags, defaultProtobufFlags...)
 	protoFlags.Flags = append(protoFlags.Flags, proto.Properties.Proto_flags...)
 
-	protoFlags.Deps = append(protoFlags.Deps, pluginPath)
+	protoFlags.Deps = append(protoFlags.Deps, pluginPaths...)
 
 	protoFile := android.OptionalPathForModuleSrc(ctx, proto.Properties.Proto)
 	if !protoFile.Valid() {
@@ -90,21 +90,25 @@
 	return modFile
 }
 
-func (proto *protobufDecorator) setupPlugin(ctx ModuleContext, protoFlags android.ProtoFlags, outDir android.ModuleOutPath) (android.Path, android.ProtoFlags) {
-	var pluginPath android.Path
+func (proto *protobufDecorator) setupPlugin(ctx ModuleContext, protoFlags android.ProtoFlags, outDir android.ModuleOutPath) (android.Paths, android.ProtoFlags) {
+	pluginPaths := []android.Path{}
 
 	if proto.plugin == Protobuf {
-		pluginPath = ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+		pluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+		pluginPaths = append(pluginPaths, pluginPath)
 		protoFlags.Flags = append(protoFlags.Flags, "--plugin="+pluginPath.String())
 	} else if proto.plugin == Grpc {
-		pluginPath = ctx.Config().HostToolPath(ctx, "grpc_rust_plugin")
+		grpcPath := ctx.Config().HostToolPath(ctx, "grpc_rust_plugin")
+		protobufPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+		pluginPaths = append(pluginPaths, grpcPath, protobufPath)
 		protoFlags.Flags = append(protoFlags.Flags, "--grpc_out="+outDir.String())
-		protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-grpc="+pluginPath.String())
+		protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-grpc="+grpcPath.String())
+		protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-rust="+protobufPath.String())
 	} else {
 		ctx.ModuleErrorf("Unknown protobuf plugin type requested")
 	}
 
-	return pluginPath, protoFlags
+	return pluginPaths, protoFlags
 }
 
 func (proto *protobufDecorator) SourceProviderProps() []interface{} {