Merge "Reapply "Enable CFI for riscv64"" into main
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 5427c84..23ced73 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -65,6 +65,7 @@
 
 		"build/bazel":                        Bp2BuildDefaultTrueRecursively,
 		"build/make/target/product/security": Bp2BuildDefaultTrue,
+		"build/make/tools":                   Bp2BuildDefaultTrue,
 		"build/make/tools/protos":            Bp2BuildDefaultTrue,
 		"build/make/tools/releasetools":      Bp2BuildDefaultTrue,
 		"build/make/tools/sbom":              Bp2BuildDefaultTrue,
@@ -79,7 +80,9 @@
 		"build/soong/scripts":                Bp2BuildDefaultTrueRecursively,
 
 		"cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
-		"cts/libs/json": Bp2BuildDefaultTrueRecursively,
+		"cts/libs/json":                          Bp2BuildDefaultTrueRecursively,
+		"cts/tests/tests/gesture":                Bp2BuildDefaultTrueRecursively,
+		"platform_testing/libraries/annotations": Bp2BuildDefaultTrueRecursively,
 
 		"dalvik/tools/dexdeps": Bp2BuildDefaultTrueRecursively,
 
@@ -892,9 +895,6 @@
 
 		"merge_annotation_zips_test",
 
-		// bouncycastle dep
-		"platform-test-annotations",
-
 		// java_resources with multiple resource_dirs
 		"emma",
 
@@ -904,6 +904,16 @@
 		"ndk_libc++_static",
 		"ndk_libc++_shared",
 		"ndk_system",
+
+		// allowlist //prebuilts/common/misc/androidx-test/...
+		"androidx.test.runner",
+		"androidx.test.runner-nodeps",
+		"androidx.test.services.storage",
+		"androidx.test.services.storage-nodeps",
+		"androidx.test.monitor",
+		"androidx.test.monitor-nodeps",
+		"androidx.test.annotation",
+		"androidx.test.annotation-nodeps",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -1649,6 +1659,17 @@
 
 		// TODO(b/299974637) Fix linking error
 		"libbinder_rpc_unstable",
+
+		// TODO(b/297356704) sdk_version is unset.
+		"VendorAtomCodeGenJavaTest",
+
+		// android_test from allowlisted packages, but with unconverted deps
+		"MtsLibnativehelperLazyTestCases",
+		"ObjenesisTck",
+		"DevCodelabTest",
+		"MtsTimeZoneDataTestCases",
+		"NanoAndroidTest",
+		"MtsLibnativehelperTestCases",
 	}
 
 	// Bazel prod-mode allowlist. Modules in this list are built by Bazel
diff --git a/android/module.go b/android/module.go
index 516810f..e6e5918 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1636,15 +1636,23 @@
 }
 
 func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
-	if m.commonProperties.BazelConversionStatus.UnconvertedReason != nil {
-		panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name()))
+	reason := m.commonProperties.BazelConversionStatus.UnconvertedReason
+	if reason != nil {
+		panic(fmt.Errorf("bp2build: internal error trying to convert module '%s' marked unconvertible. Reason type %d: %s",
+			m.Name(),
+			reason.ReasonType,
+			reason.Detail))
 	}
 	m.commonProperties.BazelConversionStatus.Bp2buildInfo = append(m.commonProperties.BazelConversionStatus.Bp2buildInfo, info)
 }
 
 func (m *ModuleBase) setBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
 	if len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0 {
-		panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name()))
+		fmt.Println(m.commonProperties.BazelConversionStatus.Bp2buildInfo)
+		panic(fmt.Errorf("bp2build: internal error trying to mark converted module '%s' as unconvertible. Reason type %d: %s",
+			m.Name(),
+			reasonType,
+			detail))
 	}
 	m.commonProperties.BazelConversionStatus.UnconvertedReason = &UnconvertedReason{
 		ReasonType: int(reasonType),
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index 13bb167..ce20721 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -17,7 +17,6 @@
 import (
 	"android/soong/android"
 	"android/soong/java"
-	"fmt"
 
 	"testing"
 )
@@ -91,7 +90,6 @@
 	sdk_version: "current",
 }
 `,
-		ExpectedErr:          fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
 		ExpectedBazelTargets: []string{},
 	})
 }
diff --git a/java/aar.go b/java/aar.go
index b1a7827..262657d 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1340,7 +1340,10 @@
 	if !commonAttrs.Srcs.IsEmpty() {
 		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
 	} else if !depLabels.Deps.IsEmpty() {
-		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
+		ctx.MarkBp2buildUnconvertible(
+			bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED,
+			"Module has direct dependencies but no sources. Bazel will not allow this.")
+		return
 	}
 	name := a.Name()
 	props := AndroidLibraryBazelTargetModuleProperties()
diff --git a/java/app.go b/java/app.go
index 7ee0e38..1b4d279 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1115,6 +1115,8 @@
 	testConfig       android.Path
 	extraTestConfigs android.Paths
 	data             android.Paths
+
+	android.BazelModuleBase
 }
 
 func (a *AndroidTest) InstallInTestcases() bool {
@@ -1232,6 +1234,8 @@
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
+
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -1630,11 +1634,10 @@
 	Proguard_specs   bazel.LabelListAttribute
 }
 
-// ConvertWithBp2build is used to convert android_app to Bazel.
-func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func convertWithBp2build(ctx android.TopDownMutatorContext, a *AndroidApp) (bool, android.CommonAttributes, *bazelAndroidAppAttributes) {
 	aapt, supported := a.convertAaptAttrsWithBp2Build(ctx)
 	if !supported {
-		return
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
 	}
 	certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
 
@@ -1706,18 +1709,13 @@
 
 	commonAttrs, bp2BuildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
 	if !supported {
-		return
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
 	}
 	depLabels := bp2BuildInfo.DepLabels
 
 	deps := depLabels.Deps
 	deps.Append(depLabels.StaticDeps)
 
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "android_binary",
-		Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
-	}
-
 	if !bp2BuildInfo.hasKotlin {
 		appAttrs.javaCommonAttributes = commonAttrs
 		appAttrs.bazelAapt = aapt
@@ -1743,10 +1741,31 @@
 		}
 	}
 
-	ctx.CreateBazelTargetModule(
-		props,
-		android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)},
-		appAttrs,
-	)
+	return true, android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)}, appAttrs
+}
+
+// ConvertWithBp2build is used to convert android_app to Bazel.
+func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, a); ok {
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "android_binary",
+			Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
+		}
+
+		ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs)
+	}
+
+}
+
+// ConvertWithBp2build is used to convert android_test to Bazel.
+func (at *AndroidTest) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, &at.AndroidApp); ok {
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "android_test",
+			Bzl_load_location: "//build/bazel/rules/android:android_test.bzl",
+		}
+
+		ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs)
+	}
 
 }
diff --git a/java/java.go b/java/java.go
index 48e13fe..fdb635e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -64,6 +64,7 @@
 	ctx.RegisterModuleType("dex_import", DexImportFactory)
 	ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
 	ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
+	ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory)
 
 	// This mutator registers dependencies on dex2oat for modules that should be
 	// dexpreopted. This is done late when the final variants have been
@@ -1623,7 +1624,8 @@
 }
 
 type JavaApiImportInfo struct {
-	ApiFile android.Path
+	ApiFile    android.Path
+	ApiSurface string
 }
 
 var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
@@ -1635,7 +1637,8 @@
 	}
 
 	ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
-		ApiFile: apiFile,
+		ApiFile:    apiFile,
+		ApiSurface: proptools.String(ap.properties.Api_surface),
 	})
 }
 
@@ -1821,18 +1824,29 @@
 var scopeOrderedSourceFileNames = allApiScopes.Strings(
 	func(s *apiScope) string { return s.apiFilePrefix + "current.txt" })
 
-func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles android.Paths) android.Paths {
-	sortedSrcFiles := android.Paths{}
+func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo, apiFiles android.Paths) android.Paths {
+	var sortedSrcFiles android.Paths
 
-	for _, scopeSourceFileName := range scopeOrderedSourceFileNames {
-		for _, sourceFileName := range srcFiles {
-			if sourceFileName.Base() == scopeSourceFileName {
-				sortedSrcFiles = append(sortedSrcFiles, sourceFileName)
+	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)
 			}
 		}
 	}
-	if len(srcFiles) != len(sortedSrcFiles) {
-		ctx.ModuleErrorf("Unrecognizable source file found within %s", srcFiles)
+
+	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
@@ -1853,7 +1867,7 @@
 
 	homeDir := android.PathForModuleOut(ctx, "metalava", "home")
 
-	var srcFiles android.Paths
+	var srcFilesInfo []JavaApiImportInfo
 	var classPaths android.Paths
 	var staticLibs android.Paths
 	var depApiSrcsStubsJar android.Path
@@ -1862,11 +1876,10 @@
 		switch tag {
 		case javaApiContributionTag:
 			provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo)
-			providerApiFile := provider.ApiFile
-			if providerApiFile == nil && !ctx.Config().AllowMissingDependencies() {
+			if provider.ApiFile == nil && !ctx.Config().AllowMissingDependencies() {
 				ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name())
 			}
-			srcFiles = append(srcFiles, android.PathForSource(ctx, providerApiFile.String()))
+			srcFilesInfo = append(srcFilesInfo, provider)
 		case libTag:
 			provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
 			classPaths = append(classPaths, provider.HeaderJars...)
@@ -1880,16 +1893,19 @@
 	})
 
 	// 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 {
-		srcFiles = append(srcFiles, android.PathForModuleSrc(ctx, api))
+		apiFiles = append(apiFiles, android.PathForModuleSrc(ctx, api))
 	}
 
+	srcFiles := al.sortApiFilesByApiScope(ctx, srcFilesInfo, apiFiles)
+
 	if srcFiles == nil && !ctx.Config().AllowMissingDependencies() {
 		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
 	}
 
-	srcFiles = al.sortApiFilesByApiScope(ctx, srcFiles)
-
 	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
 
 	al.stubsFlags(ctx, cmd, stubsDir)
@@ -3428,3 +3444,30 @@
 func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
 	return true
 }
+
+type JavaApiContributionImport struct {
+	JavaApiContribution
+
+	prebuilt android.Prebuilt
+}
+
+func ApiContributionImportFactory() android.Module {
+	module := &JavaApiContributionImport{}
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	android.InitPrebuiltModule(module, &[]string{""})
+	module.AddProperties(&module.properties)
+	return module
+}
+
+func (module *JavaApiContributionImport) Prebuilt() *android.Prebuilt {
+	return &module.prebuilt
+}
+
+func (module *JavaApiContributionImport) Name() string {
+	return module.prebuilt.Name(module.ModuleBase.Name())
+}
+
+func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	ap.JavaApiContribution.GenerateAndroidBuildActions(ctx)
+}
diff --git a/java/java_test.go b/java/java_test.go
index 27933c3..2ee05ec 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1865,11 +1865,13 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	ctx, _ := testJavaWithFS(t, `
@@ -1919,24 +1921,28 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_c := `
 	java_api_contribution {
 		name: "foo3",
-		api_file: "current.txt",
+		api_file: "system-current.txt",
+		api_surface: "system",
 	}
 	`
 	provider_bp_d := `
 	java_api_contribution {
 		name: "foo4",
-		api_file: "current.txt",
+		api_file: "system-current.txt",
+		api_surface: "system",
 	}
 	`
 	ctx, _ := testJavaWithFS(t, `
@@ -1992,8 +1998,9 @@
 			sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
 		},
 		{
-			moduleName:         "bar3",
-			sourceTextFileDirs: []string{"c/current.txt", "a/current.txt", "b/current.txt", "d/current.txt", "api1/current.txt", "api2/current.txt"},
+			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"},
 		},
 	}
 	for _, c := range testcases {
@@ -2011,12 +2018,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	ctx, _ := testJavaWithFS(t, `
@@ -2064,12 +2073,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	lib_bp_a := `
@@ -2139,12 +2150,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	lib_bp_a := `
@@ -2213,12 +2226,14 @@
 	java_api_contribution {
 		name: "foo1",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	provider_bp_b := `
 	java_api_contribution {
 		name: "foo2",
 		api_file: "current.txt",
+		api_surface: "public",
 	}
 	`
 	lib_bp_a := `
@@ -2388,3 +2403,23 @@
 	javac := ctx.ModuleForTests("foo", "android_common").MaybeRule("javac")
 	android.AssertDeepEquals(t, "javac rule", nil, javac.Rule)
 }
+
+func TestJavaApiContributionImport(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_api_library {
+			name: "foo",
+			api_contributions: ["bar"],
+		}
+		java_api_contribution_import {
+			name: "bar",
+			api_file: "current.txt",
+			api_surface: "public",
+		}
+	`)
+	m := ctx.ModuleForTests("foo", "android_common")
+	manifest := m.Output("metalava.sbox.textproto")
+	sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+	manifestCommand := sboxProto.Commands[0].GetCommand()
+	sourceFilesFlag := "--source-files current.txt"
+	android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d1620af..6349d92 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2479,6 +2479,10 @@
 		if len(scopeProperties.Stub_srcs) > 0 {
 			module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
 		}
+
+		if scopeProperties.Current_api != nil {
+			module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties)
+		}
 	}
 
 	javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -2534,6 +2538,25 @@
 	mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
 }
 
+func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+	api_file := scopeProperties.Current_api
+	api_surface := &apiScope.name
+
+	props := struct {
+		Name        *string
+		Api_surface *string
+		Api_file    *string
+		Visibility  []string
+	}{}
+
+	props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
+	props.Api_surface = api_surface
+	props.Api_file = api_file
+	props.Visibility = []string{"//visibility:override", "//visibility:public"}
+
+	mctx.CreateModule(ApiContributionImportFactory, &props)
+}
+
 // Add the dependencies on the child module in the component deps mutator so that it
 // creates references to the prebuilt and not the source modules.
 func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 868d697..0b46919 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -74,6 +74,8 @@
 		    name: "quuz",
 				public: {
 					jars: ["c.jar"],
+					current_api: "api/current.txt",
+					removed_api: "api/removed.txt",
 				},
 		}
 		java_sdk_library_import {
@@ -173,6 +175,9 @@
 		android.AssertDeepEquals(t, "qux exports (optional)", []string{}, optionalSdkLibs)
 	}
 
+	// test if quuz have created the api_contribution module
+	result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "")
+
 	fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8")
 	// tests if kotlinc generated files are NOT excluded from output of foo.
 	android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")