Allow exporting of sdk members to be done per tag

Previously, every module added to an sdk directly through one of the
SdkMemberType specific properties, e.g. java_libs, was exported and
every module added automatically via a transitive dependencies was not
exported. This change allows that behavior to be customized per tag.

Bug: 186290299
Test: m art-module-sdk
      - verify that this change does not affect its contents.
Change-Id: I563b5bcd823e61c23cdb706cfcbb13337963d550
diff --git a/android/sdk.go b/android/sdk.go
index f2cdc88..b4ef8aa 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -281,10 +281,31 @@
 	Variants() []SdkAware
 }
 
+// SdkMemberTypeDependencyTag is the interface that a tag must implement in order to allow the
+// dependent module to be automatically added to the sdk. In order for this to work the
+// SdkMemberType of the depending module must return true from
+// SdkMemberType.HasTransitiveSdkMembers.
 type SdkMemberTypeDependencyTag interface {
 	blueprint.DependencyTag
 
+	// SdkMemberType returns the SdkMemberType that will be used to automatically add the child module
+	// to the sdk.
 	SdkMemberType() SdkMemberType
+
+	// ExportMember determines whether a module added to the sdk through this tag will be exported
+	// from the sdk or not.
+	//
+	// An exported member is added to the sdk using its own name, e.g. if "foo" was exported from sdk
+	// "bar" then its prebuilt would be simply called "foo". A member can be added to the sdk via
+	// multiple tags and if any of those tags returns true from this method then the membe will be
+	// exported. Every module added directly to the sdk via one of the member type specific
+	// properties, e.g. java_libs, will automatically be exported.
+	//
+	// If a member is not exported then it is treated as an internal implementation detail of the
+	// sdk and so will be added with an sdk specific name. e.g. if "foo" was an internal member of sdk
+	// "bar" then its prebuilt would be called "bar_foo". Additionally its visibility will be set to
+	// "//visibility:private" so it will not be accessible from outside its Android.bp file.
+	ExportMember() bool
 }
 
 var _ SdkMemberTypeDependencyTag = (*sdkMemberDependencyTag)(nil)
@@ -293,20 +314,28 @@
 type sdkMemberDependencyTag struct {
 	blueprint.BaseDependencyTag
 	memberType SdkMemberType
+	export     bool
 }
 
 func (t *sdkMemberDependencyTag) SdkMemberType() SdkMemberType {
 	return t.memberType
 }
 
+func (t *sdkMemberDependencyTag) ExportMember() bool {
+	return t.export
+}
+
 // Prevent dependencies from the sdk/module_exports onto their members from being
 // replaced with a preferred prebuilt.
 func (t *sdkMemberDependencyTag) ReplaceSourceWithPrebuilt() bool {
 	return false
 }
 
-func DependencyTagForSdkMemberType(memberType SdkMemberType) SdkMemberTypeDependencyTag {
-	return &sdkMemberDependencyTag{memberType: memberType}
+// DependencyTagForSdkMemberType creates an SdkMemberTypeDependencyTag that will cause any
+// dependencies added by the tag to be added to the sdk as the specified SdkMemberType and exported
+// (or not) as specified by the export parameter.
+func DependencyTagForSdkMemberType(memberType SdkMemberType, export bool) SdkMemberTypeDependencyTag {
+	return &sdkMemberDependencyTag{memberType: memberType, export: export}
 }
 
 // Interface that must be implemented for every type that can be a member of an
diff --git a/java/system_modules.go b/java/system_modules.go
index 320a2bb..a09778c 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -77,8 +77,9 @@
 		"classpath", "outDir", "workDir")
 
 	// Dependency tag that causes the added dependencies to be added as java_header_libs
-	// to the sdk/module_exports/snapshot.
-	systemModulesLibsTag = android.DependencyTagForSdkMemberType(javaHeaderLibsSdkMemberType)
+	// to the sdk/module_exports/snapshot. Dependencies that are added automatically via this tag are
+	// not automatically exported.
+	systemModulesLibsTag = android.DependencyTagForSdkMemberType(javaHeaderLibsSdkMemberType, false)
 )
 
 func TransformJarsToSystemModules(ctx android.ModuleContext, jars android.Paths) (android.Path, android.Paths) {
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 710c1f2..1c6002a 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -193,7 +193,8 @@
 
 			memberType: memberType,
 
-			dependencyTag: android.DependencyTagForSdkMemberType(memberType),
+			// Dependencies added directly from member properties are always exported.
+			dependencyTag: android.DependencyTagForSdkMemberType(memberType, true),
 		}
 
 		listProperties = append(listProperties, memberListProperty)
@@ -255,22 +256,6 @@
 	return s.dynamicSdkMemberTypes.memberListProperties
 }
 
-func (s *sdk) getExportedMembers() map[string]struct{} {
-	// Collect all the exported members.
-	exportedMembers := make(map[string]struct{})
-
-	for _, memberListProperty := range s.memberListProperties() {
-		names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
-
-		// Every member specified explicitly in the properties is exported by the sdk.
-		for _, name := range names {
-			exportedMembers[name] = struct{}{}
-		}
-	}
-
-	return exportedMembers
-}
-
 func (s *sdk) snapshot() bool {
 	return s.properties.Snapshot
 }
diff --git a/sdk/update.go b/sdk/update.go
index 8b75da2..43ec926 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -130,7 +130,8 @@
 			// Keep track of which multilib variants are used by the sdk.
 			s.multilibUsages = s.multilibUsages.addArchType(child.Target().Arch.ArchType)
 
-			s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{memberType, child.(android.SdkAware)})
+			export := memberTag.ExportMember()
+			s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{memberType, child.(android.SdkAware), export})
 
 			// If the member type supports transitive sdk members then recurse down into
 			// its dependencies, otherwise exit traversal.
@@ -226,12 +227,12 @@
 		// Record the names of all the members, both explicitly specified and implicitly
 		// included.
 		for _, memberVariantDep := range sdkVariant.memberVariantDeps {
-			allMembersByName[memberVariantDep.variant.Name()] = struct{}{}
-		}
+			name := memberVariantDep.variant.Name()
+			allMembersByName[name] = struct{}{}
 
-		// Merge the exported member sets from all sdk variants.
-		for key, _ := range sdkVariant.getExportedMembers() {
-			exportedMembersByName[key] = struct{}{}
+			if memberVariantDep.export {
+				exportedMembersByName[name] = struct{}{}
+			}
 		}
 	}
 
@@ -944,6 +945,7 @@
 type sdkMemberVariantDep struct {
 	memberType android.SdkMemberType
 	variant    android.SdkAware
+	export     bool
 }
 
 var _ android.SdkMember = (*sdkMember)(nil)