Uncompress dex file in imported apk when needed.

This implements the uncompress-dexs macro's behavior in Soong.

Test: Converted TvSampleLeanbackLauncher + zipinfo
Change-Id: I9477aa21429d055f3f36ca90c7fd2c345c999029
diff --git a/java/app.go b/java/app.go
index 849af5b..db9c5dd 100644
--- a/java/app.go
+++ b/java/app.go
@@ -764,6 +764,19 @@
 	return shouldUncompressDex(ctx, &a.dexpreopter)
 }
 
+func (a *AndroidAppImport) uncompressDex(
+	ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
+	rule := android.NewRuleBuilder()
+	rule.Command().
+		Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
+		Tool(ctx.Config().HostToolPath(ctx, "zip2zip")).
+		FlagWithInput("-i ", inputPath).
+		FlagWithOutput("-o ", outputPath).
+		FlagWithArg("-0 ", "'classes*.dex'").
+		Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
+	rule.Build(pctx, ctx, "uncompress-dex", "Uncompress dex files")
+}
+
 func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	if String(a.properties.Certificate) == "" && !Bool(a.properties.Presigned) {
 		ctx.PropertyErrorf("certificate", "No certificate specified for prebuilt")
@@ -791,6 +804,11 @@
 	a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
 	a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
 	dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
+	if a.dexpreopter.uncompressedDex {
+		dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
+		a.uncompressDex(ctx, dexOutput, dexUncompressed.OutputPath)
+		dexOutput = dexUncompressed
+	}
 
 	// Sign or align the package
 	// TODO: Handle EXTERNAL