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

Commit 5d701272 authored by Jihoon Kang's avatar Jihoon Kang
Browse files

Enable non-"everything" stubs generation in java_api_library

This change adds support to generate non-"everything" (i.e. "runtime"
and "exportable") stubs in java_api_library, which generates the stubs
from the api signature files.

Unlike droidstubs module that generates "everything", "exportable" and
"runtime" stubs in a single module, java_api_library generates a single
set of stubs per module, which is set by the default-"everything"
property `stubs_type`. This is because java_api_library is responsible
for both generation and the compilation of the stubs srcjar, and
compilation of the stubs srcjar are done in separate java_library
modules for from-source stubs.

Utilization of this feature will be done in a follow up change that
generates the "exportable" java_api_library modules in java_sdk_library.

Test: m nothing --no-skip-soong-tests
Bug: 318009570
Change-Id: I1051544ac3bcdb3ba1f78bfec28eba4e9fad9c2d
parent 60bdd05b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ java_api_library {
        "stub-annotations",
    ],
    enable_validation: false,
    stubs_type: "everything",
}

java_library {
@@ -248,6 +249,7 @@ java_api_library {
        "stub-annotations",
    ],
    visibility: ["//visibility:private"],
    stubs_type: "everything",
}

// Produces a dist file that is used by the
@@ -358,6 +360,7 @@ java_api_library {
    libs: [
        "stub-annotations",
    ],
    stubs_type: "everything",
}

java_library {
@@ -446,6 +449,7 @@ java_api_library {
    libs: [
        "stub-annotations",
    ],
    stubs_type: "everything",
}

java_library {
+15 −2
Original line number Diff line number Diff line
@@ -52,6 +52,19 @@ func (s StubsType) String() string {
	}
}

func StringToStubsType(s string) StubsType {
	switch strings.ToLower(s) {
	case Everything.String():
		return Everything
	case Runtime.String():
		return Runtime
	case Exportable.String():
		return Exportable
	default:
		return Unavailable
	}
}

func init() {
	RegisterStubsBuildComponents(android.InitRegistrationContext)
}
@@ -731,7 +744,7 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
// property is defined, apply transformations and only revert the flagged apis that are not
// enabled via release configurations and are not specified in aconfig_declarations
func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {

	if len(aconfigFlagsPaths) == 0 {
		cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
@@ -1106,7 +1119,7 @@ func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsComm

	cmd := d.commonMetalavaStubCmd(ctx, rule, params)

	d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
	generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)

	if params.stubConfig.doApiLint {
		// Pass the lint baseline file as an input to resolve the lint errors.
+1 −0
Original line number Diff line number Diff line
@@ -337,6 +337,7 @@ func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
			name: "bar",
			api_surface: "public",
			api_contributions: ["foo.api.contribution"],
			stubs_type: "everything",
		}
	`
	ctx, _ := testJavaWithFS(t, `
+52 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import (
	"sort"
	"strings"

	"android/soong/aconfig"
	"android/soong/remoteexec"
	"android/soong/testing"

@@ -1863,6 +1864,10 @@ type ApiLibrary struct {
	dexJarFile OptionalDexJarPath

	validationPaths android.Paths

	stubsType StubsType

	aconfigProtoFiles android.Paths
}

type JavaApiLibraryProperties struct {
@@ -1904,6 +1909,20 @@ type JavaApiLibraryProperties struct {
	// in sync with the source Java files. However, the environment variable
	// DISABLE_STUB_VALIDATION has precedence over this property.
	Enable_validation *bool

	// Type of stubs the module should generate. Must be one of "everything", "runtime" or
	// "exportable". Defaults to "everything".
	// - "everything" stubs include all non-flagged apis and flagged apis, regardless of the state
	// of the flag.
	// - "runtime" stubs include all non-flagged apis and flagged apis that are ENABLED or
	// READ_WRITE, and all other flagged apis are stripped.
	// - "exportable" stubs include all non-flagged apis and flagged apis that are ENABLED and
	// READ_ONLY, and all other flagged apis are stripped.
	Stubs_type *string

	// List of aconfig_declarations module names that the stubs generated in this module
	// depend on.
	Aconfig_declarations []string
}

func ApiLibraryFactory() android.Module {
@@ -2067,6 +2086,9 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
	if al.properties.System_modules != nil {
		ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules))
	}
	for _, aconfigDeclarationsName := range al.properties.Aconfig_declarations {
		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationsName)
	}
}

// Map where key is the api scope name and value is the int value
@@ -2087,7 +2109,23 @@ func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles
	return srcFilesInfo
}

var validstubsType = []StubsType{Everything, Runtime, Exportable}

func (al *ApiLibrary) validateProperties(ctx android.ModuleContext) {
	if al.properties.Stubs_type == nil {
		ctx.ModuleErrorf("java_api_library module type must specify stubs_type property.")
	} else {
		al.stubsType = StringToStubsType(proptools.String(al.properties.Stubs_type))
	}

	if !android.InList(al.stubsType, validstubsType) {
		ctx.PropertyErrorf("stubs_type", "%s is not a valid stubs_type property value. "+
			"Must be one of %s.", proptools.String(al.properties.Stubs_type), validstubsType)
	}
}

func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	al.validateProperties(ctx)

	rule := android.NewRuleBuilder(pctx, ctx)

@@ -2131,6 +2169,18 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
			if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok {
				al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp())
			}
		case aconfigDeclarationTag:
			if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
				al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPath)
			} else if provider, ok := android.OtherModuleProvider(ctx, dep, aconfig.CodegenInfoProvider); ok {
				al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPaths...)
			} else {
				ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+
					"module type is allowed for flags_packages property, but %s is neither "+
					"of these supported module types",
					dep.Name(),
				)
			}
		}
	})

@@ -2156,6 +2206,8 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {

	al.addValidation(ctx, cmd, al.validationPaths)

	generateRevertAnnotationArgs(ctx, cmd, al.stubsType, al.aconfigProtoFiles)

	al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
	al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
	al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
+69 −0
Original line number Diff line number Diff line
@@ -1756,6 +1756,7 @@ func TestJavaApiContributionEmptyApiFile(t *testing.T) {
			name: "bar",
			api_surface: "public",
			api_contributions: ["foo"],
			stubs_type: "everything",
		}
	`)
}
@@ -1792,12 +1793,14 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) {
			name: "bar1",
			api_surface: "public",
			api_contributions: ["foo1"],
			stubs_type: "everything",
		}

		java_api_library {
			name: "bar2",
			api_surface: "system",
			api_contributions: ["foo1", "foo2"],
			stubs_type: "everything",
		}
	`)

@@ -1885,12 +1888,14 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
			name: "bar1",
			api_surface: "public",
			api_contributions: ["foo1"],
			stubs_type: "everything",
		}

		java_api_library {
			name: "bar2",
			api_surface: "public",
			defaults:["baz1"],
			stubs_type: "everything",
		}

		java_api_library {
@@ -1898,6 +1903,7 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
			api_surface: "system",
			defaults:["baz1", "baz2"],
			api_contributions: ["foo4"],
			stubs_type: "everything",
		}
	`)

@@ -1962,12 +1968,14 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) {
			name: "bar1",
			api_surface: "public",
			api_contributions: ["foo1"],
			stubs_type: "everything",
		}

		java_api_library {
			name: "bar2",
			api_surface: "system",
			api_contributions: ["foo1", "foo2"],
			stubs_type: "everything",
		}
	`)

@@ -2044,6 +2052,7 @@ func TestJavaApiLibraryLibsLink(t *testing.T) {
			api_surface: "public",
			api_contributions: ["foo1"],
			libs: ["lib1"],
			stubs_type: "everything",
		}

		java_api_library {
@@ -2051,6 +2060,7 @@ func TestJavaApiLibraryLibsLink(t *testing.T) {
			api_surface: "system",
			api_contributions: ["foo1", "foo2"],
			libs: ["lib1", "lib2", "bar1"],
			stubs_type: "everything",
		}
	`)

@@ -2130,6 +2140,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
			api_surface: "public",
			api_contributions: ["foo1"],
			static_libs: ["lib1"],
			stubs_type: "everything",
		}

		java_api_library {
@@ -2137,6 +2148,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
			api_surface: "system",
			api_contributions: ["foo1", "foo2"],
			static_libs: ["lib1", "lib2", "bar1"],
			stubs_type: "everything",
		}
	`)

@@ -2184,6 +2196,7 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
		name: "lib1",
		api_surface: "public",
		api_contributions: ["foo1", "foo2"],
		stubs_type: "everything",
	}
	`

@@ -2207,6 +2220,7 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
			api_surface: "public",
			api_contributions: ["foo1"],
			full_api_surface_stub: "lib1",
			stubs_type: "everything",
		}
	`)

@@ -2368,6 +2382,7 @@ func TestJavaApiContributionImport(t *testing.T) {
		java_api_library {
			name: "foo",
			api_contributions: ["bar"],
			stubs_type: "everything",
		}
		java_api_contribution_import {
			name: "bar",
@@ -2394,6 +2409,7 @@ func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
				"module-lib-api-stubs-docs-non-updatable.api.contribution",
				"api-stubs-docs-non-updatable.api.contribution",
			],
			stubs_type: "everything",
		}
	`)
	m := ctx.ModuleForTests("foo", "android_common")
@@ -2466,6 +2482,7 @@ func TestApiLibraryDroidstubsDependency(t *testing.T) {
				"api-stubs-docs-non-updatable.api.contribution",
			],
			enable_validation: true,
			stubs_type: "everything",
		}
		java_api_library {
			name: "bar",
@@ -2473,6 +2490,7 @@ func TestApiLibraryDroidstubsDependency(t *testing.T) {
				"api-stubs-docs-non-updatable.api.contribution",
			],
			enable_validation: false,
			stubs_type: "everything",
		}
	`)

@@ -2624,3 +2642,54 @@ func TestMultiplePrebuilts(t *testing.T) {
		android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0])
	}
}

func TestApiLibraryAconfigDeclarations(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForJavaTest,
		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
		}),
		android.FixtureMergeMockFs(map[string][]byte{
			"a/A.java":      nil,
			"a/current.txt": nil,
			"a/removed.txt": nil,
		}),
	).RunTestWithBp(t, `
	aconfig_declarations {
		name: "bar",
		package: "com.example.package",
		srcs: [
			"bar.aconfig",
		],
	}
	java_api_contribution {
		name: "baz",
		api_file: "a/current.txt",
		api_surface: "public",
	}
	java_api_library {
		name: "foo",
		api_surface: "public",
		api_contributions: [
			"baz",
		],
		aconfig_declarations: [
			"bar",
		],
		stubs_type: "exportable",
		enable_validation: false,
	}
	`)

	// Check if java_api_library depends on aconfig_declarations
	android.AssertBoolEquals(t, "foo expected to depend on bar",
		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)

	m := result.ModuleForTests("foo", "android_common")
	android.AssertStringDoesContain(t, "foo generates revert annotations file",
		strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")

	// revert-annotations.txt passed to exportable stubs generation metalava command
	manifest := m.Output("metalava.sbox.textproto")
	cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
	android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
}
Loading