Merge "Support header and implementation jars in sdk"
diff --git a/java/java.go b/java/java.go
index 71b95df..a9e554b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1710,18 +1710,16 @@
 }
 
 const (
-	aidlIncludeDir     = "aidl"
-	javaStubDir        = "java"
-	javaStubFileSuffix = ".jar"
+	aidlIncludeDir = "aidl"
+	javaDir        = "java"
+	jarFileSuffix  = ".jar"
 )
 
-// path to the stub file of a java library. Relative to <sdk_root>/<api_dir>
-func (j *Library) javaStubFilePathFor() string {
-	return filepath.Join(javaStubDir, j.Name()+javaStubFileSuffix)
+// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
+func (j *Library) sdkSnapshotFilePathForJar() string {
+	return filepath.Join(javaDir, j.Name()+jarFileSuffix)
 }
 
-var LibrarySdkMemberType = &librarySdkMemberType{}
-
 type librarySdkMemberType struct {
 }
 
@@ -1734,7 +1732,12 @@
 	return ok
 }
 
-func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+func (mt *librarySdkMemberType) buildSnapshot(
+	sdkModuleContext android.ModuleContext,
+	builder android.SnapshotBuilder,
+	member android.SdkMember,
+	jarToExportGetter func(j *Library) android.Path) {
+
 	variants := member.Variants()
 	if len(variants) != 1 {
 		sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
@@ -1745,12 +1748,9 @@
 	variant := variants[0]
 	j := variant.(*Library)
 
-	headerJars := j.HeaderJars()
-	if len(headerJars) != 1 {
-		panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
-	}
-	snapshotRelativeJavaLibPath := j.javaStubFilePathFor()
-	builder.CopyToSnapshot(headerJars[0], snapshotRelativeJavaLibPath)
+	exportedJar := jarToExportGetter(j)
+	snapshotRelativeJavaLibPath := j.sdkSnapshotFilePathForJar()
+	builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
 
 	for _, dir := range j.AidlIncludeDirs() {
 		// TODO(jiyong): copy parcelable declarations only
@@ -1764,6 +1764,40 @@
 	module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
 }
 
+var HeaderLibrarySdkMemberType = &headerLibrarySdkMemberType{}
+
+type headerLibrarySdkMemberType struct {
+	librarySdkMemberType
+}
+
+func (mt *headerLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+	mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path {
+		headerJars := j.HeaderJars()
+		if len(headerJars) != 1 {
+			panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
+		}
+
+		return headerJars[0]
+	})
+}
+
+var ImplLibrarySdkMemberType = &implLibrarySdkMemberType{}
+
+type implLibrarySdkMemberType struct {
+	librarySdkMemberType
+}
+
+func (mt *implLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+	mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path {
+		implementationJars := j.ImplementationJars()
+		if len(implementationJars) != 1 {
+			panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
+		}
+
+		return implementationJars[0]
+	})
+}
+
 // java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
 //
 // By default, a java_library has a single variant that produces a `.jar` file containing `.class` files that were
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index e87a82c..5b72248 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -34,17 +34,17 @@
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
-			java_libs: ["myjavalib"],
+			java_header_libs: ["myjavalib"],
 		}
 
 		sdk_snapshot {
 			name: "mysdk@1",
-			java_libs: ["sdkmember_mysdk_1"],
+			java_header_libs: ["sdkmember_mysdk_1"],
 		}
 
 		sdk_snapshot {
 			name: "mysdk@2",
-			java_libs: ["sdkmember_mysdk_2"],
+			java_header_libs: ["sdkmember_mysdk_2"],
 		}
 
 		java_import {
@@ -103,7 +103,116 @@
 	ensureListContains(t, pathsToStrings(javalibForMyApex2.Rule("javac").Implicits), sdkMemberV2.String())
 }
 
-func TestSnapshotWithJavaLibrary(t *testing.T) {
+func TestSnapshotWithJavaHeaderLibrary(t *testing.T) {
+	result := testSdkWithJava(t, `
+		sdk {
+			name: "mysdk",
+			java_header_libs: ["myjavalib"],
+		}
+
+		java_library {
+			name: "myjavalib",
+			srcs: ["Test.java"],
+			aidl: {
+				export_include_dirs: ["aidl"],
+			},
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+			host_supported: true,
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "android_common",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+    name: "mysdk_myjavalib@current",
+    sdk_member_name: "myjavalib",
+    jars: ["java/myjavalib.jar"],
+}
+
+java_import {
+    name: "myjavalib",
+    prefer: false,
+    jars: ["java/myjavalib.jar"],
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    java_header_libs: ["mysdk_myjavalib@current"],
+}
+
+`),
+		checkAllCopyRules(`
+.intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar -> java/myjavalib.jar
+aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl
+`),
+	)
+}
+
+func TestHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
+	// b/145598135 - Generating host snapshots for anything other than linux is not supported.
+	SkipIfNotLinux(t)
+
+	result := testSdkWithJava(t, `
+		sdk {
+			name: "mysdk",
+			device_supported: false,
+			host_supported: true,
+			java_header_libs: ["myjavalib"],
+		}
+
+		java_library {
+			name: "myjavalib",
+			device_supported: false,
+			host_supported: true,
+			srcs: ["Test.java"],
+			aidl: {
+				export_include_dirs: ["aidl"],
+			},
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "linux_glibc_common",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+    name: "mysdk_myjavalib@current",
+    sdk_member_name: "myjavalib",
+    device_supported: false,
+    host_supported: true,
+    jars: ["java/myjavalib.jar"],
+}
+
+java_import {
+    name: "myjavalib",
+    prefer: false,
+    device_supported: false,
+    host_supported: true,
+    jars: ["java/myjavalib.jar"],
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    device_supported: false,
+    host_supported: true,
+    java_header_libs: ["mysdk_myjavalib@current"],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/myjavalib/linux_glibc_common/javac/myjavalib.jar -> java/myjavalib.jar
+aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl
+`),
+	)
+}
+
+func TestSnapshotWithJavaImplLibrary(t *testing.T) {
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -146,13 +255,13 @@
 
 `),
 		checkAllCopyRules(`
-.intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar -> java/myjavalib.jar
+.intermediates/myjavalib/android_common/javac/myjavalib.jar -> java/myjavalib.jar
 aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl
 `),
 	)
 }
 
-func TestHostSnapshotWithJavaLibrary(t *testing.T) {
+func TestHostSnapshotWithJavaImplLibrary(t *testing.T) {
 	// b/145598135 - Generating host snapshots for anything other than linux is not supported.
 	SkipIfNotLinux(t)
 
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 75c8585..c7e12b9 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -61,7 +61,12 @@
 }
 
 type sdkProperties struct {
-	// The list of java libraries in this SDK
+	// The list of java header libraries in this SDK
+	//
+	// This should be used for java libraries that are provided separately at runtime,
+	// e.g. through an APEX.
+	Java_header_libs []string
+	// The list of java implementation libraries in this SDK
 	Java_libs []string
 	// The list of native libraries in this SDK
 	Native_shared_libs []string
@@ -77,7 +82,7 @@
 }
 
 // Contains information about the sdk properties that list sdk members, e.g.
-// Java_libs.
+// Java_header_libs.
 type sdkMemberListProperty struct {
 	// the name of the property as used in a .bp file
 	name string
@@ -106,9 +111,14 @@
 	},
 	// Members from java package.
 	{
+		name:       "java_header_libs",
+		getter:     func(properties *sdkProperties) []string { return properties.Java_header_libs },
+		memberType: java.HeaderLibrarySdkMemberType,
+	},
+	{
 		name:       "java_libs",
 		getter:     func(properties *sdkProperties) []string { return properties.Java_libs },
-		memberType: java.LibrarySdkMemberType,
+		memberType: java.ImplLibrarySdkMemberType,
 	},
 	{
 		name:       "stubs_sources",
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 0a9dfb1..f4e944a 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -27,12 +27,12 @@
 	testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
 		sdk {
 			name: "mysdk",
-			java_libs: ["sdkmember"],
+			java_header_libs: ["sdkmember"],
 		}
 
 		sdk_snapshot {
 			name: "mysdk@1",
-			java_libs: ["sdkmember_mysdk_1"],
+			java_header_libs: ["sdkmember_mysdk_1"],
 		}
 
 		java_import {