Add HiddenAPIScope to replace use of SdkKind

Previously, the hidden API processing used SdkKind to identify the API
scopes, e.g. public, system, etc. that are of interest for hidden API
processing. Unfortunately, there is a mismatch between the SdkKind and
what hidden API processing needs. e.g. SdkKind includes values that are
not used by hidden API processing and hidden API processing needs
additional API scope specific information not provided by SdkKind. The
apiScope struct used in sdk_library.go is also not a suitable
representation for similar reasons.

This change adds the HiddenAPIScope (following a similar approach as
apiScope) that rectifies that and uses it as a replacement for SdkKind
in most parts of the hidden API processing. The SdkKind is still used
for retrieving information from java_sdk_library[_import] modules.

Follow up changes will extend the HiddenAPIScope with more information.

Bug: 179354495
Test: m out/soong/hiddenapi/hiddenapi-flags.csv
      - make sure that this change has no effect on the generated flags.
Change-Id: I97968f58535121652852b8d25217aa288afd2bfd
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 6e22614..66f4fe7 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -25,9 +25,97 @@
 
 // Contains support for processing hiddenAPI in a modular fashion.
 
+// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
+// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
+// not provide the information needed by hidden API processing.
+type HiddenAPIScope struct {
+	// The name of the scope, used for debug purposes.
+	name string
+
+	// The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
+	sdkKind android.SdkKind
+
+	// The option needed to passed to "hiddenapi list".
+	hiddenAPIListOption string
+}
+
+// initHiddenAPIScope initializes the scope.
+func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
+	return apiScope
+}
+
+func (l *HiddenAPIScope) String() string {
+	return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
+}
+
+var (
+	PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "public",
+		sdkKind:             android.SdkPublic,
+		hiddenAPIListOption: "--public-stub-classpath",
+	})
+	SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "system",
+		sdkKind:             android.SdkSystem,
+		hiddenAPIListOption: "--system-stub-classpath",
+	})
+	TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "test",
+		sdkKind:             android.SdkTest,
+		hiddenAPIListOption: "--test-stub-classpath",
+	})
+	CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "core-platform",
+		sdkKind:             android.SdkCorePlatform,
+		hiddenAPIListOption: "--core-platform-stub-classpath",
+	})
+
+	// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
+	// API processing.
+	//
+	// These are roughly in order from narrowest API surface to widest. Widest means the API stubs
+	// with the biggest API surface, e.g. test is wider than system is wider than public.
+	//
+	// Core platform is considered wider than system because those modules that provide core platform
+	// APIs either do not have any system APIs at all, or if they do it is because the core platform
+	// API is being converted to system APIs. In either case the system API is a subset of core
+	// platform API.
+	//
+	// This is not strictly in order from narrowest to widest as the Test API is wider than system but
+	// is neither wider or narrower than the core platform API. However, this works well enough at the
+	// moment.
+	// TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
+	hiddenAPIScopes = []*HiddenAPIScope{
+		PublicHiddenAPIScope,
+		SystemHiddenAPIScope,
+		TestHiddenAPIScope,
+		CorePlatformHiddenAPIScope,
+	}
+
+	// The HiddenAPIScope instances that are supported by a java_sdk_library.
+	//
+	// CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
+	// for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
+	hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
+		PublicHiddenAPIScope,
+		SystemHiddenAPIScope,
+		TestHiddenAPIScope,
+	}
+
+	// The HiddenAPIScope instances that are supported by the `hiddenapi list`.
+	hiddenAPIFlagScopes = []*HiddenAPIScope{
+		PublicHiddenAPIScope,
+		SystemHiddenAPIScope,
+		TestHiddenAPIScope,
+		CorePlatformHiddenAPIScope,
+	}
+)
+
 type hiddenAPIStubsDependencyTag struct {
 	blueprint.BaseDependencyTag
-	sdkKind android.SdkKind
+
+	// The api scope for which this dependency was added.
+	apiScope *HiddenAPIScope
 }
 
 func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
@@ -65,24 +153,9 @@
 var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
 var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
 
-// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
-// API processing.
-//
-// These are in order from narrowest API surface to widest. Widest means the API stubs with the
-// biggest API surface, e.g. test is wider than system is wider than public. Core platform is
-// considered wider than test even though it has no relationship with test because the libraries
-// that provide core platform API don't provide test. While the core platform API is being converted
-// to a system API the system API is still a subset of core platform.
-var hiddenAPIRelevantSdkKinds = []android.SdkKind{
-	android.SdkPublic,
-	android.SdkSystem,
-	android.SdkTest,
-	android.SdkCorePlatform,
-}
-
 // hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
 // needed to produce the hidden API monolithic stub flags file.
-func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
+func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
 	var publicStubModules []string
 	var systemStubModules []string
 	var testStubModules []string
@@ -115,22 +188,22 @@
 		testStubModules = append(testStubModules, "jacoco-stubs")
 	}
 
-	m := map[android.SdkKind][]string{}
-	m[android.SdkPublic] = publicStubModules
-	m[android.SdkSystem] = systemStubModules
-	m[android.SdkTest] = testStubModules
-	m[android.SdkCorePlatform] = corePlatformStubModules
+	m := map[*HiddenAPIScope][]string{}
+	m[PublicHiddenAPIScope] = publicStubModules
+	m[SystemHiddenAPIScope] = systemStubModules
+	m[TestHiddenAPIScope] = testStubModules
+	m[CorePlatformHiddenAPIScope] = corePlatformStubModules
 	return m
 }
 
 // hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
-// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
-// identify the source of the dependency.
-func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
+// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
+// tag to identify the source of the dependency.
+func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
 	module := ctx.Module()
-	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
-		modules := sdkKindToStubLibModules[sdkKind]
-		ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
+	for _, apiScope := range hiddenAPIScopes {
+		modules := apiScopeToStubLibModules[apiScope]
+		ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
 	}
 }
 
@@ -153,13 +226,6 @@
 	return dexJar
 }
 
-var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
-	android.SdkPublic:       "public-stub-classpath",
-	android.SdkSystem:       "system-stub-classpath",
-	android.SdkTest:         "test-stub-classpath",
-	android.SdkCorePlatform: "core-platform-stub-classpath",
-}
-
 // ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
 //
 // The rule is initialized but not built so that the caller can modify it and select an appropriate
@@ -172,11 +238,11 @@
 
 	// Find the widest API stubs provided by the fragments on which this depends, if any.
 	var dependencyStubDexJars android.Paths
-	for i := len(hiddenAPIRelevantSdkKinds) - 1; i >= 0; i-- {
-		kind := hiddenAPIRelevantSdkKinds[i]
-		stubsForKind := input.DependencyStubDexJarsByKind[kind]
-		if len(stubsForKind) != 0 {
-			dependencyStubDexJars = stubsForKind
+	for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
+		apiScope := hiddenAPIScopes[i]
+		stubsForAPIScope := input.DependencyStubDexJarsByScope[apiScope]
+		if len(stubsForAPIScope) != 0 {
+			dependencyStubDexJars = stubsForAPIScope
 			break
 		}
 	}
@@ -187,16 +253,17 @@
 		FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
 		FlagForEachInput("--boot-dex=", bootDexJars)
 
-	// Iterate over the sdk kinds in a fixed order.
-	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
-		// Merge in the stub dex jar paths for this kind from the fragments on which it depends. They
-		// will be needed to resolve dependencies from this fragment's stubs to classes in the other
-		// fragment's APIs.
-		dependencyPaths := input.DependencyStubDexJarsByKind[sdkKind]
-		paths := append(dependencyPaths, input.StubDexJarsByKind[sdkKind]...)
+	// Iterate over the api scopes in a fixed order.
+	for _, apiScope := range hiddenAPIFlagScopes {
+		// Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
+		// They will be needed to resolve dependencies from this fragment's stubs to classes in the
+		// other fragment's APIs.
+		var paths android.Paths
+		paths = append(paths, input.DependencyStubDexJarsByScope[apiScope]...)
+		paths = append(paths, input.StubDexJarsByScope[apiScope]...)
 		if len(paths) > 0 {
-			option := sdkKindToHiddenapiListOption[sdkKind]
-			command.FlagWithInputList("--"+option+"=", paths, ":")
+			option := apiScope.hiddenAPIListOption
+			command.FlagWithInputList(option+"=", paths, ":")
 		}
 	}
 
@@ -377,8 +444,8 @@
 	// that category.
 	FlagFilesByCategory FlagFilesByCategory
 
-	// The paths to the stub dex jars for each of the android.SdkKind in hiddenAPIRelevantSdkKinds.
-	TransitiveStubDexJarsByKind StubDexJarsByKind
+	// The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes.
+	TransitiveStubDexJarsByScope StubDexJarsByScope
 
 	// The output from the hidden API processing needs to be made available to other modules.
 	HiddenAPIFlagOutput
@@ -386,8 +453,8 @@
 
 func newHiddenAPIInfo() *HiddenAPIInfo {
 	info := HiddenAPIInfo{
-		FlagFilesByCategory:         FlagFilesByCategory{},
-		TransitiveStubDexJarsByKind: StubDexJarsByKind{},
+		FlagFilesByCategory:          FlagFilesByCategory{},
+		TransitiveStubDexJarsByScope: StubDexJarsByScope{},
 	}
 	return &info
 }
@@ -398,33 +465,33 @@
 	for _, fragment := range fragments {
 		if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
 			info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
-			i.TransitiveStubDexJarsByKind.append(info.TransitiveStubDexJarsByKind)
+			i.TransitiveStubDexJarsByScope.append(info.TransitiveStubDexJarsByScope)
 		}
 	}
 
 	// Dedup and sort paths.
-	i.TransitiveStubDexJarsByKind.dedupAndSort()
+	i.TransitiveStubDexJarsByScope.dedupAndSort()
 }
 
 var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
 
-// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
-// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
-type StubDexJarsByKind map[android.SdkKind]android.Paths
+// StubDexJarsByScope maps a *HiddenAPIScope to the paths to stub dex jars appropriate for that
+// scope. See hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
+type StubDexJarsByScope map[*HiddenAPIScope]android.Paths
 
-// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
+// append appends the API scope specific stub dex jar args to the corresponding scope in this
 // map.
-func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
-	for _, kind := range hiddenAPIRelevantSdkKinds {
-		s[kind] = append(s[kind], other[kind]...)
+func (s StubDexJarsByScope) append(other StubDexJarsByScope) {
+	for _, scope := range hiddenAPIScopes {
+		s[scope] = append(s[scope], other[scope]...)
 	}
 }
 
 // dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
 // deterministic order.
-func (s StubDexJarsByKind) dedupAndSort() {
-	for kind, paths := range s {
-		s[kind] = android.SortedUniquePaths(paths)
+func (s StubDexJarsByScope) dedupAndSort() {
+	for apiScope, paths := range s {
+		s[apiScope] = android.SortedUniquePaths(paths)
 	}
 }
 
@@ -435,14 +502,14 @@
 	// from the stub dex files.
 	FlagFilesByCategory FlagFilesByCategory
 
-	// StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
+	// StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
 	// the initial flags for each dex member.
-	StubDexJarsByKind StubDexJarsByKind
+	StubDexJarsByScope StubDexJarsByScope
 
-	// DependencyStubDexJarsByKind contains the stub dex jars provided by the fragments on which this
-	// depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByKind from each
+	// DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
+	// depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
 	// fragment on which this depends.
-	DependencyStubDexJarsByKind StubDexJarsByKind
+	DependencyStubDexJarsByScope StubDexJarsByScope
 
 	// RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
 	// specified in the bootclasspath_fragment's stub_libs and contents properties.
@@ -452,8 +519,9 @@
 // newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
 func newHiddenAPIFlagInput() HiddenAPIFlagInput {
 	input := HiddenAPIFlagInput{
-		FlagFilesByCategory: FlagFilesByCategory{},
-		StubDexJarsByKind:   StubDexJarsByKind{},
+		FlagFilesByCategory:          FlagFilesByCategory{},
+		StubDexJarsByScope:           StubDexJarsByScope{},
+		DependencyStubDexJarsByScope: StubDexJarsByScope{},
 	}
 
 	return input
@@ -469,7 +537,7 @@
 	// required as the whole point of adding something to the bootclasspath fragment is to add it to
 	// the bootclasspath in order to be used by something else in the system. Without any stubs it
 	// cannot do that.
-	if len(i.StubDexJarsByKind) == 0 {
+	if len(i.StubDexJarsByScope) == 0 {
 		return false
 	}
 
@@ -500,14 +568,15 @@
 //
 // That includes paths to the stub dex jars as well as paths to the *removed.txt files.
 func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
-	addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
-		dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
+	addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
+		sdkKind := apiScope.sdkKind
+		dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
 		if dexJar != nil {
-			i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
+			i.StubDexJarsByScope[apiScope] = append(i.StubDexJarsByScope[apiScope], dexJar)
 		}
 
 		if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
-			removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, kind)
+			removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
 			i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
 		}
 	}
@@ -515,11 +584,9 @@
 	// If the contents includes any java_sdk_library modules then add them to the stubs.
 	for _, module := range contents {
 		if _, ok := module.(SdkLibraryDependency); ok {
-			// Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
-			// as the java_sdk_library does not have special support for core_platform API, instead it is
-			// implemented as a customized form of SdkPublic.
-			for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
-				addFromModule(ctx, module, kind)
+			// Add information for every possible API scope needed by hidden API.
+			for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+				addFromModule(ctx, module, apiScope)
 			}
 		}
 	}
@@ -527,13 +594,14 @@
 	ctx.VisitDirectDeps(func(module android.Module) {
 		tag := ctx.OtherModuleDependencyTag(module)
 		if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
-			kind := hiddenAPIStubsTag.sdkKind
-			addFromModule(ctx, module, kind)
+			apiScope := hiddenAPIStubsTag.apiScope
+			addFromModule(ctx, module, apiScope)
 		}
 	})
 
 	// Normalize the paths, i.e. remove duplicates and sort.
-	i.StubDexJarsByKind.dedupAndSort()
+	i.StubDexJarsByScope.dedupAndSort()
+	i.DependencyStubDexJarsByScope.dedupAndSort()
 	i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
 }
 
@@ -546,9 +614,9 @@
 	}
 }
 
-func (i *HiddenAPIFlagInput) transitiveStubDexJarsByKind() StubDexJarsByKind {
-	transitive := i.DependencyStubDexJarsByKind
-	transitive.append(i.StubDexJarsByKind)
+func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByScope {
+	transitive := i.DependencyStubDexJarsByScope
+	transitive.append(i.StubDexJarsByScope)
 	return transitive
 }