Merge "Correct typo in prebuilt_etc property name."
diff --git a/bazel/properties.go b/bazel/properties.go
index d8b3a3a..870d293 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -736,6 +736,24 @@
 	return true
 }
 
+// IsNil returns true if the attribute has not been set for any configuration.
+func (lla LabelListAttribute) IsNil() bool {
+	if lla.Value.Includes != nil {
+		return false
+	}
+	return !lla.HasConfigurableValues()
+}
+
+// Exclude for the given axis, config, removes Includes in labelList from Includes and appends them
+// to Excludes. This is to special case any excludes that are not specified in a bp file but need to
+// be removed, e.g. if they could cause duplicate element failures.
+func (lla *LabelListAttribute) Exclude(axis ConfigurationAxis, config string, labelList LabelList) {
+	val := lla.SelectValue(axis, config)
+	newList := SubtractBazelLabelList(val, labelList)
+	newList.Excludes = append(newList.Excludes, labelList.Includes...)
+	lla.SetSelectValue(axis, config, newList)
+}
+
 // ResolveExcludes handles excludes across the various axes, ensuring that items are removed from
 // the base value and included in default values as appropriate.
 func (lla *LabelListAttribute) ResolveExcludes() {
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index e65a1fa..fac741c 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -65,7 +65,6 @@
 			t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
 		}
 	}
-
 }
 
 func registerCcLibraryStaticModuleTypes(ctx android.RegistrationContext) {
@@ -1395,6 +1394,54 @@
 	})
 }
 
+func TestCcLibrarystatic_SystemSharedLibUsedAsDep(t *testing.T) {
+	runCcLibraryStaticTestCase(t, bp2buildTestCase{
+		description: "cc_library_static system_shared_lib empty for linux_bionic variant",
+		blueprint: soongCcLibraryStaticPreamble +
+			simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
+cc_library_static {
+    name: "used_in_bionic_oses",
+    target: {
+        android: {
+            shared_libs: ["libc"],
+        },
+        linux_bionic: {
+            shared_libs: ["libc"],
+        },
+    },
+    include_build_directory: false,
+}
+
+cc_library_static {
+    name: "all",
+    shared_libs: ["libc"],
+    include_build_directory: false,
+}
+
+cc_library_static {
+    name: "keep_for_empty_system_shared_libs",
+    shared_libs: ["libc"],
+		system_shared_libs: [],
+    include_build_directory: false,
+}
+`,
+		expectedBazelTargets: []string{
+			makeBazelTarget("cc_library_static", "all", attrNameToString{
+				"implementation_dynamic_deps": `select({
+        "//build/bazel/platforms/os:android": [],
+        "//build/bazel/platforms/os:linux_bionic": [],
+        "//conditions:default": [":libc"],
+    })`,
+			}),
+			makeBazelTarget("cc_library_static", "keep_for_empty_system_shared_libs", attrNameToString{
+				"implementation_dynamic_deps": `[":libc"]`,
+				"system_dynamic_deps":         `[]`,
+			}),
+			makeBazelTarget("cc_library_static", "used_in_bionic_oses", attrNameToString{}),
+		},
+	})
+}
+
 func TestCcLibraryStaticProto(t *testing.T) {
 	runCcLibraryStaticTestCase(t, bp2buildTestCase{
 		blueprint: soongCcProtoPreamble + `cc_library_static {
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 8ae1a38..53b60fa 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -43,7 +43,7 @@
 	if len(errs) != 1 {
 		return false
 	}
-	if errs[0].Error() == expectedErr.Error() {
+	if strings.Contains(errs[0].Error(), expectedErr.Error()) {
 		return true
 	}
 
@@ -127,8 +127,12 @@
 	codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
 	codegenCtx.unconvertedDepMode = tc.unconvertedDepsMode
 	bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir)
-	if tc.expectedErr != nil && checkError(t, errs, tc.expectedErr) {
-		return
+	if tc.expectedErr != nil {
+		if checkError(t, errs, tc.expectedErr) {
+			return
+		} else {
+			t.Errorf("Expected error: %q, got: %q", tc.expectedErr, errs)
+		}
 	} else {
 		android.FailIfErrored(t, errs)
 	}
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 5421cca..b683472 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -1484,7 +1484,7 @@
 	ok := hasFile(relativePath+"/Android.mk", fs)
 	// some modules in the existing test cases in the androidmk_test.go do not have a valid path
 	if !ok && len(relativePath) > 0 {
-		return fmt.Errorf("Cannot find an Android.mk file at path %s", relativePath)
+		return fmt.Errorf("Cannot find an Android.mk file at path %q", relativePath)
 	}
 
 	licenseKindsPropertyName := "android_license_kinds"
@@ -1661,9 +1661,12 @@
 		// if empty
 		return "", fmt.Errorf("Cannot find the value of the %s.%s property", mod.Type, property)
 	}
+	if relativePath == "" {
+		relativePath = "."
+	}
 	_, isDir, _ := fs.Exists(relativePath)
 	if !isDir {
-		return "", fmt.Errorf("Cannot find the path %s", relativePath)
+		return "", fmt.Errorf("Cannot find the path %q", relativePath)
 	}
 	path := relativePath
 	for {
@@ -1675,7 +1678,7 @@
 	}
 	_, isDir, _ = fs.Exists(path)
 	if !isDir {
-		return "", fmt.Errorf("Cannot find the path %s", path)
+		return "", fmt.Errorf("Cannot find the path %q", path)
 	}
 	return path, nil
 }
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 21ca75f..69f5967 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -1936,7 +1936,7 @@
 			fs:   mockFs,
 			path: relativePathErr,
 			expectedErr: `
-				Cannot find an Android.mk file at path a/b/c
+				Cannot find an Android.mk file at path "a/b/c"
 			`,
 		},
 	}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index e4762a0..cc2e60e 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -531,7 +531,7 @@
 	(&linkerAttrs).convertProductVariables(ctx, productVariableProps)
 
 	(&compilerAttrs).finalize(ctx, implementationHdrs)
-	(&linkerAttrs).finalize()
+	(&linkerAttrs).finalize(ctx)
 
 	protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
 
@@ -550,13 +550,14 @@
 
 // Convenience struct to hold all attributes parsed from linker properties.
 type linkerAttributes struct {
-	deps                           bazel.LabelListAttribute
-	implementationDeps             bazel.LabelListAttribute
-	dynamicDeps                    bazel.LabelListAttribute
-	implementationDynamicDeps      bazel.LabelListAttribute
-	wholeArchiveDeps               bazel.LabelListAttribute
-	implementationWholeArchiveDeps bazel.LabelListAttribute
-	systemDynamicDeps              bazel.LabelListAttribute
+	deps                             bazel.LabelListAttribute
+	implementationDeps               bazel.LabelListAttribute
+	dynamicDeps                      bazel.LabelListAttribute
+	implementationDynamicDeps        bazel.LabelListAttribute
+	wholeArchiveDeps                 bazel.LabelListAttribute
+	implementationWholeArchiveDeps   bazel.LabelListAttribute
+	systemDynamicDeps                bazel.LabelListAttribute
+	usedSystemDynamicDepAsDynamicDep map[string]bool
 
 	linkCrt                       bazel.BoolAttribute
 	useLibcrt                     bazel.BoolAttribute
@@ -571,6 +572,10 @@
 	features                      bazel.StringListAttribute
 }
 
+var (
+	soongSystemSharedLibs = []string{"libc", "libm", "libdl"}
+)
+
 func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
 	// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
 	var axisFeatures []string
@@ -602,6 +607,17 @@
 	la.systemDynamicDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
 
 	sharedLibs := android.FirstUniqueStrings(props.Shared_libs)
+	excludeSharedLibs := props.Exclude_shared_libs
+	usedSystem := android.FilterListPred(sharedLibs, func(s string) bool {
+		return android.InList(s, soongSystemSharedLibs) && !android.InList(s, excludeSharedLibs)
+	})
+	for _, el := range usedSystem {
+		if la.usedSystemDynamicDepAsDynamicDep == nil {
+			la.usedSystemDynamicDepAsDynamicDep = map[string]bool{}
+		}
+		la.usedSystemDynamicDepAsDynamicDep[el] = true
+	}
+
 	sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, props.Exclude_shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
 	la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
 	la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
@@ -721,13 +737,25 @@
 	}
 }
 
-func (la *linkerAttributes) finalize() {
+func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) {
+	// if system dynamic deps have the default value, any use of a system dynamic library used will
+	// result in duplicate library errors for bionic OSes. Here, we explicitly exclude those libraries
+	// from bionic OSes.
+	if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsDynamicDep) > 0 {
+		toRemove := bazelLabelForSharedDeps(ctx, android.SortedStringKeys(la.usedSystemDynamicDepAsDynamicDep))
+		la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+		la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+		la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+		la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+	}
+
 	la.deps.ResolveExcludes()
 	la.implementationDeps.ResolveExcludes()
 	la.dynamicDeps.ResolveExcludes()
 	la.implementationDynamicDeps.ResolveExcludes()
 	la.wholeArchiveDeps.ResolveExcludes()
 	la.systemDynamicDeps.ForceSpecifyEmptyList = true
+
 }
 
 // Relativize a list of root-relative paths with respect to the module's
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 83de65f..377a566 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -439,6 +439,7 @@
 	// This module is host-only
 	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -665,7 +666,7 @@
 // ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
 func (p *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
 	// All prebuilt_* modules are PrebuiltEtc, but at this time, we only convert prebuilt_etc modules.
-	if ctx.ModuleType() != "prebuilt_etc" {
+	if p.installDirBase != "etc" {
 		return
 	}
 
diff --git a/rust/protobuf.go b/rust/protobuf.go
index b91fea8..9fe27c4c 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -188,6 +188,12 @@
 			lines,
 			"pub mod empty {",
 			"    pub use protobuf::well_known_types::Empty;",
+			"}",
+			"pub mod wrappers {",
+			"    pub use protobuf::well_known_types::{",
+			"        DoubleValue, FloatValue, Int64Value, UInt64Value, Int32Value, UInt32Value,",
+			"        BoolValue, StringValue, BytesValue",
+			"    };",
 			"}")
 	}
 
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 5360342..8133762 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -166,10 +166,22 @@
 	}
 
 	commonArgs = append(commonArgs, "-l", filepath.Join(config.FileListDir(), "Android.bp.list"))
+	invocationEnv := make(map[string]string)
+	debugMode := os.Getenv("SOONG_DELVE") != ""
 
-	if os.Getenv("SOONG_DELVE") != "" {
+	if debugMode {
 		commonArgs = append(commonArgs, "--delve_listen", os.Getenv("SOONG_DELVE"))
 		commonArgs = append(commonArgs, "--delve_path", shared.ResolveDelveBinary())
+		// GODEBUG=asyncpreemptoff=1 disables the preemption of goroutines. This
+		// is useful because the preemption happens by sending SIGURG to the OS
+		// thread hosting the goroutine in question and each signal results in
+		// work that needs to be done by Delve; it uses ptrace to debug the Go
+		// process and the tracer process must deal with every signal (it is not
+		// possible to selectively ignore SIGURG). This makes debugging slower,
+		// sometimes by an order of magnitude depending on luck.
+		// The original reason for adding async preemption to Go is here:
+		// https://github.com/golang/proposal/blob/master/design/24543-non-cooperative-preemption.md
+		invocationEnv["GODEBUG"] = "asyncpreemptoff=1"
 	}
 
 	allArgs := make([]string, 0, 0)
@@ -187,6 +199,12 @@
 		Outputs:     []string{output},
 		Args:        allArgs,
 		Description: description,
+		// NB: Changing the value of this environment variable will not result in a
+		// rebuild. The bootstrap Ninja file will change, but apparently Ninja does
+		// not consider changing the pool specified in a statement a change that's
+		// worth rebuilding for.
+		Console: os.Getenv("SOONG_UNBUFFERED_OUTPUT") == "1",
+		Env:     invocationEnv,
 	}
 }