Add better error handling to bootDexJar function

aosp/2876754 missed adding error handling to one of the places which
consumes the dex jar deapexed from prebuilt apexes. This CL ensures that
when we have multiple prebuilt apexes _without_ flagging, the hiddenapi
processing code emits a more descriptive error "Multiple deapxers..."
rather than a cryptic error "<module> does not provide a dex jar"

Test: m nothing --no-skip-soong-tests

Change-Id: I80849fa7cca17d724ac53c94bb353b169175ee28
diff --git a/apex/apex_test.go b/apex/apex_test.go
index a943e4e..ff9e770 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6127,6 +6127,84 @@
 			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
 		`)
 	})
+
+	t.Run("Co-existing unflagged apexes should create a duplicate deapexer error in hiddenapi processing", func(t *testing.T) {
+		bp := `
+		// Source
+		apex {
+			name: "myapex",
+			enabled: false,
+			key: "myapex.key",
+			bootclasspath_fragments: ["my-bootclasspath-fragment"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		// Prebuilt
+		prebuilt_apex {
+			name: "myapex.v1",
+			source_apex_name: "myapex",
+			arch: {
+				arm64: {
+					src: "myapex-arm64.apex",
+				},
+				arm: {
+					src: "myapex-arm.apex",
+				},
+			},
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+			prefer: true,
+		}
+		prebuilt_apex {
+			name: "myapex.v2",
+			source_apex_name: "myapex",
+			arch: {
+				arm64: {
+					src: "myapex-arm64.apex",
+				},
+				arm: {
+					src: "myapex-arm.apex",
+				},
+			},
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+			prefer: true,
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["libfoo", "libbar"],
+			apex_available: ["myapex"],
+			hidden_api: {
+				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+				metadata: "my-bootclasspath-fragment/metadata.csv",
+				index: "my-bootclasspath-fragment/index.csv",
+				stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+				all_flags: "my-bootclasspath-fragment/all-flags.csv",
+			},
+			prefer: true,
+		}
+
+		java_import {
+			name: "libfoo",
+			jars: ["libfoo.jar"],
+			apex_available: ["myapex"],
+			prefer: true,
+		}
+		java_import {
+			name: "libbar",
+			jars: ["libbar.jar"],
+			apex_available: ["myapex"],
+			prefer: true,
+		}
+	`
+
+		testDexpreoptWithApexes(t, bp, "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_myapex.v1 and prebuilt_myapex.v2", preparer, fragment)
+	})
+
 }
 
 func TestApexWithTests(t *testing.T) {
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index e9ee3a2..5441a3b 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -44,7 +44,8 @@
 	//
 	// This must be the path to the unencoded dex jar as the encoded dex jar indirectly depends on
 	// this file so using the encoded dex jar here would result in a cycle in the ninja rules.
-	bootDexJarPath OptionalDexJarPath
+	bootDexJarPath    OptionalDexJarPath
+	bootDexJarPathErr error
 
 	// The paths to the classes jars that contain classes and class members annotated with
 	// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
@@ -56,7 +57,10 @@
 	uncompressDexState *bool
 }
 
-func (h *hiddenAPI) bootDexJar() OptionalDexJarPath {
+func (h *hiddenAPI) bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+	if h.bootDexJarPathErr != nil {
+		ctx.ModuleErrorf(h.bootDexJarPathErr.Error())
+	}
 	return h.bootDexJarPath
 }
 
@@ -77,7 +81,7 @@
 }
 
 type hiddenAPIIntf interface {
-	bootDexJar() OptionalDexJarPath
+	bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath
 	classesJars() android.Paths
 	uncompressDex() *bool
 }
@@ -126,6 +130,11 @@
 	h.active = isModuleInBootClassPath(ctx, module)
 }
 
+// Store any error encountered during the initialization of hiddenapi structure (e.g. unflagged co-existing prebuilt apexes)
+func (h *hiddenAPI) initHiddenAPIError(err error) {
+	h.bootDexJarPathErr = err
+}
+
 func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
 	// Get the configured platform and apex boot jars.
 	nonApexBootJars := ctx.Config().NonApexBootJars()
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index a512860..5176692 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -1342,7 +1342,7 @@
 // invalid, then create a fake path and either report an error immediately or defer reporting of the
 // error until the path is actually used.
 func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
-	bootDexJar := module.bootDexJar()
+	bootDexJar := module.bootDexJar(ctx)
 	if !bootDexJar.Valid() {
 		fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
 		handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
diff --git a/java/java.go b/java/java.go
index 4eeded3..807aea9 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2258,6 +2258,7 @@
 				// An error was found, possibly due to multiple apexes in the tree that export this library
 				// Defer the error till a client tries to call DexJarBuildPath
 				j.dexJarFileErr = err
+				j.initHiddenAPIError(err)
 				return
 			}
 			dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(j.BaseModuleName())
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 058862b..ce94ff9 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2769,6 +2769,7 @@
 				// An error was found, possibly due to multiple apexes in the tree that export this library
 				// Defer the error till a client tries to call DexJarBuildPath
 				module.dexJarFileErr = err
+				module.initHiddenAPIError(err)
 				return
 			}
 			dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName())