Adds droidstubs support to sdk module

Adds stubs_sources property to sdk and unzips the droidstubs srcjar
into the snapshot directory.

Adds an UnzipToSnapshot method to the SnapshotBuilder which creates
a rule that uses zip2zip to repackage the supplied zip content into a
temporary zip file that matches what the required snapshot structure.
e.g. if the supplied zip contains foo/Foo.java and that needs to be in
the snapshot directory java/foo/stubs then it will create a zip that
contains java/foo/stubs/foo/Foo.java.

The temporary zip that is the output of that rule is added to the
zipsToMerge field for merging later.

If the zipsToMerge is empty then the snapshot zip is created as
before. Otherwise, a temporary zip file is created. That is then
merged with the other zip files in zipsToMerge to create the final
snapshot zip.

Adds prebuilt_stubs_sources for use by the generated .bp module.

Bug: 143678475
Test: added conscrypt sdk module and attempted to build it
Change-Id: Ie274263af3a08e36a73c61c0dbf0c341fd6967e2
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 3471bc9..99192be 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -45,6 +45,8 @@
 	ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
 	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
 	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
+	ctx.RegisterModuleType("droidstubs", android.ModuleFactoryAdaptor(java.DroidstubsFactory))
+	ctx.RegisterModuleType("prebuilt_stubs_sources", android.ModuleFactoryAdaptor(java.PrebuiltStubsSourcesFactory))
 
 	// from cc package
 	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
@@ -104,6 +106,8 @@
 		"include/Test.h":                             nil,
 		"aidl/foo/bar/Test.aidl":                     nil,
 		"libfoo.so":                                  nil,
+		"stubs-sources/foo/bar/Foo.java":             nil,
+		"foo/bar/Foo.java":                           nil,
 	})
 
 	return ctx, config
@@ -323,6 +327,39 @@
 	ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
 }
 
+// Note: This test does not verify that a droidstubs can be referenced, either
+// directly or indirectly from an APEX as droidstubs can never be a part of an
+// apex.
+func TestBasicSdkWithDroidstubs(t *testing.T) {
+	testSdk(t, `
+		sdk {
+				name: "mysdk",
+				stubs_sources: ["mystub"],
+		}
+		sdk_snapshot {
+				name: "mysdk@10",
+				stubs_sources: ["mystub_mysdk@10"],
+		}
+		prebuilt_stubs_sources {
+				name: "mystub_mysdk@10",
+				sdk_member_name: "mystub",
+				srcs: ["stubs-sources/foo/bar/Foo.java"],
+		}
+		droidstubs {
+				name: "mystub",
+				srcs: ["foo/bar/Foo.java"],
+				sdk_version: "none",
+				system_modules: "none",
+		}
+		java_library {
+				name: "myjavalib",
+				srcs: [":mystub"],
+				sdk_version: "none",
+				system_modules: "none",
+		}
+	`)
+}
+
 func TestDepNotInRequiredSdks(t *testing.T) {
 	testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
 		sdk {
@@ -417,6 +454,7 @@
 			name: "mysdk",
 			java_libs: ["myjavalib"],
 			native_shared_libs: ["mynativelib"],
+			stubs_sources: ["myjavaapistubs"],
 		}
 
 		java_library {
@@ -444,15 +482,26 @@
 			system_shared_libs: [],
 			stl: "none",
 		}
+
+		droidstubs {
+			name: "myjavaapistubs",
+			srcs: ["foo/bar/Foo.java"],
+			system_modules: "none",
+			sdk_version: "none",
+		}
 	`)
 
 	var copySrcs []string
 	var copyDests []string
 	buildParams := ctx.ModuleForTests("mysdk", "android_common").Module().BuildParamsForTests()
+	var zipBp android.BuildParams
 	for _, bp := range buildParams {
-		if bp.Rule.String() == "android/soong/android.Cp" {
+		ruleString := bp.Rule.String()
+		if ruleString == "android/soong/android.Cp" {
 			copySrcs = append(copySrcs, bp.Input.String())
 			copyDests = append(copyDests, bp.Output.Rel()) // rooted at the snapshot root
+		} else if ruleString == "<local rule>:m.mysdk_android_common.snapshot" {
+			zipBp = bp
 		}
 	}
 
@@ -472,6 +521,19 @@
 	ensureListContains(t, copyDests, "arm64/include_gen/mynativelib/aidl/foo/bar/Test.h")
 	ensureListContains(t, copyDests, "java/myjavalib.jar")
 	ensureListContains(t, copyDests, "arm64/lib/mynativelib.so")
+
+	// Ensure that the droidstubs .srcjar as repackaged into a temporary zip file
+	// and then merged together with the intermediate snapshot zip.
+	snapshotCreationInputs := zipBp.Implicits.Strings()
+	ensureListContains(t, snapshotCreationInputs,
+		filepath.Join(buildDir, ".intermediates/mysdk/android_common/tmp/java/myjavaapistubs_stubs_sources.zip"))
+	ensureListContains(t, snapshotCreationInputs,
+		filepath.Join(buildDir, ".intermediates/mysdk/android_common/mysdk-current.unmerged.zip"))
+	actual := zipBp.Output.String()
+	expected := filepath.Join(buildDir, ".intermediates/mysdk/android_common/mysdk-current.zip")
+	if actual != expected {
+		t.Errorf("Expected snapshot output to be %q but was %q", expected, actual)
+	}
 }
 
 var buildDir string