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

Commit 98aa8fa8 authored by Jihoon Kang's avatar Jihoon Kang
Browse files

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
parent d5e16ac5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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.
+1 −1
Original line number Diff line number Diff line
@@ -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 {
+20 −10
Original line number Diff line number Diff line
@@ -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)

+136 −0
Original line number Diff line number Diff line
@@ -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",
    },
}
`),
		)
	})
+50 −0
Original line number Diff line number Diff line
@@ -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")