Merge changes I831da5fa,I866916c9 am: c66769ddd9

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1579441

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Icae891ef2e16df3db3ac4c4d9f670cda89c5cc57
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 069595e..1651c1c 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -28,9 +28,27 @@
 }, "outFlag", "stubAPIFlags")
 
 type hiddenAPI struct {
-	// True if the module containing this structure contributes to the hiddenapi information.
+	// The name of the module as it would be used in the boot jars configuration, e.g. without any
+	// prebuilt_ prefix (if it is a prebuilt), without any "-hiddenapi" suffix if it just provides
+	// annotations and without any ".impl" suffix if it is a java_sdk_library implementation library.
+	configurationName string
+
+	// True if the module containing this structure contributes to the hiddenapi information or has
+	// that information encoded within it.
 	active bool
 
+	// Identifies the active module variant which will be used as the source of hiddenapi information.
+	//
+	// A class may be compiled into a number of different module variants each of which will need the
+	// hiddenapi information encoded into it and so will be marked as active. However, only one of
+	// them must be used as a source of information by hiddenapi otherwise it will end up with
+	// duplicate entries. That module will have primary=true.
+	//
+	// Note, that modules <x>-hiddenapi that provide additional annotation information for module <x>
+	// that is on the bootclasspath are marked as primary=true as they are the primary source of that
+	// annotation information.
+	primary bool
+
 	// True if the module only contains additional annotations and so does not require hiddenapi
 	// information to be encoded in its dex file and should not be used to generate the
 	// hiddenAPISingletonPathsStruct.stubFlags file.
@@ -109,18 +127,45 @@
 
 	// Modules whose names are of the format <x>-hiddenapi provide hiddenapi information for the boot
 	// jar module <x>. Otherwise, the module provides information for itself. Either way extract the
-	// name of the boot jar module.
-	bootJarName := strings.TrimSuffix(name, "-hiddenapi")
+	// configurationName of the boot jar module.
+	configurationName := strings.TrimSuffix(name, "-hiddenapi")
+	h.configurationName = configurationName
 
 	// It is important that hiddenapi information is only gathered for/from modules that are actually
 	// on the boot jars list because the runtime only enforces access to the hidden API for the
 	// bootclassloader. If information is gathered for modules not on the list then that will cause
 	// failures in the CtsHiddenApiBlocklist... tests.
-	h.active = inList(bootJarName, ctx.Config().BootJars())
+	h.active = inList(configurationName, ctx.Config().BootJars())
+	if !h.active {
+		// The rest of the properties will be ignored if active is false.
+		return
+	}
 
 	// If this module has a suffix of -hiddenapi then it only provides additional annotation
 	// information for a module on the boot jars list.
 	h.annotationsOnly = strings.HasSuffix(name, "-hiddenapi")
+
+	// Determine whether this module is the primary module or not.
+	primary := true
+
+	// A prebuilt module is only primary if it is preferred and conversely a source module is only
+	// primary if it has not been replaced by a prebuilt module.
+	module := ctx.Module()
+	if pi, ok := module.(android.PrebuiltInterface); ok {
+		if p := pi.Prebuilt(); p != nil {
+			primary = p.UsePrebuilt()
+		}
+	} else {
+		// The only module that will pass a different name to its module name to this method is the
+		// implementation library of a java_sdk_library. It has a configuration name of <x> the same
+		// as its parent java_sdk_library but a module name of <x>.impl. It is not the primary module,
+		// the java_sdk_library with the name of <x> is.
+		primary = name == ctx.ModuleName()
+
+		// A source module that has been replaced by a prebuilt can never be the primary module.
+		primary = primary && !module.IsReplacedByPrebuilt()
+	}
+	h.primary = primary
 }
 
 // hiddenAPIExtractAndEncode is called by any module that could contribute to the hiddenapi
@@ -137,17 +182,17 @@
 // 3. Conditionally creates a copy of the supplied dex file into which it has encoded the hiddenapi
 //    flags and returns this instead of the supplied dex jar, otherwise simply returns the supplied
 //    dex jar.
-func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, name string, primary bool, dexJar android.OutputPath,
+func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, dexJar android.OutputPath,
 	implementationJar android.Path, uncompressDex bool) android.OutputPath {
 
 	if !h.active {
 		return dexJar
 	}
 
-	h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar, primary)
+	h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar)
 
 	if !h.annotationsOnly {
-		hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar").OutputPath
+		hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
 
 		// Create a copy of the dex jar which has been encoded with hiddenapi flags.
 		hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
@@ -164,7 +209,7 @@
 //
 // It also makes the dex jar available for use when generating the
 // hiddenAPISingletonPathsStruct.stubFlags.
-func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJar, classesJar android.Path, primary bool) {
+func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJar, classesJar android.Path) {
 	if !h.active {
 		return
 	}
@@ -172,7 +217,7 @@
 	// More than one library with the same classes may need to be encoded but only one should be
 	// used as a source of information for hidden API processing otherwise it will result in
 	// duplicate entries in the files.
-	if !primary {
+	if !h.primary {
 		return
 	}
 
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 77cfff4..df825bb 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -84,6 +84,12 @@
 			compile_dex: true,
 		}
 
+		java_library {
+			name: "foo-hiddenapi",
+			srcs: ["a.java"],
+			compile_dex: true,
+		}
+
 		java_import {
 			name: "foo",
 			jars: ["a.jar"],
@@ -102,6 +108,7 @@
 	indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index")
 	CheckHiddenAPIRuleInputs(t, `
 .intermediates/bar/android_common/hiddenapi/index.csv
+.intermediates/foo-hiddenapi/android_common/hiddenapi/index.csv
 .intermediates/foo/android_common/hiddenapi/index.csv
 `,
 		indexRule)
diff --git a/java/java.go b/java/java.go
index 8cf4ee5..4c6009b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1798,14 +1798,8 @@
 			return
 		}
 
-		configurationName := j.ConfigurationName()
-		primary := configurationName == ctx.ModuleName()
-		// If the prebuilt is being used rather than the from source, skip this
-		// module to prevent duplicated classes
-		primary = primary && !j.IsReplacedByPrebuilt()
-
 		// Hidden API CSV generation and dex encoding
-		dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile,
+		dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
 			proptools.Bool(j.dexProperties.Uncompress_dex))
 
 		// merge dex jar with resources if necessary
@@ -2917,9 +2911,6 @@
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
 
 	if ctx.Device() {
-		configurationName := j.BaseModuleName()
-		primary := j.Prebuilt().UsePrebuilt()
-
 		// If this is a variant created for a prebuilt_apex then use the dex implementation jar
 		// obtained from the associated deapexer module.
 		ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
@@ -2935,7 +2926,7 @@
 			di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
 			if dexOutputPath := di.PrebuiltExportPath(j.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
 				j.dexJarFile = dexOutputPath
-				j.hiddenAPI.hiddenAPIExtractInformation(ctx, dexOutputPath, outputFile, primary)
+				j.hiddenAPIExtractInformation(ctx, dexOutputPath, outputFile)
 			} else {
 				// This should never happen as a variant for a prebuilt_apex is only created if the
 				// prebuilt_apex has been configured to export the java library dex file.
@@ -2967,7 +2958,7 @@
 			}
 
 			// Hidden API CSV generation and dex encoding
-			dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, configurationName, primary, dexOutputFile, outputFile,
+			dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, outputFile,
 				proptools.Bool(j.dexProperties.Uncompress_dex))
 
 			j.dexJarFile = dexOutputFile