Merge "Allow sdk_version: "system_server_current" modules to access module-lib APIs"

This commit is contained in:
Treehugger Robot
2022-10-05 22:05:25 +00:00
committed by Gerrit Code Review
2 changed files with 109 additions and 2 deletions

View File

@@ -65,8 +65,27 @@ type apiScope struct {
name string
// The api scope that this scope extends.
//
// This organizes the scopes into an extension hierarchy.
//
// If set this means that the API provided by this scope includes the API provided by the scope
// set in this field.
extends *apiScope
// The next api scope that a library that uses this scope can access.
//
// This organizes the scopes into an access hierarchy.
//
// If set this means that a library that can access this API can also access the API provided by
// the scope set in this field.
//
// A module that sets sdk_version: "<scope>_current" should have access to the <scope> API of
// every java_sdk_library that it depends on. If the library does not provide an API for <scope>
// then it will traverse up this access hierarchy to find an API that it does provide.
//
// If this is not set then it defaults to the scope set in extends.
canAccess *apiScope
// The legacy enabled status for a specific scope can be dependent on other
// properties that have been specified on the library so it is provided by
// a function that can determine the status by examining those properties.
@@ -107,7 +126,7 @@ type apiScope struct {
// The scope specific prefix to add to the api file base of "current.txt" or "removed.txt".
apiFilePrefix string
// The scope specific prefix to add to the sdk library module name to construct a scope specific
// The scope specific suffix to add to the sdk library module name to construct a scope specific
// module name.
moduleSuffix string
@@ -193,6 +212,11 @@ func initApiScope(scope *apiScope) *apiScope {
}
}
// By default, a library that can access a scope can also access the scope it extends.
if scope.canAccess == nil {
scope.canAccess = scope.extends
}
// Escape any special characters in the arguments. This is needed because droidstubs
// passes these directly to the shell command.
scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs)
@@ -310,6 +334,14 @@ var (
apiScopeSystemServer = initApiScope(&apiScope{
name: "system-server",
extends: apiScopePublic,
// The system-server scope can access the module-lib scope.
//
// A module that provides a system-server API is appended to the standard bootclasspath that is
// used by the system server. So, it should be able to access module-lib APIs provided by
// libraries on the bootclasspath.
canAccess: apiScopeModuleLib,
// The system-server scope is disabled by default in legacy mode.
//
// Enabling this would break existing usages.
@@ -926,7 +958,7 @@ func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePath
// If this does not support the requested api scope then find the closest available
// scope it does support. Returns nil if no such scope is available.
func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths {
for s := scope; s != nil; s = s.extends {
for s := scope; s != nil; s = s.canAccess {
if paths := c.findScopePaths(s); paths != nil {
return paths
}

View File

@@ -18,6 +18,7 @@ import (
"fmt"
"path/filepath"
"regexp"
"strings"
"testing"
"android/soong/android"
@@ -699,6 +700,80 @@ func TestJavaSdkLibrary_SystemServer(t *testing.T) {
`)
}
func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo-public", "foo-system", "foo-module-lib", "foo-system-server"),
).RunTestWithBp(t, `
java_sdk_library {
name: "foo-public",
srcs: ["a.java"],
api_packages: ["foo"],
public: {
enabled: true,
},
}
java_sdk_library {
name: "foo-system",
srcs: ["a.java"],
api_packages: ["foo"],
system: {
enabled: true,
},
}
java_sdk_library {
name: "foo-module-lib",
srcs: ["a.java"],
api_packages: ["foo"],
system: {
enabled: true,
},
module_lib: {
enabled: true,
},
}
java_sdk_library {
name: "foo-system-server",
srcs: ["a.java"],
api_packages: ["foo"],
system_server: {
enabled: true,
},
}
java_library {
name: "bar",
srcs: ["a.java"],
libs: ["foo-public", "foo-system", "foo-module-lib", "foo-system-server"],
sdk_version: "system_server_current",
}
`)
stubsPath := func(name string, scope *apiScope) string {
name = scope.stubsLibraryModuleName(name)
return fmt.Sprintf("out/soong/.intermediates/%[1]s/android_common/turbine-combined/%[1]s.jar", name)
}
// The bar library should depend on the highest (where system server is highest and public is
// lowest) API scopes provided by each of the foo-* modules. The highest API scope provided by the
// foo-<x> module is <x>.
barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
stubLibraries := []string{
stubsPath("foo-public", apiScopePublic),
stubsPath("foo-system", apiScopeSystem),
stubsPath("foo-module-lib", apiScopeModuleLib),
stubsPath("foo-system-server", apiScopeSystemServer),
}
expectedPattern := fmt.Sprintf(`^-classpath .*:\Q%s\E$`, strings.Join(stubLibraries, ":"))
if expected, actual := expectedPattern, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected pattern %q to match %#q", expected, actual)
}
}
func TestJavaSdkLibrary_MissingScope(t *testing.T) {
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)).