Merge "Use xz prebuilt"
diff --git a/android/neverallow.go b/android/neverallow.go
index 261f2ee..3c6c004 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -50,7 +50,7 @@
 		because("the VNDK can never contain a library that is device dependent."),
 	neverallow().with("vndk.enabled", "true").without("owner", "").
 		because("a VNDK module can never have an owner."),
-	neverallow().notIn("libcore").with("no_standard_libs", "true"),
+	neverallow().notIn("libcore", "development").with("no_standard_libs", "true"),
 
 	// TODO(b/67974785): always enforce the manifest
 	neverallow().
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 9201989..7de6f06 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -116,10 +116,6 @@
 
 		// http://b/68236239 Allow 0/NULL instead of using nullptr everywhere.
 		"-Wno-zero-as-null-pointer-constant",
-
-		// http://b/36463318 Clang executes with an absolute path, so clang-provided
-		// headers are now absolute.
-		"-fdebug-prefix-map=$$PWD/=",
 	}, " "))
 
 	pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index df04358..1057655 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -63,6 +63,7 @@
 	zipsToNotStrip   = make(zipsToNotStripSet)
 	stripDirEntries  = flag.Bool("D", false, "strip directory entries from the output zip file")
 	manifest         = flag.String("m", "", "manifest file to insert in jar")
+	pyMain           = flag.String("pm", "", "__main__.py file to insert in par")
 	entrypoint       = flag.String("e", "", "par entrypoint file to insert in par")
 	ignoreDuplicates = flag.Bool("ignore-duplicates", false, "take each entry from the first zip it exists in and don't warn")
 )
@@ -75,7 +76,7 @@
 
 func main() {
 	flag.Usage = func() {
-		fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [-e entrypoint] output [inputs...]")
+		fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [-e entrypoint] [-pm __main__.py] output [inputs...]")
 		flag.PrintDefaults()
 	}
 
@@ -125,8 +126,12 @@
 		log.Fatal(errors.New("must specify -p when specifying a entrypoint via -e"))
 	}
 
+	if *pyMain != "" && !*emulatePar {
+		log.Fatal(errors.New("must specify -p when specifying a Python __main__.py via -pm"))
+	}
+
 	// do merge
-	err = mergeZips(readers, writer, *manifest, *entrypoint, *sortEntries, *emulateJar, *emulatePar,
+	err = mergeZips(readers, writer, *manifest, *entrypoint, *pyMain, *sortEntries, *emulateJar, *emulatePar,
 		*stripDirEntries, *ignoreDuplicates)
 	if err != nil {
 		log.Fatal(err)
@@ -218,7 +223,7 @@
 	source zipSource
 }
 
-func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoint string,
+func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoint, pyMain string,
 	sortEntries, emulateJar, emulatePar, stripDirEntries, ignoreDuplicates bool) error {
 
 	sourceByDest := make(map[string]zipSource, 0)
@@ -268,6 +273,22 @@
 		addMapping("entry_point.txt", fileSource)
 	}
 
+	if pyMain != "" {
+		buf, err := ioutil.ReadFile(pyMain)
+		if err != nil {
+			return err
+		}
+		fh := &zip.FileHeader{
+			Name:               "__main__.py",
+			Method:             zip.Store,
+			UncompressedSize64: uint64(len(buf)),
+		}
+		fh.SetMode(0700)
+		fh.SetModTime(jar.DefaultTime)
+		fileSource := bufferEntry{fh, buf}
+		addMapping("__main__.py", fileSource)
+	}
+
 	if emulatePar {
 		// the runfiles packages needs to be populated with "__init__.py".
 		newPyPkgs := []string{}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index eaa6c5f..8c60535 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -18,6 +18,7 @@
 	"android/soong/android"
 	"android/soong/java/config"
 	"fmt"
+	"path/filepath"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -49,6 +50,8 @@
 )
 
 func init() {
+	android.RegisterModuleType("doc_defaults", DocDefaultsFactory)
+
 	android.RegisterModuleType("droiddoc", DroiddocFactory)
 	android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
 	android.RegisterModuleType("droiddoc_template", DroiddocTemplateFactory)
@@ -63,22 +66,31 @@
 
 	// list of directories rooted at the Android.bp file that will
 	// be added to the search paths for finding source files when passing package names.
-	Local_sourcepaths []string `android:"arch_variant"`
+	Local_sourcepaths []string
 
 	// list of source files that should not be used to build the Java module.
 	// This is most useful in the arch/multilib variants to remove non-common files
 	// filegroup or genrule can be included within this property.
 	Exclude_srcs []string `android:"arch_variant"`
 
-	// list of of java libraries that will be in the classpath.
+	// list of java libraries that will be in the classpath.
 	Libs []string `android:"arch_variant"`
 
 	// don't build against the framework libraries (legacy-test, core-junit,
 	// ext, and framework for device targets)
 	No_framework_libs *bool
 
+	// the java library (in classpath) for documentation that provides java srcs and srcjars.
+	Srcs_lib *string
+
+	// the base dirs under srcs_lib will be scanned for java srcs.
+	Srcs_lib_whitelist_dirs []string
+
+	// the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs.
+	Srcs_lib_whitelist_pkgs []string
+
 	// If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
-	Installable *bool `android:"arch_variant"`
+	Installable *bool
 
 	// if not blank, set to the version of the sdk to compile against
 	Sdk_version *string `android:"arch_variant"`
@@ -86,37 +98,43 @@
 
 type DroiddocProperties struct {
 	// directory relative to top of the source tree that contains doc templates files.
-	Custom_template *string `android:"arch_variant"`
+	Custom_template *string
 
 	// directories relative to top of the source tree which contains html/jd files.
-	Html_dirs []string `android:"arch_variant"`
+	Html_dirs []string
 
 	// set a value in the Clearsilver hdf namespace.
-	Hdf []string `android:"arch_variant"`
+	Hdf []string
 
 	// proofread file contains all of the text content of the javadocs concatenated into one file,
 	// suitable for spell-checking and other goodness.
-	Proofread_file *string `android:"arch_variant"`
+	Proofread_file *string
 
 	// a todo file lists the program elements that are missing documentation.
 	// At some point, this might be improved to show more warnings.
-	Todo_file *string `android:"arch_variant"`
+	Todo_file *string
+
+	// directory under current module source that provide additional resources (images).
+	Resourcesdir *string
+
+	// resources output directory under out/soong/.intermediates.
+	Resourcesoutdir *string
 
 	// local files that are used within user customized droiddoc options.
-	Arg_files []string `android:"arch_variant"`
+	Arg_files []string
 
 	// user customized droiddoc args.
 	// Available variables for substitution:
 	//
 	//  $(location <label>): the path to the arg_files with name <label>
-	Args *string `android:"arch_variant"`
+	Args *string
 
 	// names of the output files used in args that will be generated
-	Out []string `android:"arch_variant"`
+	Out []string
 
 	// a list of files under current module source dir which contains known tags in Java sources.
 	// filegroup or genrule can be included within this property.
-	Knowntags []string `android:"arch_variant"`
+	Knowntags []string
 }
 
 type Javadoc struct {
@@ -133,6 +151,12 @@
 	stubsSrcJar android.WritablePath
 }
 
+func (j *Javadoc) Srcs() android.Paths {
+	return android.Paths{j.stubsSrcJar}
+}
+
+var _ android.SourceFileProducer = (*Javadoc)(nil)
+
 type Droiddoc struct {
 	Javadoc
 
@@ -203,6 +227,17 @@
 	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
 }
 
+func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool) {
+	for _, dir := range j.properties.Srcs_lib_whitelist_dirs {
+		for _, pkg := range j.properties.Srcs_lib_whitelist_pkgs {
+			prefix := filepath.Join(dir, pkg)
+			if _, found := whitelistPathPrefixes[prefix]; !found {
+				whitelistPathPrefixes[prefix] = true
+			}
+		}
+	}
+}
+
 func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
 	var deps deps
 
@@ -224,6 +259,24 @@
 				deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
 			case libTag:
 				deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
+				if otherName == String(j.properties.Srcs_lib) {
+					srcs := dep.(SrcDependency).CompiledSrcs()
+					whitelistPathPrefixes := make(map[string]bool)
+					j.genWhitelistPathPrefixes(whitelistPathPrefixes)
+					for _, src := range srcs {
+						if _, ok := src.(android.WritablePath); ok { // generated sources
+							deps.srcs = append(deps.srcs, src)
+						} else { // select source path for documentation based on whitelist path prefixs.
+							for k, _ := range whitelistPathPrefixes {
+								if strings.HasPrefix(src.Rel(), k) {
+									deps.srcs = append(deps.srcs, src)
+									break
+								}
+							}
+						}
+					}
+					deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...)
+				}
 			default:
 				panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
 			}
@@ -252,7 +305,10 @@
 
 	// srcs may depend on some genrule output.
 	j.srcJars = srcFiles.FilterByExt(".srcjar")
+	j.srcJars = append(j.srcJars, deps.srcJars...)
+
 	j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
+	j.srcFiles = append(j.srcFiles, deps.srcs...)
 
 	j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
 	j.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
@@ -428,6 +484,7 @@
 		proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
 		args = args + " -proofread " + proofreadFile.String()
 	}
+
 	if String(d.properties.Todo_file) != "" {
 		// tricky part:
 		// we should not compute full path for todo_file through PathForModuleOut().
@@ -435,6 +492,18 @@
 		args = args + " -todo " + String(d.properties.Todo_file)
 	}
 
+	if String(d.properties.Resourcesdir) != "" {
+		// TODO: should we add files under resourcesDir to the implicits? It seems that
+		// resourcesDir is one sub dir of htmlDir
+		resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
+		args = args + " -resourcesdir " + resourcesDir.String()
+	}
+
+	if String(d.properties.Resourcesoutdir) != "" {
+		// TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
+		args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
+	}
+
 	implicits = append(implicits, d.Javadoc.srcJars...)
 
 	opts := "-source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
@@ -503,3 +572,30 @@
 	d.dir = path
 	d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
 }
+
+//
+// Defaults
+//
+type DocDefaults struct {
+	android.ModuleBase
+	android.DefaultsModuleBase
+}
+
+func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+}
+
+func (d *DocDefaults) DepsMutator(ctx android.BottomUpMutatorContext) {
+}
+
+func DocDefaultsFactory() android.Module {
+	module := &DocDefaults{}
+
+	module.AddProperties(
+		&JavadocProperties{},
+		&DroiddocProperties{},
+	)
+
+	android.InitDefaultsModule(module)
+
+	return module
+}
diff --git a/java/java.go b/java/java.go
index 92170e6..5f5225c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -283,6 +283,21 @@
 	AidlIncludeDirs() android.Paths
 }
 
+type SrcDependency interface {
+	CompiledSrcs() android.Paths
+	CompiledSrcJars() android.Paths
+}
+
+func (j *Module) CompiledSrcs() android.Paths {
+	return j.compiledJavaSrcs
+}
+
+func (j *Module) CompiledSrcJars() android.Paths {
+	return j.compiledSrcJars
+}
+
+var _ SrcDependency = (*Module)(nil)
+
 func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
 	android.InitAndroidArchModule(module, hod, android.MultilibCommon)
 	android.InitDefaultableModule(module)
@@ -299,6 +314,7 @@
 	bootClasspathTag = dependencyTag{name: "bootclasspath"}
 	systemModulesTag = dependencyTag{name: "system modules"}
 	frameworkResTag  = dependencyTag{name: "framework-res"}
+	frameworkApkTag  = dependencyTag{name: "framework-apk"}
 	kotlinStdlibTag  = dependencyTag{name: "kotlin-stdlib"}
 	proguardRaiseTag = dependencyTag{name: "proguard-raise"}
 )
@@ -459,6 +475,11 @@
 		if ctx.ModuleName() == "framework" {
 			ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
 		}
+		if ctx.ModuleName() == "android_stubs_current" ||
+			ctx.ModuleName() == "android_system_stubs_current" ||
+			ctx.ModuleName() == "android_test_stubs_current" {
+			ctx.AddDependency(ctx.Module(), frameworkApkTag, "framework-res")
+		}
 	}
 
 	ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
@@ -544,6 +565,7 @@
 	staticHeaderJars   android.Paths
 	staticJarResources android.Paths
 	aidlIncludeDirs    android.Paths
+	srcs               android.Paths
 	srcJars            android.Paths
 	systemModules      android.Path
 	aidlPreprocess     android.OptionalPath
@@ -606,6 +628,18 @@
 					// generated by framework-res.apk
 					deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
 				}
+			case frameworkApkTag:
+				if ctx.ModuleName() == "android_stubs_current" ||
+					ctx.ModuleName() == "android_system_stubs_current" ||
+					ctx.ModuleName() == "android_test_stubs_current" {
+					// framework stubs.jar need to depend on framework-res.apk, in order to pull the
+					// resource files out of there for aapt.
+					//
+					// Normally the package rule runs aapt, which includes the resource,
+					// but we're not running that in our package rule so just copy in the
+					// resource files here.
+					deps.staticJarResources = append(deps.staticJarResources, dep.(*AndroidApp).exportPackage)
+				}
 			case kotlinStdlibTag:
 				deps.kotlinStdlib = dep.HeaderJars()
 			default:
@@ -895,6 +929,7 @@
 
 	// static classpath jars have the resources in them, so the resource jars aren't necessary here
 	jars = append(jars, deps.staticJars...)
+	jars = append(jars, deps.staticJarResources...)
 
 	var manifest android.OptionalPath
 	if j.properties.Manifest != nil {
diff --git a/python/binary.go b/python/binary.go
index 0314edb..4135dfe 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -18,8 +18,6 @@
 
 import (
 	"fmt"
-	"path/filepath"
-	"strings"
 
 	"android/soong/android"
 )
@@ -80,89 +78,44 @@
 	return []interface{}{&binary.binaryProperties}
 }
 
-func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actual_version string,
-	embedded_launcher bool, srcsPathMappings []pathMapping, parSpec parSpec,
-	depsPyRunfiles []string, depsParSpecs []parSpec) android.OptionalPath {
-	// no Python source file for compiling .par file.
-	if len(srcsPathMappings) == 0 {
-		return android.OptionalPath{}
-	}
-
-	// the runfiles packages needs to be populated with "__init__.py".
-	newPyPkgs := []string{}
-	// the set to de-duplicate the new Python packages above.
-	newPyPkgSet := make(map[string]bool)
-	// the runfiles dirs have been treated as packages.
-	existingPyPkgSet := make(map[string]bool)
-
-	wholePyRunfiles := []string{}
-	for _, path := range srcsPathMappings {
-		wholePyRunfiles = append(wholePyRunfiles, path.dest)
-	}
-	wholePyRunfiles = append(wholePyRunfiles, depsPyRunfiles...)
-
-	// find all the runfiles dirs which have been treated as packages.
-	for _, path := range wholePyRunfiles {
-		if filepath.Base(path) != initFileName {
-			continue
-		}
-		existingPyPkg := PathBeforeLastSlash(path)
-		if _, found := existingPyPkgSet[existingPyPkg]; found {
-			panic(fmt.Errorf("found init file path duplicates: %q for module: %q.",
-				path, ctx.ModuleName()))
-		} else {
-			existingPyPkgSet[existingPyPkg] = true
-		}
-		parentPath := PathBeforeLastSlash(existingPyPkg)
-		populateNewPyPkgs(parentPath, existingPyPkgSet, newPyPkgSet, &newPyPkgs)
-	}
-
-	// create new packages under runfiles tree.
-	for _, path := range wholePyRunfiles {
-		if filepath.Base(path) == initFileName {
-			continue
-		}
-		parentPath := PathBeforeLastSlash(path)
-		populateNewPyPkgs(parentPath, existingPyPkgSet, newPyPkgSet, &newPyPkgs)
-	}
+func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string,
+	embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path,
+	depsSrcsZips android.Paths) android.OptionalPath {
 
 	main := binary.getPyMainFile(ctx, srcsPathMappings)
-	if main == "" {
-		return android.OptionalPath{}
-	}
 
-	var launcher_path android.Path
-	if embedded_launcher {
+	var launcherPath android.Path
+	if embeddedLauncher {
 		ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
 			if provider, ok := m.(IntermPathProvider); ok {
-				if launcher_path != nil {
+				if launcherPath != nil {
 					panic(fmt.Errorf("launcher path was found before: %q",
-						launcher_path))
+						launcherPath))
 				}
-				launcher_path = provider.IntermPathForModuleOut().Path()
+				launcherPath = provider.IntermPathForModuleOut().Path()
 			}
 		})
 	}
 
-	binFile := registerBuildActionForParFile(ctx, embedded_launcher, launcher_path,
-		binary.getHostInterpreterName(ctx, actual_version),
-		main, binary.getStem(ctx), newPyPkgs, append(depsParSpecs, parSpec))
+	binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
+		binary.getHostInterpreterName(ctx, actualVersion),
+		main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
 
 	return android.OptionalPathForPath(binFile)
 }
 
 // get host interpreter name.
 func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext,
-	actual_version string) string {
+	actualVersion string) string {
 	var interp string
-	switch actual_version {
+	switch actualVersion {
 	case pyVersion2:
 		interp = "python2.7"
 	case pyVersion3:
 		interp = "python3"
 	default:
 		panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
-			actual_version, ctx.ModuleName()))
+			actualVersion, ctx.ModuleName()))
 	}
 
 	return interp
@@ -196,30 +149,3 @@
 
 	return stem + String(binary.binaryProperties.Suffix)
 }
-
-// Sets the given directory and all its ancestor directories as Python packages.
-func populateNewPyPkgs(pkgPath string, existingPyPkgSet,
-	newPyPkgSet map[string]bool, newPyPkgs *[]string) {
-	for pkgPath != "" {
-		if _, found := existingPyPkgSet[pkgPath]; found {
-			break
-		}
-		if _, found := newPyPkgSet[pkgPath]; !found {
-			newPyPkgSet[pkgPath] = true
-			*newPyPkgs = append(*newPyPkgs, pkgPath)
-			// Gets its ancestor directory by trimming last slash.
-			pkgPath = PathBeforeLastSlash(pkgPath)
-		} else {
-			break
-		}
-	}
-}
-
-// filepath.Dir("abc") -> "." and filepath.Dir("/abc") -> "/". However,
-// the PathBeforeLastSlash() will return "" for both cases above.
-func PathBeforeLastSlash(path string) string {
-	if idx := strings.LastIndex(path, "/"); idx != -1 {
-		return path[:idx]
-	}
-	return ""
-}
diff --git a/python/builder.go b/python/builder.go
index f194354..353054d 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -17,7 +17,6 @@
 // This file contains Ninja build actions for building Python program.
 
 import (
-	"fmt"
 	"strings"
 
 	"android/soong/android"
@@ -29,25 +28,30 @@
 var (
 	pctx = android.NewPackageContext("android/soong/python")
 
-	host_par = pctx.AndroidStaticRule("host_par",
+	zip = pctx.AndroidStaticRule("zip",
 		blueprint.RuleParams{
-			Command: `touch $initFile && ` +
-				`sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
-				`$parCmd -o $parFile $parArgs && echo '#!/usr/bin/env python' | cat - $parFile > $out && ` +
-				`chmod +x $out && (rm -f $initFile; rm -f $stub; rm -f $parFile)`,
-			CommandDeps: []string{"$parCmd", "$template"},
-		},
-		"initFile", "interp", "main", "template", "stub", "parCmd", "parFile", "parArgs")
-
-	embedded_par = pctx.AndroidStaticRule("embedded_par",
-		blueprint.RuleParams{
-			Command: `touch $initFile && ` +
-				`echo '$main' > $entry_point && ` +
-				`$parCmd -o $parFile $parArgs && cat $launcher | cat - $parFile > $out && ` +
-				`chmod +x $out && (rm -f $initFile; rm -f $entry_point; rm -f $parFile)`,
+			Command:     `$parCmd -o $out $args`,
 			CommandDeps: []string{"$parCmd"},
 		},
-		"initFile", "main", "entry_point", "parCmd", "parFile", "parArgs", "launcher")
+		"args")
+
+	hostPar = pctx.AndroidStaticRule("hostPar",
+		blueprint.RuleParams{
+			Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
+				`$mergeParCmd -p -pm $stub $mergedZip $srcsZips && echo '#!/usr/bin/env python' | cat - $mergedZip > $out && ` +
+				`chmod +x $out && (rm -f $stub; rm -f $mergedZip)`,
+			CommandDeps: []string{"$mergeParCmd"},
+		},
+		"interp", "main", "template", "stub", "mergedZip", "srcsZips")
+
+	embeddedPar = pctx.AndroidStaticRule("embeddedPar",
+		blueprint.RuleParams{
+			Command: `echo '$main' > $entryPoint &&` +
+				`$mergeParCmd -p -e $entryPoint $mergedZip $srcsZips && cat $launcher | cat - $mergedZip > $out && ` +
+				`chmod +x $out && (rm -f $entryPoint; rm -f $mergedZip)`,
+			CommandDeps: []string{"$mergeParCmd"},
+		},
+		"main", "entryPoint", "mergedZip", "srcsZips", "launcher")
 )
 
 func init() {
@@ -55,132 +59,65 @@
 	pctx.Import("android/soong/common")
 
 	pctx.HostBinToolVariable("parCmd", "soong_zip")
+	pctx.HostBinToolVariable("mergeParCmd", "merge_zips")
 }
 
-type fileListSpec struct {
-	fileList     android.Path
-	relativeRoot string
-}
+func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
+	launcherPath android.Path, interpreter, main, binName string,
+	srcsZips android.Paths) android.Path {
 
-type parSpec struct {
-	rootPrefix string
-
-	fileListSpecs []fileListSpec
-}
-
-func (p parSpec) soongParArgs() string {
-	ret := `-P ` + p.rootPrefix
-
-	for _, spec := range p.fileListSpecs {
-		ret += ` -C ` + spec.relativeRoot + ` -l ` + spec.fileList.String()
-	}
-
-	return ret
-}
-
-func registerBuildActionForModuleFileList(ctx android.ModuleContext,
-	name string, files android.Paths) android.Path {
-	fileList := android.PathForModuleOut(ctx, name+".list")
-
-	content := []string{}
-	for _, file := range files {
-		content = append(content, file.String())
-	}
-
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.WriteFile,
-		Description: "generate " + fileList.Rel(),
-		Output:      fileList,
-		Implicits:   files,
-		Args: map[string]string{
-			"content": strings.Join(content, `\n`),
-		},
-	})
-
-	return fileList
-}
-
-func registerBuildActionForParFile(ctx android.ModuleContext, embedded_launcher bool,
-	launcher_path android.Path, interpreter, main, binName string,
-	newPyPkgs []string, parSpecs []parSpec) android.Path {
-
-	// .intermediate output path for __init__.py
-	initFile := android.PathForModuleOut(ctx, initFileName).String()
-
-	// .intermediate output path for par file.
-	parFile := android.PathForModuleOut(ctx, binName+parFileExt)
+	// .intermediate output path for merged zip file.
+	mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip")
 
 	// .intermediate output path for bin executable.
 	binFile := android.PathForModuleOut(ctx, binName)
 
 	// implicit dependency for parFile build action.
-	implicits := android.Paths{}
-	for _, p := range parSpecs {
-		for _, f := range p.fileListSpecs {
-			implicits = append(implicits, f.fileList)
-		}
-	}
+	implicits := srcsZips
 
-	parArgs := []string{}
-	parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(initFile, initFileName)+` -f `+initFile)
-	for _, pkg := range newPyPkgs {
-		parArgs = append(parArgs, `-P `+pkg+` -f `+initFile)
-	}
-	for _, p := range parSpecs {
-		parArgs = append(parArgs, p.soongParArgs())
-	}
-
-	if !embedded_launcher {
+	if !embeddedLauncher {
 		// the path of stub_template_host.txt from source tree.
 		template := android.PathForSource(ctx, stubTemplateHost)
+		implicits = append(implicits, template)
 
 		// intermediate output path for __main__.py
 		stub := android.PathForModuleOut(ctx, mainFileName).String()
 
-		// added stub file to the soong_zip args.
-		parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(stub, mainFileName)+` -f `+stub)
-
 		ctx.Build(pctx, android.BuildParams{
-			Rule:        host_par,
+			Rule:        hostPar,
 			Description: "host python archive",
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"initFile": initFile,
-				"interp":   strings.Replace(interpreter, "/", `\/`, -1),
+				"interp": strings.Replace(interpreter, "/", `\/`, -1),
 				// we need remove "runfiles/" suffix since stub script starts
 				// searching for main file in each sub-dir of "runfiles" directory tree.
 				"main": strings.Replace(strings.TrimPrefix(main, runFiles+"/"),
 					"/", `\/`, -1),
-				"template": template.String(),
-				"stub":     stub,
-				"parFile":  parFile.String(),
-				"parArgs":  strings.Join(parArgs, " "),
+				"template":  template.String(),
+				"stub":      stub,
+				"mergedZip": mergedZip.String(),
+				"srcsZips":  strings.Join(srcsZips.Strings(), " "),
 			},
 		})
 	} else {
-		// added launcher_path to the implicits Ninja dependencies.
-		implicits = append(implicits, launcher_path)
+		// added launcherPath to the implicits Ninja dependencies.
+		implicits = append(implicits, launcherPath)
 
 		// .intermediate output path for entry_point.txt
 		entryPoint := android.PathForModuleOut(ctx, entryPointFile).String()
 
-		// added entry_point file to the soong_zip args.
-		parArgs = append(parArgs, `-P "" `+`-C `+fmt.Sprintf(
-			"%q", strings.TrimSuffix(entryPoint, entryPointFile))+` -f `+entryPoint)
-
 		ctx.Build(pctx, android.BuildParams{
-			Rule:        embedded_par,
+			Rule:        embeddedPar,
 			Description: "embedded python archive",
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"initFile":    initFile,
-				"main":        main,
-				"entry_point": entryPoint,
-				"parFile":     parFile.String(),
-				"parArgs":     strings.Join(parArgs, " "),
-				"launcher":    launcher_path.String(),
+				"main":       main,
+				"entryPoint": entryPoint,
+				"mergedZip":  mergedZip.String(),
+				"srcsZips":   strings.Join(srcsZips.Strings(), " "),
+				"launcher":   launcherPath.String(),
 			},
 		})
 	}
diff --git a/python/python.go b/python/python.go
index ed879eb..7626d09 100644
--- a/python/python.go
+++ b/python/python.go
@@ -132,18 +132,15 @@
 	// pathMapping: <dest: runfile_path, src: source_path>
 	dataPathMappings []pathMapping
 
-	// soong_zip arguments of all its dependencies.
-	depsParSpecs []parSpec
+	// the zip filepath for zipping current module source/data files.
+	srcsZip android.Path
 
-	// Python runfiles paths of all its dependencies.
-	depsPyRunfiles []string
+	// dependency modules' zip filepath for zipping current module source/data files.
+	depsSrcsZips android.Paths
 
 	// (.intermediate) module output path as installation source.
 	installSource android.OptionalPath
 
-	// the soong_zip arguments for zipping current module source/data files.
-	parSpec parSpec
-
 	subAndroidMkOnce map[subAndroidMkProvider]bool
 }
 
@@ -156,9 +153,9 @@
 
 type bootstrapper interface {
 	bootstrapperProps() []interface{}
-	bootstrap(ctx android.ModuleContext, Actual_version string, embedded_launcher bool,
-		srcsPathMappings []pathMapping, parSpec parSpec,
-		depsPyRunfiles []string, depsParSpecs []parSpec) android.OptionalPath
+	bootstrap(ctx android.ModuleContext, ActualVersion string, embeddedLauncher bool,
+		srcsPathMappings []pathMapping, srcsZip android.Path,
+		depsSrcsZips android.Paths) android.OptionalPath
 }
 
 type installer interface {
@@ -168,7 +165,7 @@
 type PythonDependency interface {
 	GetSrcsPathMappings() []pathMapping
 	GetDataPathMappings() []pathMapping
-	GetParSpec() parSpec
+	GetSrcsZip() android.Path
 }
 
 func (p *Module) GetSrcsPathMappings() []pathMapping {
@@ -179,8 +176,8 @@
 	return p.dataPathMappings
 }
 
-func (p *Module) GetParSpec() parSpec {
-	return p.parSpec
+func (p *Module) GetSrcsZip() android.Path {
+	return p.srcsZip
 }
 
 var _ PythonDependency = (*Module)(nil)
@@ -339,13 +336,12 @@
 	if p.bootstrapper != nil {
 		// TODO(nanzhang): Since embedded launcher is not supported for Python3 for now,
 		// so we initialize "embedded_launcher" to false.
-		embedded_launcher := false
+		embeddedLauncher := false
 		if p.properties.Actual_version == pyVersion2 {
-			embedded_launcher = p.isEmbeddedLauncherEnabled(pyVersion2)
+			embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion2)
 		}
 		p.installSource = p.bootstrapper.bootstrap(ctx, p.properties.Actual_version,
-			embedded_launcher, p.srcsPathMappings, p.parSpec, p.depsPyRunfiles,
-			p.depsParSpecs)
+			embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips)
 	}
 
 	if p.installer != nil && p.installSource.Valid() {
@@ -378,11 +374,11 @@
 	expandedData := ctx.ExpandSources(p.properties.Data, nil)
 
 	// sanitize pkg_path.
-	pkg_path := String(p.properties.Pkg_path)
-	if pkg_path != "" {
-		pkg_path = filepath.Clean(String(p.properties.Pkg_path))
-		if pkg_path == ".." || strings.HasPrefix(pkg_path, "../") ||
-			strings.HasPrefix(pkg_path, "/") {
+	pkgPath := String(p.properties.Pkg_path)
+	if pkgPath != "" {
+		pkgPath = filepath.Clean(String(p.properties.Pkg_path))
+		if pkgPath == ".." || strings.HasPrefix(pkgPath, "../") ||
+			strings.HasPrefix(pkgPath, "/") {
 			ctx.PropertyErrorf("pkg_path",
 				"%q must be a relative path contained in par file.",
 				String(p.properties.Pkg_path))
@@ -390,31 +386,31 @@
 		}
 		if p.properties.Is_internal != nil && *p.properties.Is_internal {
 			// pkg_path starts from "internal/" implicitly.
-			pkg_path = filepath.Join(internal, pkg_path)
+			pkgPath = filepath.Join(internal, pkgPath)
 		} else {
 			// pkg_path starts from "runfiles/" implicitly.
-			pkg_path = filepath.Join(runFiles, pkg_path)
+			pkgPath = filepath.Join(runFiles, pkgPath)
 		}
 	} else {
 		if p.properties.Is_internal != nil && *p.properties.Is_internal {
 			// pkg_path starts from "runfiles/" implicitly.
-			pkg_path = internal
+			pkgPath = internal
 		} else {
 			// pkg_path starts from "runfiles/" implicitly.
-			pkg_path = runFiles
+			pkgPath = runFiles
 		}
 	}
 
-	p.genModulePathMappings(ctx, pkg_path, expandedSrcs, expandedData)
-
-	p.parSpec = p.dumpFileList(ctx, pkg_path)
+	p.genModulePathMappings(ctx, pkgPath, expandedSrcs, expandedData)
 
 	p.uniqWholeRunfilesTree(ctx)
+
+	p.srcsZip = p.createSrcsZip(ctx, pkgPath)
 }
 
 // generate current module unique pathMappings: <dest: runfiles_path, src: source_path>
 // for python/data files.
-func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path string,
+func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkgPath string,
 	expandedSrcs, expandedData android.Paths) {
 	// fetch <runfiles_path, source_path> pairs from "src" and "data" properties to
 	// check duplicates.
@@ -426,7 +422,7 @@
 			ctx.PropertyErrorf("srcs", "found non (.py) file: %q!", s.String())
 			continue
 		}
-		runfilesPath := filepath.Join(pkg_path, s.Rel())
+		runfilesPath := filepath.Join(pkgPath, s.Rel())
 		identifiers := strings.Split(strings.TrimSuffix(runfilesPath, pyExt), "/")
 		for _, token := range identifiers {
 			if !pyIdentifierRegexp.MatchString(token) {
@@ -445,7 +441,7 @@
 			ctx.PropertyErrorf("data", "found (.py) file: %q!", d.String())
 			continue
 		}
-		runfilesPath := filepath.Join(pkg_path, d.Rel())
+		runfilesPath := filepath.Join(pkgPath, d.Rel())
 		if fillInMap(ctx, destToPyData, runfilesPath, d.String(), p.Name(), p.Name()) {
 			p.dataPathMappings = append(p.dataPathMappings,
 				pathMapping{dest: runfilesPath, src: d})
@@ -454,12 +450,9 @@
 
 }
 
-// register build actions to dump filelist to disk.
-func (p *Module) dumpFileList(ctx android.ModuleContext, pkg_path string) parSpec {
+// register build actions to zip current module's sources.
+func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) android.Path {
 	relativeRootMap := make(map[string]android.Paths)
-	// the soong_zip params in order to pack current module's Python/data files.
-	ret := parSpec{rootPrefix: pkg_path}
-
 	pathMappings := append(p.srcsPathMappings, p.dataPathMappings...)
 
 	// "srcs" or "data" properties may have filegroup so it might happen that
@@ -482,15 +475,29 @@
 	}
 	sort.Strings(keys)
 
+	parArgs := []string{}
+	parArgs = append(parArgs, `-P `+pkgPath)
+	implicits := android.Paths{}
 	for _, k := range keys {
-		// use relative root as filelist name.
-		fileListPath := registerBuildActionForModuleFileList(
-			ctx, strings.Replace(k, "/", "_", -1), relativeRootMap[k])
-		ret.fileListSpecs = append(ret.fileListSpecs,
-			fileListSpec{fileList: fileListPath, relativeRoot: k})
+		parArgs = append(parArgs, `-C `+k)
+		for _, path := range relativeRootMap[k] {
+			parArgs = append(parArgs, `-f `+path.String())
+			implicits = append(implicits, path)
+		}
 	}
 
-	return ret
+	srcsZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        zip,
+		Description: "python library archive",
+		Output:      srcsZip,
+		Implicits:   implicits,
+		Args: map[string]string{
+			"args": strings.Join(parArgs, " "),
+		},
+	})
+
+	return srcsZip
 }
 
 func isPythonLibModule(module blueprint.Module) bool {
@@ -537,9 +544,6 @@
 					ctx.OtherModuleName(module)) {
 					continue
 				}
-				// binary needs the Python runfiles paths from all its
-				// dependencies to fill __init__.py in each runfiles dir.
-				p.depsPyRunfiles = append(p.depsPyRunfiles, path.dest)
 			}
 			data := dep.GetDataPathMappings()
 			for _, path := range data {
@@ -547,9 +551,7 @@
 					path.dest, path.src.String(), ctx.ModuleName(),
 					ctx.OtherModuleName(module))
 			}
-			// binary needs the soong_zip arguments from all its
-			// dependencies to generate executable par file.
-			p.depsParSpecs = append(p.depsParSpecs, dep.GetParSpec())
+			p.depsSrcsZips = append(p.depsSrcsZips, dep.GetSrcsZip())
 		}
 	})
 }
diff --git a/python/python_test.go b/python/python_test.go
index 176c6ec..67b1982 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -29,12 +29,11 @@
 )
 
 type pyModule struct {
-	name           string
-	actualVersion  string
-	pyRunfiles     []string
-	depsPyRunfiles []string
-	parSpec        string
-	depsParSpecs   []string
+	name          string
+	actualVersion string
+	pyRunfiles    []string
+	srcsZip       string
+	depsSrcsZips  []string
 }
 
 var (
@@ -313,14 +312,10 @@
 						"runfiles/e/default_py3.py",
 						"runfiles/e/file4.py",
 					},
-					depsPyRunfiles: []string{
-						"runfiles/a/b/file1.py",
-						"runfiles/c/d/file2.py",
-					},
-					parSpec: "-P runfiles/e -C dir/ -l @prefix@/.intermediates/dir/bin/PY3/dir_.list",
-					depsParSpecs: []string{
-						"-P runfiles/a/b -C dir/ -l @prefix@/.intermediates/dir/lib5/PY3/dir_.list",
-						"-P runfiles/c/d -C dir/ -l @prefix@/.intermediates/dir/lib6/PY3/dir_.list",
+					srcsZip: "@prefix@/.intermediates/dir/bin/PY3/bin.zip",
+					depsSrcsZips: []string{
+						"@prefix@/.intermediates/dir/lib5/PY3/lib5.zip",
+						"@prefix@/.intermediates/dir/lib6/PY3/lib6.zip",
 					},
 				},
 			},
@@ -356,8 +351,9 @@
 					testErrs = append(testErrs,
 						expectModule(t, ctx, buildDir, e.name,
 							e.actualVersion,
-							e.pyRunfiles, e.depsPyRunfiles,
-							e.parSpec, e.depsParSpecs)...)
+							e.srcsZip,
+							e.pyRunfiles,
+							e.depsSrcsZips)...)
 				}
 			}
 			fail(t, testErrs)
@@ -388,9 +384,8 @@
 	return
 }
 
-func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant string,
-	expPyRunfiles, expDepsPyRunfiles []string,
-	expParSpec string, expDepsParSpecs []string) (testErrs []error) {
+func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant, expectedSrcsZip string,
+	expectedPyRunfiles, expectedDepsSrcsZips []string) (testErrs []error) {
 	module := ctx.ModuleForTests(name, variant)
 
 	base, baseOk := module.Module().(*Module)
@@ -398,47 +393,36 @@
 		t.Fatalf("%s is not Python module!", name)
 	}
 
-	actPyRunfiles := []string{}
+	actualPyRunfiles := []string{}
 	for _, path := range base.srcsPathMappings {
-		actPyRunfiles = append(actPyRunfiles, path.dest)
+		actualPyRunfiles = append(actualPyRunfiles, path.dest)
 	}
 
-	if !reflect.DeepEqual(actPyRunfiles, expPyRunfiles) {
+	if !reflect.DeepEqual(actualPyRunfiles, expectedPyRunfiles) {
 		testErrs = append(testErrs, errors.New(fmt.Sprintf(
 			`binary "%s" variant "%s" has unexpected pyRunfiles: %q!`,
 			base.Name(),
 			base.properties.Actual_version,
-			actPyRunfiles)))
+			actualPyRunfiles)))
 	}
 
-	if !reflect.DeepEqual(base.depsPyRunfiles, expDepsPyRunfiles) {
+	if base.srcsZip.String() != strings.Replace(expectedSrcsZip, "@prefix@", buildDir, 1) {
 		testErrs = append(testErrs, errors.New(fmt.Sprintf(
-			`binary "%s" variant "%s" has unexpected depsPyRunfiles: %q!`,
+			`binary "%s" variant "%s" has unexpected srcsZip: %q!`,
 			base.Name(),
 			base.properties.Actual_version,
-			base.depsPyRunfiles)))
+			base.srcsZip)))
 	}
 
-	if base.parSpec.soongParArgs() != strings.Replace(expParSpec, "@prefix@", buildDir, 1) {
+	for i, _ := range expectedDepsSrcsZips {
+		expectedDepsSrcsZips[i] = strings.Replace(expectedDepsSrcsZips[i], "@prefix@", buildDir, 1)
+	}
+	if !reflect.DeepEqual(base.depsSrcsZips.Strings(), expectedDepsSrcsZips) {
 		testErrs = append(testErrs, errors.New(fmt.Sprintf(
-			`binary "%s" variant "%s" has unexpected parSpec: %q!`,
+			`binary "%s" variant "%s" has unexpected depsSrcsZips: %q!`,
 			base.Name(),
 			base.properties.Actual_version,
-			base.parSpec.soongParArgs())))
-	}
-
-	actDepsParSpecs := []string{}
-	for i, p := range base.depsParSpecs {
-		actDepsParSpecs = append(actDepsParSpecs, p.soongParArgs())
-		expDepsParSpecs[i] = strings.Replace(expDepsParSpecs[i], "@prefix@", buildDir, 1)
-	}
-
-	if !reflect.DeepEqual(actDepsParSpecs, expDepsParSpecs) {
-		testErrs = append(testErrs, errors.New(fmt.Sprintf(
-			`binary "%s" variant "%s" has unexpected depsParSpecs: %q!`,
-			base.Name(),
-			base.properties.Actual_version,
-			actDepsParSpecs)))
+			base.depsSrcsZips)))
 	}
 
 	return