Merge "Differentiate between exported and internal sdk members"
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 79d3c26..0737e5e 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -588,12 +588,13 @@
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
+			java_header_libs: ["exported-system-module"],
 			java_system_modules: ["my-system-modules"],
 		}
 
 		java_system_modules {
 			name: "my-system-modules",
-			libs: ["system-module"],
+			libs: ["system-module", "exported-system-module"],
 		}
 
 		java_library {
@@ -602,6 +603,13 @@
 			sdk_version: "none",
 			system_modules: "none",
 		}
+
+		java_library {
+			name: "exported-system-module",
+			srcs: ["Test.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
 	`)
 
 	result.CheckSnapshot("mysdk", "android_common", "",
@@ -609,35 +617,59 @@
 // This is auto-generated. DO NOT EDIT.
 
 java_import {
+    name: "mysdk_exported-system-module@current",
+    sdk_member_name: "exported-system-module",
+    jars: ["java/exported-system-module.jar"],
+}
+
+java_import {
+    name: "exported-system-module",
+    prefer: false,
+    jars: ["java/exported-system-module.jar"],
+}
+
+java_import {
     name: "mysdk_system-module@current",
     sdk_member_name: "system-module",
+    visibility: ["//visibility:private"],
     jars: ["java/system-module.jar"],
 }
 
 java_import {
-    name: "system-module",
+    name: "mysdk_system-module",
     prefer: false,
+    visibility: ["//visibility:private"],
     jars: ["java/system-module.jar"],
 }
 
 java_system_modules_import {
     name: "mysdk_my-system-modules@current",
     sdk_member_name: "my-system-modules",
-    libs: ["mysdk_system-module@current"],
+    libs: [
+        "mysdk_system-module@current",
+        "mysdk_exported-system-module@current",
+    ],
 }
 
 java_system_modules_import {
     name: "my-system-modules",
     prefer: false,
-    libs: ["system-module"],
+    libs: [
+        "mysdk_system-module",
+        "exported-system-module",
+    ],
 }
 
 sdk_snapshot {
     name: "mysdk@current",
+    java_header_libs: ["mysdk_exported-system-module@current"],
     java_system_modules: ["mysdk_my-system-modules@current"],
 }
 `),
-		checkAllCopyRules(".intermediates/system-module/android_common/turbine-combined/system-module.jar -> java/system-module.jar"),
+		checkAllCopyRules(`
+.intermediates/exported-system-module/android_common/turbine-combined/exported-system-module.jar -> java/exported-system-module.jar
+.intermediates/system-module/android_common/turbine-combined/system-module.jar -> java/system-module.jar
+`),
 	)
 }
 
@@ -677,14 +709,16 @@
 java_import {
     name: "mysdk_system-module@current",
     sdk_member_name: "system-module",
+    visibility: ["//visibility:private"],
     device_supported: false,
     host_supported: true,
     jars: ["java/system-module.jar"],
 }
 
 java_import {
-    name: "system-module",
+    name: "mysdk_system-module",
     prefer: false,
+    visibility: ["//visibility:private"],
     device_supported: false,
     host_supported: true,
     jars: ["java/system-module.jar"],
@@ -703,7 +737,7 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
-    libs: ["system-module"],
+    libs: ["mysdk_system-module"],
 }
 
 sdk_snapshot {
diff --git a/sdk/sdk.go b/sdk/sdk.go
index f22763c..dbe9ce2 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -50,6 +50,9 @@
 	// list properties, e.g. java_libs.
 	dynamicMemberTypeListProperties interface{}
 
+	// The set of exported members.
+	exportedMembers map[string]struct{}
+
 	properties sdkProperties
 
 	snapshotFile android.OptionalPath
@@ -217,6 +220,33 @@
 	return s
 }
 
+func (s *sdk) memberListProperties() []*sdkMemberListProperty {
+	return s.dynamicSdkMemberTypes.memberListProperties
+}
+
+func (s *sdk) getExportedMembers() map[string]struct{} {
+	if s.exportedMembers == nil {
+		// Collect all the exported members.
+		s.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 {
+				s.exportedMembers[name] = struct{}{}
+			}
+		}
+	}
+
+	return s.exportedMembers
+}
+
+func (s *sdk) isInternalMember(memberName string) bool {
+	_, ok := s.getExportedMembers()[memberName]
+	return !ok
+}
+
 func (s *sdk) snapshot() bool {
 	return s.properties.Snapshot
 }
@@ -290,7 +320,7 @@
 // Step 1: create dependencies from an SDK module to its members.
 func memberMutator(mctx android.BottomUpMutatorContext) {
 	if s, ok := mctx.Module().(*sdk); ok {
-		for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+		for _, memberListProperty := range s.memberListProperties() {
 			names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
 			tag := memberListProperty.dependencyTag
 			memberListProperty.memberType.AddDependencies(mctx, tag, names)
diff --git a/sdk/update.go b/sdk/update.go
index 9032d1f..ff567be 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -130,7 +130,9 @@
 				byType[memberType] = append(byType[memberType], member)
 			}
 
-			member.variants = append(member.variants, child.(android.SdkAware))
+			// Only append new variants to the list. This is needed because a member can be both
+			// exported by the sdk and also be a transitive sdk member.
+			member.variants = appendUniqueVariants(member.variants, child.(android.SdkAware))
 
 			// If the member type supports transitive sdk members then recurse down into
 			// its dependencies, otherwise exit traversal.
@@ -141,7 +143,7 @@
 	})
 
 	var members []*sdkMember
-	for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+	for _, memberListProperty := range s.memberListProperties() {
 		membersOfType := byType[memberListProperty.memberType]
 		members = append(members, membersOfType...)
 	}
@@ -149,6 +151,15 @@
 	return members
 }
 
+func appendUniqueVariants(variants []android.SdkAware, newVariant android.SdkAware) []android.SdkAware {
+	for _, v := range variants {
+		if v == newVariant {
+			return variants
+		}
+	}
+	return append(variants, newVariant)
+}
+
 // SDK directory structure
 // <sdk_root>/
 //     Android.bp   : definition of a 'sdk' module is here. This is a hand-made one.
@@ -203,17 +214,20 @@
 	// Create a transformer that will transform an unversioned module into a versioned module.
 	unversionedToVersionedTransformer := unversionedToVersionedTransformation{builder: builder}
 
+	// Create a transformer that will transform an unversioned module by replacing any references
+	// to internal members with a unique module name and setting prefer: false.
+	unversionedTransformer := unversionedTransformation{builder: builder}
+
 	for _, unversioned := range builder.prebuiltOrder {
 		// Copy the unversioned module so it can be modified to make it versioned.
 		versioned := unversioned.deepCopy()
 
 		// Transform the unversioned module into a versioned one.
 		versioned.transform(unversionedToVersionedTransformer)
-
 		bpFile.AddModule(versioned)
 
-		// Set prefer: false - this is not strictly required as that is the default.
-		unversioned.insertAfter("name", "prefer", false)
+		// Transform the unversioned module to make it suitable for use in the snapshot.
+		unversioned.transform(unversionedTransformer)
 		bpFile.AddModule(unversioned)
 	}
 
@@ -235,7 +249,7 @@
 	}
 
 	addHostDeviceSupportedProperties(&s.ModuleBase, snapshotModule)
-	for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+	for _, memberListProperty := range s.memberListProperties() {
 		names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
 		if len(names) > 0 {
 			snapshotModule.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names))
@@ -319,6 +333,30 @@
 	}
 }
 
+type unversionedTransformation struct {
+	identityTransformation
+	builder *snapshotBuilder
+}
+
+func (t unversionedTransformation) transformModule(module *bpModule) *bpModule {
+	// If the module is an internal member then use a unique name for it.
+	name := module.getValue("name").(string)
+	module.setProperty("name", t.builder.unversionedSdkMemberName(name))
+
+	// Set prefer: false - this is not strictly required as that is the default.
+	module.insertAfter("name", "prefer", false)
+
+	return module
+}
+
+func (t unversionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+	if tag == sdkMemberReferencePropertyTag {
+		return t.builder.unversionedSdkMemberNames(value.([]string)), tag
+	} else {
+		return value, tag
+	}
+}
+
 func generateBpContents(contents *generatedContents, bpFile *bpFile) {
 	contents.Printfln("// This is auto-generated. DO NOT EDIT.")
 	for _, bpModule := range bpFile.order {
@@ -442,11 +480,17 @@
 	m := s.bpFile.newModule(moduleType)
 	m.AddProperty("name", name)
 
-	// Extract visibility information from a member variant. All variants have the same
-	// visibility so it doesn't matter which one is used.
-	visibility := android.EffectiveVisibilityRules(s.ctx, member.Variants()[0])
-	if len(visibility) != 0 {
-		m.AddProperty("visibility", visibility)
+	if s.sdk.isInternalMember(name) {
+		// An internal member is only referenced from the sdk snapshot which is in the
+		// same package so can be marked as private.
+		m.AddProperty("visibility", []string{"//visibility:private"})
+	} else {
+		// Extract visibility information from a member variant. All variants have the same
+		// visibility so it doesn't matter which one is used.
+		visibility := android.EffectiveVisibilityRules(s.ctx, member.Variants()[0])
+		if len(visibility) != 0 {
+			m.AddProperty("visibility", visibility)
+		}
 	}
 
 	addHostDeviceSupportedProperties(&s.sdk.ModuleBase, m)
@@ -482,6 +526,23 @@
 	return references
 }
 
+// Get an internal name unique to the sdk.
+func (s *snapshotBuilder) unversionedSdkMemberName(unversionedName string) string {
+	if s.sdk.isInternalMember(unversionedName) {
+		return s.ctx.ModuleName() + "_" + unversionedName
+	} else {
+		return unversionedName
+	}
+}
+
+func (s *snapshotBuilder) unversionedSdkMemberNames(members []string) []string {
+	var references []string = nil
+	for _, m := range members {
+		references = append(references, s.unversionedSdkMemberName(m))
+	}
+	return references
+}
+
 var _ android.SdkMember = (*sdkMember)(nil)
 
 type sdkMember struct {