Merge "Fix bootDexJarByModule with UNSAFE_DISABLE_HIDDENAPI_FLAGS" into sc-dev
diff --git a/android/deapexer.go b/android/deapexer.go
index f3c541c..de3f635 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -55,9 +55,9 @@
 //
 // The files that are passed to `deapexer` and those that are passed back have a unique identifier
 // that links them together. e.g. If the `deapexer` is passed something like this:
-//     core-libart{.dexjar} -> javalib/core-libart.jar
+//     javalib/core-libart.jar -> javalib/core-libart.jar
 // it will return something like this:
-//     core-libart{.dexjar} -> out/soong/.....deapexer.../javalib/core-libart.jar
+//     javalib/core-libart.jar -> out/soong/.....deapexer.../javalib/core-libart.jar
 //
 // The reason why the `deapexer` module is separate from the prebuilt_apex/apex_set is to avoid
 // cycles. e.g.
@@ -70,7 +70,7 @@
 // The information exported by the `deapexer` module, access it using `DeapxerInfoProvider`.
 type DeapexerInfo struct {
 	// map from the name of an exported file from a prebuilt_apex to the path to that file. The
-	// exported file name is of the form <module>{<tag>}.
+	// exported file name is the apex relative path, e.g. javalib/core-libart.jar.
 	//
 	// See Prebuilt.ApexInfoMutator for more information.
 	exports map[string]Path
@@ -79,15 +79,11 @@
 // PrebuiltExportPath provides the path, or nil if not available, of a file exported from the
 // prebuilt_apex that created this ApexInfo.
 //
-// The exported file is identified by the module name and the tag:
-// * The module name is the name of the module that contributed the file when the .apex file
-//   referenced by the prebuilt_apex was built. It must be specified in one of the exported_...
-//   properties on the prebuilt_apex module.
-// * The tag identifies the type of file and is dependent on the module type.
+// The exported file is identified by the apex relative path, e.g. "javalib/core-libart.jar".
 //
 // See apex/deapexer.go for more information.
-func (i DeapexerInfo) PrebuiltExportPath(name, tag string) Path {
-	path := i.exports[name+"{"+tag+"}"]
+func (i DeapexerInfo) PrebuiltExportPath(apexRelativePath string) Path {
+	path := i.exports[apexRelativePath]
 	return path
 }
 
@@ -120,11 +116,20 @@
 // RequiredFilesFromPrebuiltApex must be implemented by modules that require files to be exported
 // from a prebuilt_apex/apex_set.
 type RequiredFilesFromPrebuiltApex interface {
-	// RequiredFilesFromPrebuiltApex returns a map from the key (module name plus tag) to the required
-	// path of the file within the prebuilt .apex file.
+	// RequiredFilesFromPrebuiltApex returns a list of the file paths (relative to the root of the
+	// APEX's contents) that the implementing module requires from within a prebuilt .apex file.
 	//
-	// For each key/file pair this will cause the file to be extracted out of the prebuilt .apex file,
-	// and the path to the extracted file will be stored in the DeapexerInfo using that key, The path
-	// can then be retrieved using the PrebuiltExportPath(name, tag) method.
-	RequiredFilesFromPrebuiltApex(ctx BaseModuleContext) map[string]string
+	// For each file path this will cause the file to be extracted out of the prebuilt .apex file, and
+	// the path to the extracted file will be stored in the DeapexerInfo using the APEX relative file
+	// path as the key, The path can then be retrieved using the PrebuiltExportPath(key) method.
+	RequiredFilesFromPrebuiltApex(ctx BaseModuleContext) []string
+}
+
+// Marker interface that identifies dependencies on modules that may require files from a prebuilt
+// apex.
+type RequiresFilesFromPrebuiltApexTag interface {
+	blueprint.DependencyTag
+
+	// Method that differentiates this interface from others.
+	RequiresFilesFromPrebuiltApex()
 }
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 9088c49..c70da15 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -40,16 +40,6 @@
 // This is intentionally not registered by name as it is not intended to be used from within an
 // `Android.bp` file.
 
-// DeapexerExportedFile defines the properties needed to expose a file from the deapexer module.
-type DeapexerExportedFile struct {
-	// The tag parameter which must be passed to android.DeapexerInfo's PrebuiltExportPath(name, tag)
-	// method to retrieve the path to the unpacked file.
-	Tag string
-
-	// The path within the APEX that needs to be exported.
-	Path string `android:"path"`
-}
-
 // DeapexerProperties specifies the properties supported by the deapexer module.
 //
 // As these are never intended to be supplied in a .bp file they use a different naming convention
@@ -62,7 +52,9 @@
 	CommonModules []string
 
 	// List of files exported from the .apex file by this module
-	ExportedFiles []DeapexerExportedFile
+	//
+	// Each entry is a path from the apex root, e.g. javalib/core-libart.jar.
+	ExportedFiles []string
 }
 
 type SelectedApexProperties struct {
@@ -107,27 +99,23 @@
 
 	exports := make(map[string]android.Path)
 
-	// Create mappings from name+tag to all the required exported paths.
-	for _, e := range p.properties.ExportedFiles {
-		tag := e.Tag
-		path := e.Path
-
+	// Create mappings from apex relative path to the extracted file's path.
+	exportedPaths := make(android.Paths, 0, len(exports))
+	for _, path := range p.properties.ExportedFiles {
 		// Populate the exports that this makes available.
-		exports[tag] = deapexerOutput.Join(ctx, path)
+		extractedPath := deapexerOutput.Join(ctx, path)
+		exports[path] = extractedPath
+		exportedPaths = append(exportedPaths, extractedPath)
 	}
 
 	// If the prebuilt_apex exports any files then create a build rule that unpacks the apex using
 	// deapexer and verifies that all the required files were created. Also, make the mapping from
-	// name+tag to path available for other modules.
+	// apex relative path to extracted file path available for other modules.
 	if len(exports) > 0 {
 		// Make the information available for other modules.
 		ctx.SetProvider(android.DeapexerProvider, android.NewDeapexerInfo(exports))
 
 		// Create a sorted list of the files that this exports.
-		exportedPaths := make(android.Paths, 0, len(exports))
-		for _, p := range exports {
-			exportedPaths = append(exportedPaths, p)
-		}
 		exportedPaths = android.SortedUniquePaths(exportedPaths)
 
 		// The apex needs to export some files so create a ninja rule to unpack the apex and check that
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index d486776..9504b07 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -17,7 +17,6 @@
 import (
 	"fmt"
 	"io"
-	"path/filepath"
 	"strconv"
 	"strings"
 
@@ -554,35 +553,24 @@
 
 	// Compute the deapexer properties from the transitive dependencies of this module.
 	commonModules := []string{}
-	exportedFilesByKey := map[string]string{}
-	requiringModulesByKey := map[string]android.Module{}
+	exportedFiles := []string{}
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		tag := ctx.OtherModuleDependencyTag(child)
 
+		// If the child is not in the same apex as the parent then ignore it and all its children.
+		if !android.IsDepInSameApex(ctx, parent, child) {
+			return false
+		}
+
 		name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child))
-		if java.IsBootclasspathFragmentContentDepTag(tag) || tag == exportedJavaLibTag {
-			commonModules = append(commonModules, name)
-
-			// Add the dex implementation jar to the set of exported files. The path here must match the
-			// path of the file in the APEX created by apexFileForJavaModule(...).
-			exportedFilesByKey[name+"{.dexjar}"] = filepath.Join("javalib", name+".jar")
-
-		} else if tag == exportedBootclasspathFragmentTag {
+		if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok {
 			commonModules = append(commonModules, name)
 
 			requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx)
-			for k, v := range requiredFiles {
-				if f, ok := exportedFilesByKey[k]; ok && f != v {
-					otherModule := requiringModulesByKey[k]
-					ctx.ModuleErrorf("inconsistent paths have been requested for key %q, %s requires path %s while %s requires path %s",
-						k, child, v, otherModule, f)
-					continue
-				}
-				exportedFilesByKey[k] = v
-				requiringModulesByKey[k] = child
-			}
+			exportedFiles = append(exportedFiles, requiredFiles...)
 
-			// Make sure to visit the children of the bootclasspath_fragment.
+			// Visit the dependencies of this module just in case they also require files from the
+			// prebuilt apex.
 			return true
 		}
 
@@ -597,12 +585,7 @@
 	}
 
 	// Populate the exported files property in a fixed order.
-	for _, tag := range android.SortedStringKeys(exportedFilesByKey) {
-		deapexerProperties.ExportedFiles = append(deapexerProperties.ExportedFiles, DeapexerExportedFile{
-			Tag:  tag,
-			Path: exportedFilesByKey[tag],
-		})
-	}
+	deapexerProperties.ExportedFiles = android.SortedUniqueStrings(exportedFiles)
 
 	props := struct {
 		Name          *string
@@ -659,6 +642,10 @@
 // incorrectly.
 func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {}
 
+func (t exportedDependencyTag) RequiresFilesFromPrebuiltApex() {}
+
+var _ android.RequiresFilesFromPrebuiltApexTag = exportedDependencyTag{}
+
 var (
 	exportedJavaLibTag               = exportedDependencyTag{name: "exported_java_libs"}
 	exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 4d00587..03faf34 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -81,6 +81,9 @@
 // they were listed in java_libs.
 func (b bootclasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {}
 
+// Contents of bootclasspath fragments require files from prebuilt apex files.
+func (b bootclasspathFragmentContentDependencyTag) RequiresFilesFromPrebuiltApex() {}
+
 // The tag used for the dependency between the bootclasspath_fragment module and its contents.
 var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{}
 
@@ -88,6 +91,7 @@
 var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag
 var _ android.SdkMemberTypeDependencyTag = bootclasspathFragmentContentDepTag
 var _ android.CopyDirectlyInAnyApexTag = bootclasspathFragmentContentDepTag
+var _ android.RequiresFilesFromPrebuiltApexTag = bootclasspathFragmentContentDepTag
 
 func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool {
 	return tag == bootclasspathFragmentContentDepTag
@@ -926,13 +930,12 @@
 	}
 
 	di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
-	name := module.BaseModuleName()
 	for _, variant := range imageConfig.apexVariants() {
 		arch := variant.target.Arch.ArchType
 		for _, toPath := range variant.imagesDeps {
+			apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
 			// Get the path to the file that the deapexer extracted from the prebuilt apex file.
-			tag := createBootImageTag(arch, toPath.Base())
-			fromPath := di.PrebuiltExportPath(name, tag)
+			fromPath := di.PrebuiltExportPath(apexRelativePath)
 
 			// Copy the file to the predefined location.
 			ctx.Build(pctx, android.BuildParams{
@@ -963,19 +966,16 @@
 //
 // If there is no image config associated with this fragment then it returns nil. Otherwise, it
 // returns the files that are listed in the image config.
-func (module *prebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) map[string]string {
+func (module *prebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
 	imageConfig := module.getImageConfig(ctx)
 	if imageConfig != nil {
 		// Add the boot image files, e.g. .art, .oat and .vdex files.
-		files := map[string]string{}
-		name := module.BaseModuleName()
+		files := []string{}
 		for _, variant := range imageConfig.apexVariants() {
 			arch := variant.target.Arch.ArchType
 			for _, path := range variant.imagesDeps.Paths() {
 				base := path.Base()
-				tag := createBootImageTag(arch, base)
-				key := fmt.Sprintf("%s{%s}", name, tag)
-				files[key] = filepath.Join("javalib", arch.String(), base)
+				files = append(files, apexRootRelativePathToBootImageFile(arch, base))
 			}
 		}
 		return files
@@ -983,6 +983,10 @@
 	return nil
 }
 
+func apexRootRelativePathToBootImageFile(arch android.ArchType, base string) string {
+	return filepath.Join("javalib", arch.String(), base)
+}
+
 var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltBootclasspathFragmentModule)(nil)
 
 func prebuiltBootclasspathFragmentFactory() android.Module {
diff --git a/java/java.go b/java/java.go
index 2bbb5b1..ae8adf2 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1309,7 +1309,7 @@
 
 			// Get the path of the dex implementation jar from the `deapexer` module.
 			di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
-			if dexOutputPath := di.PrebuiltExportPath(j.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
+			if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(j.BaseModuleName())); dexOutputPath != nil {
 				j.dexJarFile = dexOutputPath
 
 				// Initialize the hiddenapi structure.
@@ -1426,6 +1426,29 @@
 	return nil
 }
 
+// requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or
+// java_sdk_library_import with the specified base module name requires to be exported from a
+// prebuilt_apex/apex_set.
+func requiredFilesFromPrebuiltApexForImport(name string) []string {
+	// Add the dex implementation jar to the set of exported files.
+	return []string{
+		apexRootRelativePathToJavaLib(name),
+	}
+}
+
+// apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
+// the java library with the specified name.
+func apexRootRelativePathToJavaLib(name string) string {
+	return filepath.Join("javalib", name+".jar")
+}
+
+var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil)
+
+func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string {
+	name := j.BaseModuleName()
+	return requiredFilesFromPrebuiltApexForImport(name)
+}
+
 // Add compile time check for interface implementation
 var _ android.IDEInfo = (*Import)(nil)
 var _ android.IDECustomizedModuleName = (*Import)(nil)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 133deda..1213d3f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2140,7 +2140,7 @@
 
 			// Get the path of the dex implementation jar from the `deapexer` module.
 			di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
-			if dexOutputPath := di.PrebuiltExportPath(module.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
+			if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(module.BaseModuleName())); dexOutputPath != nil {
 				module.dexJarFile = dexOutputPath
 				module.initHiddenAPI(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
 			} else {
@@ -2265,6 +2265,13 @@
 	}
 }
 
+var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil)
+
+func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
+	name := module.BaseModuleName()
+	return requiredFilesFromPrebuiltApexForImport(name)
+}
+
 //
 // java_sdk_library_xml
 //