add java_import to mixed build

Bug: 220168131
Test: go test ./java -run TestImportMixedBuild
Test: USE_BAZEL_ANALYSIS=1 m CtsManagedProfileApp && verify jars are
  included from execroot/__main__ directory
Test: build/bazel/ci/mixed_droid.sh
Change-Id: I6d35a2389ea35525d532efc8474c71d2c8825646
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index ab71d99..9decfbd 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -217,6 +217,7 @@
 		"system/unwinding/libunwindstack":                        Bp2BuildDefaultTrueRecursively,
 		"tools/apksig":                                           Bp2BuildDefaultTrue,
 		"tools/platform-compat/java/android/compat":              Bp2BuildDefaultTrueRecursively,
+		"tools/tradefederation/prebuilts/filegroups":             Bp2BuildDefaultTrueRecursively,
 	}
 
 	Bp2buildKeepExistingBuildFile = map[string]bool{
@@ -526,5 +527,20 @@
 		"simpleperf_ndk",
 		"toybox-static",
 		"zlib_bench",
+
+		// java_import[_host] issues
+		// tradefed prebuilts depend on libprotobuf
+		"prebuilt_tradefed",
+		"prebuilt_tradefed-test-framework",
+		// handcrafted BUILD.bazel files in //prebuilts/...
+		"prebuilt_r8lib-prebuilt",
+		"prebuilt_sdk-core-lambda-stubs",
+		"prebuilt_android-support-collections-nodeps",
+		"prebuilt_android-arch-core-common-nodeps",
+		"prebuilt_android-arch-lifecycle-common-java8-nodeps",
+		"prebuilt_android-arch-lifecycle-common-nodeps",
+		"prebuilt_android-support-annotations-nodeps",
+		"prebuilt_android-arch-paging-common-nodeps",
+		"prebuilt_android-arch-room-common-nodeps",
 	}
 )
diff --git a/java/java.go b/java/java.go
index dae69dc..f4ec04e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -24,6 +24,7 @@
 	"strings"
 
 	"android/soong/bazel"
+	"android/soong/bazel/cquery"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -1610,7 +1611,8 @@
 	}
 }
 
-func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (j *Import) commonBuildActions(ctx android.ModuleContext) {
+	//TODO(b/231322772) these should come from Bazel once available
 	j.sdkVersion = j.SdkVersion(ctx)
 	j.minSdkVersion = j.MinSdkVersion(ctx)
 
@@ -1621,6 +1623,10 @@
 	if ctx.Windows() {
 		j.HideFromMake()
 	}
+}
+
+func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	j.commonBuildActions(ctx)
 
 	jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
 
@@ -1662,19 +1668,7 @@
 		addCLCFromDep(ctx, module, j.classLoaderContexts)
 	})
 
-	if Bool(j.properties.Installable) {
-		var installDir android.InstallPath
-		if ctx.InstallInTestcases() {
-			var archDir string
-			if !ctx.Host() {
-				archDir = ctx.DeviceConfig().DeviceArch()
-			}
-			installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
-		} else {
-			installDir = android.PathForModuleInstall(ctx, "framework")
-		}
-		ctx.InstallFile(installDir, jarName, outputFile)
-	}
+	j.maybeInstall(ctx, jarName, outputFile)
 
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
 
@@ -1748,6 +1742,24 @@
 	})
 }
 
+func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) {
+	if !Bool(j.properties.Installable) {
+		return
+	}
+
+	var installDir android.InstallPath
+	if ctx.InstallInTestcases() {
+		var archDir string
+		if !ctx.Host() {
+			archDir = ctx.DeviceConfig().DeviceArch()
+		}
+		installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
+	} else {
+		installDir = android.PathForModuleInstall(ctx, "framework")
+	}
+	ctx.InstallFile(installDir, jarName, outputFile)
+}
+
 func (j *Import) OutputFiles(tag string) (android.Paths, error) {
 	switch tag {
 	case "", ".jar":
@@ -2046,9 +2058,7 @@
 	return module
 }
 
-//
 // Defaults
-//
 type Defaults struct {
 	android.ModuleBase
 	android.DefaultsModuleBase
@@ -2063,29 +2073,29 @@
 //
 // Example:
 //
-//     java_defaults {
-//         name: "example_defaults",
-//         srcs: ["common/**/*.java"],
-//         javacflags: ["-Xlint:all"],
-//         aaptflags: ["--auto-add-overlay"],
-//     }
+//	java_defaults {
+//	    name: "example_defaults",
+//	    srcs: ["common/**/*.java"],
+//	    javacflags: ["-Xlint:all"],
+//	    aaptflags: ["--auto-add-overlay"],
+//	}
 //
-//     java_library {
-//         name: "example",
-//         defaults: ["example_defaults"],
-//         srcs: ["example/**/*.java"],
-//     }
+//	java_library {
+//	    name: "example",
+//	    defaults: ["example_defaults"],
+//	    srcs: ["example/**/*.java"],
+//	}
 //
 // is functionally identical to:
 //
-//     java_library {
-//         name: "example",
-//         srcs: [
-//             "common/**/*.java",
-//             "example/**/*.java",
-//         ],
-//         javacflags: ["-Xlint:all"],
-//     }
+//	java_library {
+//	    name: "example",
+//	    srcs: [
+//	        "common/**/*.java",
+//	        "example/**/*.java",
+//	    ],
+//	    javacflags: ["-Xlint:all"],
+//	}
 func DefaultsFactory() android.Module {
 	module := &Defaults{}
 
@@ -2483,5 +2493,54 @@
 	props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
 
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs)
+}
 
+var _ android.MixedBuildBuildable = (*Import)(nil)
+
+func (i *Import) getBazelModuleLabel(ctx android.BaseModuleContext) string {
+	return android.RemoveOptionalPrebuiltPrefixFromBazelLabel(i.GetBazelLabel(ctx, i))
+}
+
+func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) {
+	i.commonBuildActions(ctx)
+
+	bazelCtx := ctx.Config().BazelContext
+	filePaths, err := bazelCtx.GetOutputFiles(i.getBazelModuleLabel(ctx), android.GetConfigKey(ctx))
+	if err != nil {
+		ctx.ModuleErrorf(err.Error())
+		return
+	}
+
+	bazelJars := android.Paths{}
+	for _, bazelOutputFile := range filePaths {
+		bazelJars = append(bazelJars, android.PathForBazelOut(ctx, bazelOutputFile))
+	}
+
+	jarName := android.RemoveOptionalPrebuiltPrefix(i.Name()) + ".jar"
+	outputFile := android.PathForModuleOut(ctx, "bazelCombined", jarName)
+	TransformJarsToJar(ctx, outputFile, "combine prebuilt jars", bazelJars,
+		android.OptionalPath{}, // manifest
+		false,                  // stripDirEntries
+		[]string{},             // filesToStrip
+		[]string{},             // dirsToStrip
+	)
+	i.combinedClasspathFile = outputFile
+
+	ctx.SetProvider(JavaInfoProvider, JavaInfo{
+		HeaderJars:                     android.PathsIfNonNil(i.combinedClasspathFile),
+		ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile),
+		ImplementationJars:             android.PathsIfNonNil(i.combinedClasspathFile),
+		//TODO(b/240308299) include AIDL information from Bazel
+	})
+
+	i.maybeInstall(ctx, jarName, outputFile)
+}
+
+func (i *Import) QueueBazelCall(ctx android.BaseModuleContext) {
+	bazelCtx := ctx.Config().BazelContext
+	bazelCtx.QueueBazelRequest(i.getBazelModuleLabel(ctx), cquery.GetOutputFiles, android.GetConfigKey(ctx))
+}
+
+func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
+	return true
 }
diff --git a/java/java_test.go b/java/java_test.go
index 32b0b0f..9e5cf0c 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1667,3 +1667,48 @@
 		})
 	}
 }
+
+func TestImportMixedBuild(t *testing.T) {
+	bp := `
+		java_import {
+			name: "baz",
+			jars: [
+				"test1.jar",
+				"test2.jar",
+			],
+			bazel_module: { label: "//foo/bar:baz" },
+		}
+	`
+
+	ctx := android.GroupFixturePreparers(
+		prepareForJavaTest,
+		android.FixtureModifyConfig(func(config android.Config) {
+			config.BazelContext = android.MockBazelContext{
+				OutputBaseDir: "outputbase",
+				LabelToOutputFiles: map[string][]string{
+					"//foo/bar:baz": []string{"test1.jar", "test2.jar"},
+				},
+			}
+		}),
+	).RunTestWithBp(t, bp)
+
+	bazMod := ctx.ModuleForTests("baz", "android_common").Module()
+	producer := bazMod.(android.OutputFileProducer)
+	expectedOutputFiles := []string{".intermediates/baz/android_common/bazelCombined/baz.jar"}
+
+	outputFiles, err := producer.OutputFiles("")
+	if err != nil {
+		t.Errorf("Unexpected error getting java_import outputfiles %s", err)
+	}
+	actualOutputFiles := android.NormalizePathsForTesting(outputFiles)
+	android.AssertDeepEquals(t, "Output files are produced", expectedOutputFiles, actualOutputFiles)
+
+	javaInfoProvider := ctx.ModuleProvider(bazMod, JavaInfoProvider)
+	javaInfo, ok := javaInfoProvider.(JavaInfo)
+	if !ok {
+		t.Error("could not get JavaInfo from java_import module")
+	}
+	android.AssertDeepEquals(t, "Header JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.HeaderJars))
+	android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars))
+	android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars))
+}