Merge "Regenerate R.java files from LOCAL_STATIC_ANDROID_LIBRARIES"
diff --git a/cmd/extract_jar_packages/Android.bp b/cmd/extract_jar_packages/Android.bp
new file mode 100644
index 0000000..ea0cbbf
--- /dev/null
+++ b/cmd/extract_jar_packages/Android.bp
@@ -0,0 +1,25 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+blueprint_go_binary {
+    name: "extract_jar_packages",
+    deps: [
+        "android-archive-zip",
+        "blueprint-pathtools",
+    ],
+    srcs: [
+        "extract_jar_packages.go",
+    ],
+}
+
diff --git a/cmd/extract_jar_packages/extract_jar_packages.go b/cmd/extract_jar_packages/extract_jar_packages.go
new file mode 100644
index 0000000..fca308f
--- /dev/null
+++ b/cmd/extract_jar_packages/extract_jar_packages.go
@@ -0,0 +1,88 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"archive/zip"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+)
+
+var (
+	outputFile = flag.String("o", "", "output file")
+	prefix     = flag.String("prefix", "", "prefix for each entry in the output file")
+	inputFile  = flag.String("i", "", "input jar or srcjar")
+)
+
+func must(err error) {
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func fileToPackage(file string) string {
+	dir := filepath.Dir(file)
+	return strings.Replace(dir, "/", ".", -1)
+}
+
+func main() {
+	flag.Usage = func() {
+		fmt.Fprintln(os.Stderr, "usage: extract_jar_packages -i <input file> -o <output -file> [-prefix <prefix>]")
+		flag.PrintDefaults()
+	}
+
+	flag.Parse()
+
+	if *outputFile == "" || *inputFile == "" {
+		flag.Usage()
+		os.Exit(1)
+	}
+
+	pkgSet := make(map[string]bool)
+
+	reader, err := zip.OpenReader(*inputFile)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer reader.Close()
+
+	for _, f := range reader.File {
+		ext := filepath.Ext(f.Name)
+		if ext == ".java" || ext == ".class" {
+			pkgSet[fileToPackage(f.Name)] = true
+		}
+	}
+
+	var pkgs []string
+	for k := range pkgSet {
+		pkgs = append(pkgs, k)
+	}
+	sort.Strings(pkgs)
+
+	var data []byte
+	for _, pkg := range pkgs {
+		data = append(data, *prefix...)
+		data = append(data, pkg...)
+		data = append(data, "\n"...)
+	}
+
+	must(ioutil.WriteFile(*outputFile, data, 0666))
+}
diff --git a/java/aapt2.go b/java/aapt2.go
index 61e9451..70c7507 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -113,14 +113,17 @@
 	blueprint.RuleParams{
 		Command: `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
 			`--output-text-symbols ${rTxt} $inFlags && ` +
-			`${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir`,
+			`${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
+			`${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
+
 		CommandDeps: []string{
 			"${config.Aapt2Cmd}",
 			"${config.SoongZipCmd}",
+			"${config.ExtractJarPackagesCmd}",
 		},
 		Restat: true,
 	},
-	"flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt")
+	"flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt", "extraPackages")
 
 var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
 	blueprint.RuleParams{
@@ -130,7 +133,7 @@
 	})
 
 func aapt2Link(ctx android.ModuleContext,
-	packageRes, genJar, proguardOptions, rTxt android.WritablePath,
+	packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
 	flags []string, deps android.Paths,
 	compiledRes, compiledOverlay android.Paths) {
 
@@ -172,7 +175,7 @@
 		Description:     "aapt2 link",
 		Implicits:       deps,
 		Output:          packageRes,
-		ImplicitOutputs: android.WritablePaths{proguardOptions, genJar, rTxt},
+		ImplicitOutputs: android.WritablePaths{proguardOptions, genJar, rTxt, extraPackages},
 		Args: map[string]string{
 			"flags":           strings.Join(flags, " "),
 			"inFlags":         strings.Join(inFlags, " "),
@@ -180,6 +183,7 @@
 			"genDir":          genDir.String(),
 			"genJar":          genJar.String(),
 			"rTxt":            rTxt.String(),
+			"extraPackages":   extraPackages.String(),
 		},
 	})
 }
diff --git a/java/aar.go b/java/aar.go
index 47676fd..9e5cddb 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -26,6 +26,7 @@
 	Dependency
 	ExportPackage() android.Path
 	ExportedProguardFlagFiles() android.Paths
+	ExportedStaticPackages() android.Paths
 }
 
 func init() {
@@ -58,12 +59,13 @@
 }
 
 type aapt struct {
-	aaptSrcJar          android.Path
-	exportPackage       android.Path
-	manifestPath        android.Path
-	proguardOptionsFile android.Path
-	rroDirs             android.Paths
-	rTxt                android.Path
+	aaptSrcJar            android.Path
+	exportPackage         android.Path
+	manifestPath          android.Path
+	proguardOptionsFile   android.Path
+	rroDirs               android.Paths
+	rTxt                  android.Path
+	extraAaptPackagesFile android.Path
 
 	aaptProperties aaptProperties
 }
@@ -123,9 +125,9 @@
 	linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
 	linkDeps = append(linkDeps, assetFiles...)
 
-	staticLibs, libDeps, libFlags := aaptLibs(ctx, sdkVersion)
+	transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, sdkVersion)
 
-	overlayFiles = append(overlayFiles, staticLibs...)
+	overlayFiles = append(overlayFiles, transitiveStaticLibs...)
 	linkDeps = append(linkDeps, libDeps...)
 	linkFlags = append(linkFlags, libFlags...)
 
@@ -178,6 +180,8 @@
 	srcJar := android.PathForModuleGen(ctx, "R.jar")
 	proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
 	rTxt := android.PathForModuleOut(ctx, "R.txt")
+	// This file isn't used by Soong, but is generated for exporting
+	extraPackages := android.PathForModuleOut(ctx, "extra_packages")
 
 	var compiledRes, compiledOverlay android.Paths
 	for _, dir := range resDirs {
@@ -189,7 +193,7 @@
 
 	compiledOverlay = append(compiledOverlay, overlayFiles...)
 
-	aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
+	aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
 		linkFlags, linkDeps, compiledRes, compiledOverlay)
 
 	a.aaptSrcJar = srcJar
@@ -197,11 +201,14 @@
 	a.manifestPath = manifestPath
 	a.proguardOptionsFile = proguardOptionsFile
 	a.rroDirs = rroDirs
+	a.extraAaptPackagesFile = extraPackages
 	a.rTxt = rTxt
 }
 
 // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
-func aaptLibs(ctx android.ModuleContext, sdkVersion string) (staticLibs, deps android.Paths, flags []string) {
+func aaptLibs(ctx android.ModuleContext, sdkVersion string) (transitiveStaticLibs, deps android.Paths,
+	flags []string) {
+
 	var sharedLibs android.Paths
 
 	sdkDep := decodeSdkDep(ctx, sdkVersion)
@@ -211,7 +218,8 @@
 
 	ctx.VisitDirectDeps(func(module android.Module) {
 		var exportPackage android.Path
-		if aarDep, ok := module.(AndroidLibraryDependency); ok {
+		aarDep, _ := module.(AndroidLibraryDependency)
+		if aarDep != nil {
 			exportPackage = aarDep.ExportPackage()
 		}
 
@@ -222,15 +230,16 @@
 			}
 		case staticLibTag:
 			if exportPackage != nil {
-				staticLibs = append(staticLibs, exportPackage)
+				transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
+				transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
 			}
 		}
 	})
 
 	deps = append(deps, sharedLibs...)
-	deps = append(deps, staticLibs...)
+	deps = append(deps, transitiveStaticLibs...)
 
-	if len(staticLibs) > 0 {
+	if len(transitiveStaticLibs) > 0 {
 		flags = append(flags, "--auto-add-overlay")
 	}
 
@@ -238,7 +247,9 @@
 		flags = append(flags, "-I "+sharedLib.String())
 	}
 
-	return staticLibs, deps, flags
+	transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
+
+	return transitiveStaticLibs, deps, flags
 }
 
 type AndroidLibrary struct {
@@ -250,12 +261,17 @@
 	aarFile android.WritablePath
 
 	exportedProguardFlagFiles android.Paths
+	exportedStaticPackages    android.Paths
 }
 
 func (a *AndroidLibrary) ExportedProguardFlagFiles() android.Paths {
 	return a.exportedProguardFlagFiles
 }
 
+func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
+	return a.exportedStaticPackages
+}
+
 var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
 
 func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -290,10 +306,13 @@
 	ctx.VisitDirectDeps(func(m android.Module) {
 		if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
 			a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
+			a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportPackage())
+			a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportedStaticPackages()...)
 		}
 	})
 
 	a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
+	a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
 }
 
 func AndroidLibraryFactory() android.Module {
@@ -331,9 +350,12 @@
 
 	properties AARImportProperties
 
-	classpathFile android.WritablePath
-	proguardFlags android.WritablePath
-	exportPackage android.WritablePath
+	classpathFile         android.WritablePath
+	proguardFlags         android.WritablePath
+	exportPackage         android.WritablePath
+	extraAaptPackagesFile android.WritablePath
+
+	exportedStaticPackages android.Paths
 }
 
 var _ AndroidLibraryDependency = (*AARImport)(nil)
@@ -346,6 +368,10 @@
 	return android.Paths{a.proguardFlags}
 }
 
+func (a *AARImport) ExportedStaticPackages() android.Paths {
+	return a.exportedStaticPackages
+}
+
 func (a *AARImport) Prebuilt() *android.Prebuilt {
 	return &a.prebuilt
 }
@@ -362,7 +388,7 @@
 		}
 	}
 
-	ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Libs...)
+	ctx.AddDependency(ctx.Module(), libTag, a.properties.Libs...)
 	ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Static_libs...)
 }
 
@@ -410,6 +436,7 @@
 	srcJar := android.PathForModuleGen(ctx, "R.jar")
 	proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
 	rTxt := android.PathForModuleOut(ctx, "R.txt")
+	a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
 
 	var linkDeps android.Paths
 
@@ -422,14 +449,14 @@
 	linkFlags = append(linkFlags, "--manifest "+manifest.String())
 	linkDeps = append(linkDeps, manifest)
 
-	staticLibs, libDeps, libFlags := aaptLibs(ctx, String(a.properties.Sdk_version))
+	transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, String(a.properties.Sdk_version))
 
 	linkDeps = append(linkDeps, libDeps...)
 	linkFlags = append(linkFlags, libFlags...)
 
-	overlayRes := append(android.Paths{flata}, staticLibs...)
+	overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
 
-	aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt,
+	aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
 		linkFlags, linkDeps, nil, overlayRes)
 }
 
diff --git a/java/androidmk.go b/java/androidmk.go
index 1e77d05..b168f2c 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -135,6 +135,7 @@
 				fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.classpathFile.String())
 				fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", prebuilt.exportPackage.String())
 				fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=", prebuilt.proguardFlags.String())
+				fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", prebuilt.extraAaptPackagesFile.String())
 				fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", String(prebuilt.properties.Sdk_version))
 			},
 		},
@@ -243,6 +244,7 @@
 		}
 
 		fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", a.exportPackage.String())
+		fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", a.extraAaptPackagesFile.String())
 		fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", a.manifestPath.String())
 		fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=",
 			strings.Join(a.exportedProguardFlagFiles.Strings(), " "))
diff --git a/java/app.go b/java/app.go
index 1fdce12..ae0592a 100644
--- a/java/app.go
+++ b/java/app.go
@@ -67,6 +67,10 @@
 	return nil
 }
 
+func (a *AndroidApp) ExportedStaticPackages() android.Paths {
+	return nil
+}
+
 var _ AndroidLibraryDependency = (*AndroidApp)(nil)
 
 type certificate struct {
diff --git a/java/config/config.go b/java/config/config.go
index 3d7f910..6633f79 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -85,6 +85,7 @@
 	pctx.SourcePathVariable("GenKotlinBuildFileCmd", "build/soong/scripts/gen-kotlin-build-file.sh")
 
 	pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
+	pctx.HostBinToolVariable("ExtractJarPackagesCmd", "extract_jar_packages")
 	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
 	pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips")
 	pctx.HostBinToolVariable("Zip2ZipCmd", "zip2zip")
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 5210f20..27c7daa 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -77,4 +77,6 @@
 
 	ctx.Strict("JACOCO_CLI_JAR", "${JacocoCLIJar}")
 	ctx.Strict("DEFAULT_JACOCO_EXCLUDE_FILTER", strings.Join(DefaultJacocoExcludeFilter, ","))
+
+	ctx.Strict("EXTRACT_JAR_PACKAGES", "${ExtractJarPackagesCmd}")
 }