Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e50b0f55 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I8466db71,I83180699 into main

* changes:
  Sort api files by api surface in java_api_library
  Add java_api_contribution_import module type
parents 8c04f3fd 8fe1982e
Loading
Loading
Loading
Loading
+60 −17
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) {
	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
@@ -1624,6 +1625,7 @@ func ApiContributionFactory() android.Module {

type JavaApiImportInfo struct {
	ApiFile    android.Path
	ApiSurface string
}

var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
@@ -1636,6 +1638,7 @@ func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleCon

	ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
		ApiFile:    apiFile,
		ApiSurface: proptools.String(ap.properties.Api_surface),
	})
}

@@ -1821,18 +1824,29 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
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 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {

	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 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		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 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	})

	// 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) QueueBazelCall(ctx android.BaseModuleContext) {
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)
}
+39 −4
Original line number Diff line number Diff line
@@ -1865,11 +1865,13 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) {
	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 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
	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, `
@@ -1993,7 +1999,8 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
		},
		{
			moduleName: "bar3",
			sourceTextFileDirs: []string{"c/current.txt", "a/current.txt", "b/current.txt", "d/current.txt", "api1/current.txt", "api2/current.txt"},
			// 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 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) {
	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 @@ func TestJavaApiLibraryLibsLink(t *testing.T) {
	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 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
	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 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
	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 @@ func TestHeadersOnly(t *testing.T) {
	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)
}