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
diff --git a/android/api_levels.go b/android/api_levels.go
index fab5fc7..dc17238 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -291,6 +291,8 @@
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.
diff --git a/java/java.go b/java/java.go
index 9fa6175..b851e74 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2178,7 +2178,7 @@
// 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 {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 72eb6e3..6c1a38d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -324,6 +324,16 @@
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 @@
},
kind: android.SdkSystemServer,
})
- allApiScopes = apiScopes{
+ AllApiScopes = apiScopes{
apiScopePublic,
apiScopeSystem,
apiScopeTest,
@@ -1204,7 +1214,7 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
stem := s.Stem
- for _, apiScope := range allApiScopes {
+ for _, apiScope := range AllApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {
scopeSet := propertySet.AddPropertySet(apiScope.propertyName)
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index f9d49d9..4894210 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -519,4 +519,140 @@
)
})
+ 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",
+ },
+}
+`),
+ )
+ })
+
}
diff --git a/sdk/update.go b/sdk/update.go
index afecf9f..0a97fd9 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -480,6 +480,12 @@
// 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 @@
}
}
+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")