Merge "Generate a ndk_sysroot target in bp2build" into main
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index deb44a2..1f678a0 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -373,6 +373,7 @@
 		"system/core/libprocessgroup/cgrouprc":                   Bp2BuildDefaultTrue,
 		"system/core/libprocessgroup/cgrouprc_format":            Bp2BuildDefaultTrue,
 		"system/core/libsparse":                                  Bp2BuildDefaultTrueRecursively,
+		"system/core/libstats/expresslog":                        Bp2BuildDefaultTrueRecursively,
 		"system/core/libsuspend":                                 Bp2BuildDefaultTrue,
 		"system/core/libsystem":                                  Bp2BuildDefaultTrueRecursively,
 		"system/core/libsysutils":                                Bp2BuildDefaultTrueRecursively,
diff --git a/bp2build/rust_protobuf_conversion_test.go b/bp2build/rust_protobuf_conversion_test.go
index cf256aa..bd4f54b 100644
--- a/bp2build/rust_protobuf_conversion_test.go
+++ b/bp2build/rust_protobuf_conversion_test.go
@@ -27,7 +27,7 @@
 
 func registerRustProtobufModuleTypes(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("rust_protobuf_host", rust.RustProtobufHostFactory)
-
+	ctx.RegisterModuleType("rust_protobuf", rust.RustProtobufHostFactory)
 }
 
 func TestRustProtobufHostTestCase(t *testing.T) {
@@ -58,3 +58,32 @@
 	},
 	)
 }
+
+func TestRustProtobufTestCase(t *testing.T) {
+	runRustProtobufTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_protobuf {
+	name: "libfoo",
+	crate_name: "foo",
+	protos: ["src/foo.proto"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			makeBazelTargetHostOrDevice("proto_library", "libfoo_proto", AttrNameToString{
+				"srcs": `["src/foo.proto"]`,
+			}, android.HostSupported),
+			makeBazelTargetHostOrDevice("rust_proto_library", "libfoo", AttrNameToString{
+				"crate_name": `"foo"`,
+				"deps":       `[":libfoo_proto"]`,
+			}, android.HostSupported),
+		},
+	},
+	)
+}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 9ea337b..e8e930e 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -98,6 +98,11 @@
 			if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(scs) {
 				return false
 			}
+			// cfi and hwasan cannot be enabled at the same time.
+			// Skip variants that have both cfi and hwasan enabled.
+			if sanitizable.IsSanitizerEnabled(cfi) && sanitizable.IsSanitizerEnabled(Hwasan) {
+				return false
+			}
 			// cfi and hwasan also export both variants. But for static, we capture both.
 			// This is because cfi static libraries can't be linked from non-cfi modules,
 			// and vice versa.
diff --git a/java/java.go b/java/java.go
index fbad4f3..bf692be 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1667,11 +1667,6 @@
 	// This is a list of Soong modules
 	Api_contributions []string
 
-	// list of api.txt files relative to this directory that contribute to the
-	// API surface.
-	// This is a list of relative paths
-	Api_files []string `android:"path"`
-
 	// List of flags to be passed to the javac compiler to generate jar file
 	Javacflags []string
 
@@ -1819,37 +1814,22 @@
 	}
 }
 
-// API signature file names sorted from
-// the narrowest api scope to the widest api scope
-var scopeOrderedSourceFileNames = allApiScopes.Strings(
-	func(s *apiScope) string { return s.apiFilePrefix + "current.txt" })
+// Map where key is the api scope name and value is the int value
+// representing the order of the api scope, narrowest to the widest
+var scopeOrderMap = allApiScopes.MapToIndex(
+	func(s *apiScope) string { return s.name })
 
-func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo, apiFiles android.Paths) android.Paths {
-	var sortedSrcFiles android.Paths
-
-	for i, apiScope := range allApiScopes {
-		for _, srcFileInfo := range srcFilesInfo {
-			if srcFileInfo.ApiFile.Base() == scopeOrderedSourceFileNames[i] || srcFileInfo.ApiSurface == apiScope.name {
-				sortedSrcFiles = append(sortedSrcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
-			}
-		}
-		// TODO: b/300964421 - Remove when api_files property is removed
-		for _, apiFileName := range apiFiles {
-			if apiFileName.Base() == scopeOrderedSourceFileNames[i] {
-				sortedSrcFiles = append(sortedSrcFiles, apiFileName)
-			}
+func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {
+	for _, srcFileInfo := range srcFilesInfo {
+		if srcFileInfo.ApiSurface == "" {
+			ctx.ModuleErrorf("Api surface not defined for the associated api file %s", srcFileInfo.ApiFile)
 		}
 	}
+	sort.Slice(srcFilesInfo, func(i, j int) bool {
+		return scopeOrderMap[srcFilesInfo[i].ApiSurface] < scopeOrderMap[srcFilesInfo[j].ApiSurface]
+	})
 
-	if len(srcFilesInfo)+len(apiFiles) != len(sortedSrcFiles) {
-		var srcFiles android.Paths
-		for _, srcFileInfo := range srcFilesInfo {
-			srcFiles = append(srcFiles, srcFileInfo.ApiFile)
-		}
-		ctx.ModuleErrorf("Unrecognizable source file found within %s", append(srcFiles, apiFiles...))
-	}
-
-	return sortedSrcFiles
+	return srcFilesInfo
 }
 
 func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1892,16 +1872,12 @@
 		}
 	})
 
-	// Add the api_files inputs
-	// These are api files in the module subdirectory, which are not provided by
-	// java_api_contribution but provided directly as module property.
-	var apiFiles android.Paths
-	for _, api := range al.properties.Api_files {
-		apiFiles = append(apiFiles, android.PathForModuleSrc(ctx, api))
+	srcFilesInfo = al.sortApiFilesByApiScope(ctx, srcFilesInfo)
+	var srcFiles android.Paths
+	for _, srcFileInfo := range srcFilesInfo {
+		srcFiles = append(srcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
 	}
 
-	srcFiles := al.sortApiFilesByApiScope(ctx, srcFilesInfo, apiFiles)
-
 	if srcFiles == nil && !ctx.Config().AllowMissingDependencies() {
 		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
 	}
diff --git a/java/java_test.go b/java/java_test.go
index 2ee05ec..b555a95 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1885,7 +1885,6 @@
 			name: "bar2",
 			api_surface: "system",
 			api_contributions: ["foo1", "foo2"],
-			api_files: ["api1/current.txt", "api2/current.txt"]
 		}
 		`,
 		map[string][]byte{
@@ -1903,7 +1902,7 @@
 		},
 		{
 			moduleName:         "bar2",
-			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "api1/current.txt", "api2/current.txt"},
+			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
 		},
 	}
 	for _, c := range testcases {
@@ -1975,7 +1974,6 @@
 			api_surface: "system",
 			defaults:["baz1", "baz2"],
 			api_contributions: ["foo4"],
-			api_files: ["api1/current.txt", "api2/current.txt"]
 		}
 		`,
 		map[string][]byte{
@@ -2000,7 +1998,7 @@
 		{
 			moduleName: "bar3",
 			// API text files need to be sorted from the narrower api scope to the wider api scope
-			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "api1/current.txt", "api2/current.txt", "c/system-current.txt", "d/system-current.txt"},
+			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "c/system-current.txt", "d/system-current.txt"},
 		},
 	}
 	for _, c := range testcases {
@@ -2265,29 +2263,6 @@
 	android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar")
 }
 
-func TestJavaApiLibraryFilegroupInput(t *testing.T) {
-	ctx, _ := testJavaWithFS(t, `
-	    filegroup {
-			name: "default_current.txt",
-			srcs: ["current.txt"],
-		}
-
-		java_api_library {
-			name: "foo",
-			api_files: [":default_current.txt"],
-		}
-		`,
-		map[string][]byte{
-			"current.txt": nil,
-		})
-
-	m := ctx.ModuleForTests("foo", "android_common")
-	outputs := fmt.Sprint(m.AllOutputs())
-	if !strings.Contains(outputs, "foo/foo.jar") {
-		t.Errorf("Module output does not contain expected jar %s", "foo/foo.jar")
-	}
-}
-
 func TestTradefedOptions(t *testing.T) {
 	result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
 java_test_host {
@@ -2423,3 +2398,30 @@
 	sourceFilesFlag := "--source-files current.txt"
 	android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
 }
+
+func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_api_library {
+			name: "foo",
+			api_contributions: [
+				"system-server-api-stubs-docs-non-updatable.api.contribution",
+				"test-api-stubs-docs-non-updatable.api.contribution",
+				"system-api-stubs-docs-non-updatable.api.contribution",
+				"module-lib-api-stubs-docs-non-updatable.api.contribution",
+				"api-stubs-docs-non-updatable.api.contribution",
+			],
+		}
+	`)
+	m := ctx.ModuleForTests("foo", "android_common")
+	manifest := m.Output("metalava.sbox.textproto")
+	sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+	manifestCommand := sboxProto.Commands[0].GetCommand()
+
+	// Api files are sorted from the narrowest api scope to the widest api scope.
+	// test api and module lib api surface do not have subset/superset relationship,
+	// but they will never be passed as inputs at the same time.
+	sourceFilesFlag := "--source-files default/java/api/current.txt " +
+		"default/java/api/system-current.txt default/java/api/test-current.txt " +
+		"default/java/api/module-lib-current.txt default/java/api/system-server-current.txt"
+	android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag)
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 27f8626..e410a41 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -286,6 +286,17 @@
 	return list
 }
 
+// Method that maps the apiScopes properties to the index of each apiScopes elements.
+// apiScopes property to be used as the key can be specified with the input accessor.
+// Only a string property of apiScope can be used as the key of the map.
+func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int {
+	ret := make(map[string]int)
+	for i, scope := range scopes {
+		ret[accessor(scope)] = i
+	}
+	return ret
+}
+
 var (
 	scopeByName    = make(map[string]*apiScope)
 	allScopeNames  []string
diff --git a/java/testing.go b/java/testing.go
index f2bcccf..98bea7f 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -424,30 +424,80 @@
 		`, extra)
 	}
 
-	extraApiLibraryModules := map[string]string{
-		"android_stubs_current.from-text":                  "api/current.txt",
-		"android_system_stubs_current.from-text":           "api/system-current.txt",
-		"android_test_stubs_current.from-text":             "api/test-current.txt",
-		"android_module_lib_stubs_current.from-text":       "api/module-lib-current.txt",
-		"android_module_lib_stubs_current_full.from-text":  "api/module-lib-current.txt",
-		"android_system_server_stubs_current.from-text":    "api/system-server-current.txt",
-		"core.current.stubs.from-text":                     "api/current.txt",
-		"legacy.core.platform.api.stubs.from-text":         "api/current.txt",
-		"stable.core.platform.api.stubs.from-text":         "api/current.txt",
-		"core-lambda-stubs.from-text":                      "api/current.txt",
-		"android-non-updatable.stubs.from-text":            "api/current.txt",
-		"android-non-updatable.stubs.system.from-text":     "api/system-current.txt",
-		"android-non-updatable.stubs.test.from-text":       "api/test-current.txt",
-		"android-non-updatable.stubs.module_lib.from-text": "api/module-lib-current.txt",
+	type apiContributionStruct struct {
+		name       string
+		apiSurface string
+		apiFile    string
 	}
 
-	for libName, apiFile := range extraApiLibraryModules {
+	var publicApiContribution = apiContributionStruct{
+		name:       "api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "public",
+		apiFile:    "api/current.txt",
+	}
+	var systemApiContribution = apiContributionStruct{
+		name:       "system-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "system",
+		apiFile:    "api/system-current.txt",
+	}
+	var testApiContribution = apiContributionStruct{
+		name:       "test-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "test",
+		apiFile:    "api/test-current.txt",
+	}
+	var moduleLibApiContribution = apiContributionStruct{
+		name:       "module-lib-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "module-lib",
+		apiFile:    "api/module-lib-current.txt",
+	}
+	var systemServerApiContribution = apiContributionStruct{
+		// This module does not exist but is named this way for consistency
+		name:       "system-server-api-stubs-docs-non-updatable.api.contribution",
+		apiSurface: "system-server",
+		apiFile:    "api/system-server-current.txt",
+	}
+	var apiContributionStructs = []apiContributionStruct{
+		publicApiContribution,
+		systemApiContribution,
+		testApiContribution,
+		moduleLibApiContribution,
+		systemServerApiContribution,
+	}
+
+	extraApiLibraryModules := map[string]apiContributionStruct{
+		"android_stubs_current.from-text":                  publicApiContribution,
+		"android_system_stubs_current.from-text":           systemApiContribution,
+		"android_test_stubs_current.from-text":             testApiContribution,
+		"android_module_lib_stubs_current.from-text":       moduleLibApiContribution,
+		"android_module_lib_stubs_current_full.from-text":  moduleLibApiContribution,
+		"android_system_server_stubs_current.from-text":    systemServerApiContribution,
+		"core.current.stubs.from-text":                     publicApiContribution,
+		"legacy.core.platform.api.stubs.from-text":         publicApiContribution,
+		"stable.core.platform.api.stubs.from-text":         publicApiContribution,
+		"core-lambda-stubs.from-text":                      publicApiContribution,
+		"android-non-updatable.stubs.from-text":            publicApiContribution,
+		"android-non-updatable.stubs.system.from-text":     systemApiContribution,
+		"android-non-updatable.stubs.test.from-text":       testApiContribution,
+		"android-non-updatable.stubs.module_lib.from-text": moduleLibApiContribution,
+	}
+
+	for _, apiContribution := range apiContributionStructs {
+		bp += fmt.Sprintf(`
+			java_api_contribution {
+				name: "%s",
+				api_surface: "%s",
+				api_file: "%s",
+			}
+		`, apiContribution.name, apiContribution.apiSurface, apiContribution.apiFile)
+	}
+
+	for libName, apiContribution := range extraApiLibraryModules {
 		bp += fmt.Sprintf(`
             java_api_library {
                 name: "%s",
-                api_files: ["%s"],
+                api_contributions: ["%s"],
             }
-        `, libName, apiFile)
+        `, libName, apiContribution.name)
 	}
 
 	bp += `
diff --git a/rust/protobuf.go b/rust/protobuf.go
index c8d2bda..c3aa8dc 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -305,7 +305,11 @@
 		},
 	}
 
-	ctx.CreateBazelTargetModule(
+	// TODO(b/295918553): Remove androidRestriction after rust toolchain for android is checked in.
+	var androidRestriction bazel.BoolAttribute
+	androidRestriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false))
+
+	ctx.CreateBazelTargetModuleWithRestrictions(
 		bazel.BazelTargetModuleProperties{
 			Rule_class: "proto_library",
 		},
@@ -317,9 +321,10 @@
 				android.BazelLabelForModuleSrc(ctx, protoFiles),
 			),
 		},
+		androidRestriction,
 	)
 
-	ctx.CreateBazelTargetModule(
+	ctx.CreateBazelTargetModuleWithRestrictions(
 		bazel.BazelTargetModuleProperties{
 			Rule_class:        "rust_proto_library",
 			Bzl_load_location: "@rules_rust//proto/protobuf:defs.bzl",
@@ -333,5 +338,6 @@
 			},
 			Deps: protoDeps,
 		},
+		androidRestriction,
 	)
 }
diff --git a/rust/rust.go b/rust/rust.go
index 3b24484..250e398 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1853,7 +1853,7 @@
 		procMacroBp2build(ctx, m)
 	} else if ctx.ModuleType() == "rust_binary_host" {
 		binaryBp2build(ctx, m)
-	} else if ctx.ModuleType() == "rust_protobuf_host" {
+	} else if ctx.ModuleType() == "rust_protobuf_host" || ctx.ModuleType() == "rust_protobuf" {
 		protoLibraryBp2build(ctx, m)
 	} else {
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")