Remove exportable modules when generating snapshots targeting older platform

This change modifies the contents of the generated Android.bp files so
that when generating a snapshot on a older platform, the "exportable"
modules are removed from the bp files, as the "exportable" modules are
first introduced in V and do not exist in older platforms.

Bug: 345162614
Test: ABTD
Change-Id: I2dba51b98deec7805bd796647a66981f237c55a9
This commit is contained in:
Jihoon Kang 2024-06-07 11:06:57 +00:00
parent d5e16ac52b
commit 98aa8fa840
5 changed files with 209 additions and 11 deletions

View file

@ -291,6 +291,8 @@ var ApiLevelR = uncheckedFinalApiLevel(30)
var ApiLevelUpsideDownCake = uncheckedFinalApiLevel(34)
var ApiLevelVanillaIceCream = uncheckedFinalApiLevel(35)
// ReplaceFinalizedCodenames returns the API level number associated with that API level
// if the `raw` input is the codename of an API level has been finalized.
// If the input is *not* a finalized codename, the input is returned unmodified.

View file

@ -2178,7 +2178,7 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
// 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(
var scopeOrderMap = AllApiScopes.MapToIndex(
func(s *apiScope) string { return s.name })
func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {

View file

@ -324,6 +324,16 @@ func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]i
return ret
}
func (scopes apiScopes) ConvertStubsLibraryExportableToEverything(name string) string {
for _, scope := range scopes {
if strings.HasSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) {
return strings.TrimSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) +
scope.stubsLibraryModuleNameSuffix()
}
}
return name
}
var (
scopeByName = make(map[string]*apiScope)
allScopeNames []string
@ -418,7 +428,7 @@ var (
},
kind: android.SdkSystemServer,
})
allApiScopes = apiScopes{
AllApiScopes = apiScopes{
apiScopePublic,
apiScopeSystem,
apiScopeTest,
@ -1204,7 +1214,7 @@ func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleCon
paths := c.findClosestScopePath(apiScope)
if paths == nil {
var scopes []string
for _, s := range allApiScopes {
for _, s := range AllApiScopes {
if c.findScopePaths(s) != nil {
scopes = append(scopes, s.name)
}
@ -1421,7 +1431,7 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
// Check to see if any scopes have been explicitly enabled. If any have then all
// must be.
anyScopesExplicitlyEnabled := false
for _, scope := range allApiScopes {
for _, scope := range AllApiScopes {
scopeProperties := module.scopeToProperties[scope]
if scopeProperties.Enabled != nil {
anyScopesExplicitlyEnabled = true
@ -1431,7 +1441,7 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
var generatedScopes apiScopes
enabledScopes := make(map[*apiScope]struct{})
for _, scope := range allApiScopes {
for _, scope := range AllApiScopes {
scopeProperties := module.scopeToProperties[scope]
// If any scopes are explicitly enabled then ignore the legacy enabled status.
// This is to ensure that any new usages of this module type do not rely on legacy
@ -1451,7 +1461,7 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
// Now check to make sure that any scope that is extended by an enabled scope is also
// enabled.
for _, scope := range allApiScopes {
for _, scope := range AllApiScopes {
if _, ok := enabledScopes[scope]; ok {
extends := scope.extends
if extends != nil {
@ -2580,7 +2590,7 @@ func SdkLibraryFactory() android.Module {
// Initialize the map from scope to scope specific properties.
scopeToProperties := make(map[*apiScope]*ApiScopeProperties)
for _, scope := range allApiScopes {
for _, scope := range AllApiScopes {
scopeToProperties[scope] = scope.scopeSpecificProperties(module)
}
module.scopeToProperties = scopeToProperties
@ -2697,7 +2707,7 @@ var allScopeStructType = createAllScopePropertiesStructType()
// Dynamically create a structure type for each apiscope in allApiScopes.
func createAllScopePropertiesStructType() reflect.Type {
var fields []reflect.StructField
for _, apiScope := range allApiScopes {
for _, apiScope := range AllApiScopes {
field := reflect.StructField{
Name: apiScope.fieldName,
Type: reflect.TypeOf(sdkLibraryScopeProperties{}),
@ -2715,7 +2725,7 @@ func createPropertiesInstance() (interface{}, map[*apiScope]*sdkLibraryScopeProp
allScopePropertiesStruct := allScopePropertiesPtr.Elem()
scopeProperties := make(map[*apiScope]*sdkLibraryScopeProperties)
for _, apiScope := range allApiScopes {
for _, apiScope := range AllApiScopes {
field := allScopePropertiesStruct.FieldByName(apiScope.fieldName)
scopeProperties[apiScope] = field.Addr().Interface().(*sdkLibraryScopeProperties)
}
@ -3597,7 +3607,7 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe
s.Stem = sdk.distStem()
s.Scopes = make(map[*apiScope]*scopeProperties)
for _, apiScope := range allApiScopes {
for _, apiScope := range AllApiScopes {
paths := sdk.findScopePaths(apiScope)
if paths == nil {
continue
@ -3659,7 +3669,7 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo
stem := s.Stem
for _, apiScope := range allApiScopes {
for _, apiScope := range AllApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {
scopeSet := propertySet.AddPropertySet(apiScope.propertyName)

View file

@ -515,6 +515,142 @@ java_sdk_library_import {
.intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar
.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
`),
)
})
t.Run("test replacing exportable module", func(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("mysdklibrary", "anothersdklibrary"),
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
bootclasspath_fragments: ["mybootclasspathfragment"],
}
bootclasspath_fragment {
name: "mybootclasspathfragment",
apex_available: ["myapex"],
contents: ["mysdklibrary"],
hidden_api: {
split_packages: ["*"],
},
core_platform_api: {
stub_libs: [
"anothersdklibrary.stubs.exportable",
],
},
api: {
stub_libs: [
"anothersdklibrary",
],
},
}
java_sdk_library {
name: "mysdklibrary",
srcs: ["Test.java"],
compile_dex: true,
min_sdk_version: "S",
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
}
java_sdk_library {
name: "anothersdklibrary",
srcs: ["Test.java"],
compile_dex: true,
min_sdk_version: "S",
public: {enabled: true},
system: {enabled: true},
module_lib: {enabled: true},
}
`),
android.FixtureMergeEnv(map[string]string{
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
}),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.BuildFlags = map[string]string{
"RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
}
variables.Platform_version_active_codenames = []string{"UpsideDownCake", "Tiramisu", "S-V2"}
}),
).RunTest(t)
CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
prebuilt_bootclasspath_fragment {
name: "mybootclasspathfragment",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["myapex"],
contents: ["mysdklibrary"],
api: {
stub_libs: ["anothersdklibrary"],
},
core_platform_api: {
stub_libs: ["anothersdklibrary.stubs"],
},
hidden_api: {
annotation_flags: "hiddenapi/annotation-flags.csv",
metadata: "hiddenapi/metadata.csv",
index: "hiddenapi/index.csv",
stub_flags: "hiddenapi/stub-flags.csv",
all_flags: "hiddenapi/all-flags.csv",
},
}
java_sdk_library_import {
name: "mysdklibrary",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
shared_library: true,
compile_dex: true,
permitted_packages: ["mysdklibrary"],
public: {
jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
current_api: "sdk_library/public/mysdklibrary.txt",
removed_api: "sdk_library/public/mysdklibrary-removed.txt",
sdk_version: "current",
},
}
java_sdk_library_import {
name: "anothersdklibrary",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
shared_library: true,
compile_dex: true,
public: {
jars: ["sdk_library/public/anothersdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/anothersdklibrary_stub_sources"],
current_api: "sdk_library/public/anothersdklibrary.txt",
removed_api: "sdk_library/public/anothersdklibrary-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/anothersdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/system/anothersdklibrary_stub_sources"],
current_api: "sdk_library/system/anothersdklibrary.txt",
removed_api: "sdk_library/system/anothersdklibrary-removed.txt",
sdk_version: "system_current",
},
module_lib: {
jars: ["sdk_library/module-lib/anothersdklibrary-stubs.jar"],
stub_srcs: ["sdk_library/module-lib/anothersdklibrary_stub_sources"],
current_api: "sdk_library/module-lib/anothersdklibrary.txt",
removed_api: "sdk_library/module-lib/anothersdklibrary-removed.txt",
sdk_version: "module_current",
},
}
`),
)
})

View file

@ -480,6 +480,12 @@ be unnecessary as every module in the sdk already has its own licenses property.
// Transform the module module to make it suitable for use in the snapshot.
module = transformModule(module, snapshotTransformer)
module = transformModule(module, emptyClasspathContentsTransformation{})
targetApiLevel, err := android.ApiLevelFromUserWithConfig(ctx.Config(), s.targetBuildRelease(ctx).name)
if err == nil && targetApiLevel.LessThan(android.ApiLevelVanillaIceCream) {
module = transformModule(module, replaceExportablePropertiesTransformer{})
}
if module != nil {
bpFile.AddModule(module)
}
@ -804,6 +810,50 @@ func (t pruneEmptySetTransformer) transformPropertySetAfterContents(_ string, pr
}
}
type replaceExportablePropertiesTransformer struct {
identityTransformation
}
var _ bpTransformer = (*replaceExportablePropertiesTransformer)(nil)
func handleExportableProperties[T any](value T) any {
switch v := any(value).(type) {
case string:
return java.AllApiScopes.ConvertStubsLibraryExportableToEverything(v)
case *bpPropertySet:
v.properties = handleExportableProperties(v.properties).(map[string]interface{})
return v
case []string:
result := make([]string, len(v))
for i, elem := range v {
result[i] = handleExportableProperties(elem).(string)
}
return result
case []any:
result := make([]any, len(v))
for i, elem := range v {
result[i] = handleExportableProperties(elem)
}
return result
case map[string]any:
result := make(map[string]any)
for k, val := range v {
result[k] = handleExportableProperties(val)
}
return result
default:
return value
}
}
func (t replaceExportablePropertiesTransformer) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
if name == "name" {
return propertySet, tag
}
propertySet.properties = handleExportableProperties(propertySet.properties).(map[string]interface{})
return propertySet, tag
}
func generateBpContents(bpFile *bpFile) string {
contents := &generatedContents{}
contents.IndentedPrintf("// This is auto-generated. DO NOT EDIT.\n")