Merge "Delete prebuilt APEXes when installing source-built APEXes"
diff --git a/android/config.go b/android/config.go
index 556ddcc..074dfc7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -756,6 +756,14 @@
 	return c.IsEnvTrue("RUN_ERROR_PRONE")
 }
 
+func (c *config) XrefCorpusName() string {
+	return c.Getenv("XREF_CORPUS")
+}
+
+func (c *config) EmitXrefRules() bool {
+	return c.XrefCorpusName() != ""
+}
+
 // Returns true if -source 1.9 -target 1.9 is being passed to javac
 func (c *config) TargetOpenJDK9() bool {
 	return c.targetOpenJDK9
diff --git a/apex/apex.go b/apex/apex.go
index de9ce0d..4729e0f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -696,12 +696,6 @@
 	return
 }
 
-func getCopyManifestForTestPerSrcExecutables(cc *cc.Module) (filesToCopy []android.Path, dirInApex string) {
-	dirInApex = filepath.Join("bin", cc.RelativeInstallPath())
-	filesToCopy = cc.TestPerSrcOutputFiles()
-	return
-}
-
 func getCopyManifestForPyBinary(py *python.Module) (fileToCopy android.Path, dirInApex string) {
 	dirInApex = "bin"
 	fileToCopy = py.HostToolPath().Path()
@@ -782,10 +776,10 @@
 	})
 
 	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
+		depTag := ctx.OtherModuleDependencyTag(child)
+		depName := ctx.OtherModuleName(child)
 		if _, ok := parent.(*apexBundle); ok {
 			// direct dependencies
-			depTag := ctx.OtherModuleDependencyTag(child)
-			depName := ctx.OtherModuleName(child)
 			switch depTag {
 			case sharedLibTag:
 				if cc, ok := child.(*cc.Module); ok {
@@ -836,22 +830,19 @@
 					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
 				}
 			case testTag:
-				if cc, ok := child.(*cc.Module); ok {
-					if cc.TestPerSrcOutputFiles() != nil {
-						// Multiple-output test module (using `test_per_src`).
-						filesToCopy, dirInApex := getCopyManifestForTestPerSrcExecutables(cc)
-						for _, fileToCopy := range filesToCopy {
-							// Handle modules created as `test_per_src` variations of a single test module:
-							// replace the name of the original test module (`depName`, shared by all
-							// `test_per_src` variants of that module) with the name of the generated test
-							// binary.
-							moduleName := filepath.Base(fileToCopy.String())
-							filesInfo = append(filesInfo, apexFile{fileToCopy, moduleName, dirInApex, nativeTest, cc, nil})
-						}
+				if ccTest, ok := child.(*cc.Module); ok {
+					if ccTest.IsTestPerSrcAllTestsVariation() {
+						// Multiple-output test module (where `test_per_src: true`).
+						//
+						// `ccTest` is the "" ("all tests") variation of a `test_per_src` module.
+						// We do not add this variation to `filesInfo`, as it has no output;
+						// however, we do add the other variations of this module as indirect
+						// dependencies (see below).
+						return true
 					} else {
-						// Single-output test module (not using `test_per_src`).
-						fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
-						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeTest, cc, nil})
+						// Single-output test module (where `test_per_src: false`).
+						fileToCopy, dirInApex := getCopyManifestForExecutable(ccTest)
+						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeTest, ccTest, nil})
 					}
 					return true
 				} else {
@@ -883,30 +874,46 @@
 		} else {
 			// indirect dependencies
 			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
-				if cc, ok := child.(*cc.Module); ok {
-					if android.InList(cc.Name(), providedNativeSharedLibs) {
-						// If we're using a shared library which is provided from other APEX,
-						// don't include it in this APEX
-						return false
-					}
-					if !a.Host() && (cc.IsStubs() || cc.HasStubsVariants()) {
-						// If the dependency is a stubs lib, don't include it in this APEX,
-						// but make sure that the lib is installed on the device.
-						// In case no APEX is having the lib, the lib is installed to the system
-						// partition.
-						//
-						// Always include if we are a host-apex however since those won't have any
-						// system libraries.
-						if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.externalDeps) {
-							a.externalDeps = append(a.externalDeps, cc.Name())
+				// We cannot use a switch statement on `depTag` here as the checked
+				// tags used below are private (e.g. `cc.sharedDepTag`).
+				if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
+					if cc, ok := child.(*cc.Module); ok {
+						if android.InList(cc.Name(), providedNativeSharedLibs) {
+							// If we're using a shared library which is provided from other APEX,
+							// don't include it in this APEX
+							return false
 						}
-						// Don't track further
-						return false
+						if !a.Host() && (cc.IsStubs() || cc.HasStubsVariants()) {
+							// If the dependency is a stubs lib, don't include it in this APEX,
+							// but make sure that the lib is installed on the device.
+							// In case no APEX is having the lib, the lib is installed to the system
+							// partition.
+							//
+							// Always include if we are a host-apex however since those won't have any
+							// system libraries.
+							if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.externalDeps) {
+								a.externalDeps = append(a.externalDeps, cc.Name())
+							}
+							// Don't track further
+							return false
+						}
+						fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
+						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
+						return true
 					}
-					depName := ctx.OtherModuleName(child)
-					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
-					return true
+				} else if cc.IsTestPerSrcDepTag(depTag) {
+					if cc, ok := child.(*cc.Module); ok {
+						fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
+						// Handle modules created as `test_per_src` variations of a single test module:
+						// use the name of the generated test binary (`fileToCopy`) instead of the name
+						// of the original test module (`depName`, shared by all `test_per_src`
+						// variations of that module).
+						moduleName := filepath.Base(fileToCopy.String())
+						filesInfo = append(filesInfo, apexFile{fileToCopy, moduleName, dirInApex, nativeTest, cc, nil})
+						return true
+					}
+				} else {
+					ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
 				}
 			}
 		}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e44163e..cecdaaf 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1393,7 +1393,7 @@
 }
 
 func TestApexWithTests(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx, config := testApex(t, `
 		apex_test {
 			name: "myapex",
 			key: "myapex.key",
@@ -1445,6 +1445,22 @@
 	ensureContains(t, copyCmds, "image.apex/bin/test/mytest1")
 	ensureContains(t, copyCmds, "image.apex/bin/test/mytest2")
 	ensureContains(t, copyCmds, "image.apex/bin/test/mytest3")
+
+	// Ensure the module is correctly translated.
+	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	name := apexBundle.BaseModuleName()
+	prefix := "TARGET_"
+	var builder strings.Builder
+	data.Custom(&builder, name, prefix, "", data)
+	androidMk := builder.String()
+	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest\n")
+	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest1\n")
+	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest2\n")
+	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest3\n")
+	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_manifest.json\n")
+	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_pubkey\n")
+	ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n")
 }
 
 func TestApexUsesOtherApex(t *testing.T) {
diff --git a/cc/builder.go b/cc/builder.go
index cbe2c88..2909d51 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -221,6 +221,17 @@
 			Rspfile:        "$out.rsp",
 			RspfileContent: "$in",
 		})
+
+	_ = pctx.SourcePathVariable("cxxExtractor",
+		"prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/cxx_extractor")
+	_ = pctx.VariableFunc("kytheCorpus",
+		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
+	kytheExtract = pctx.StaticRule("kythe",
+		blueprint.RuleParams{
+			Command:     "rm -f $out && KYTHE_CORPUS=${kytheCorpus} KYTHE_OUTPUT_FILE=$out $cxxExtractor $cFlags $in ",
+			CommandDeps: []string{"$cxxExtractor"},
+		},
+		"cFlags")
 )
 
 func init() {
@@ -257,6 +268,7 @@
 	tidy            bool
 	coverage        bool
 	sAbiDump        bool
+	emitXrefs       bool
 
 	systemIncludeFlags string
 
@@ -281,6 +293,7 @@
 	tidyFiles     android.Paths
 	coverageFiles android.Paths
 	sAbiDumpFiles android.Paths
+	kytheFiles    android.Paths
 }
 
 func (a Objects) Copy() Objects {
@@ -289,6 +302,7 @@
 		tidyFiles:     append(android.Paths{}, a.tidyFiles...),
 		coverageFiles: append(android.Paths{}, a.coverageFiles...),
 		sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
+		kytheFiles:    append(android.Paths{}, a.kytheFiles...),
 	}
 }
 
@@ -298,6 +312,7 @@
 		tidyFiles:     append(a.tidyFiles, b.tidyFiles...),
 		coverageFiles: append(a.coverageFiles, b.coverageFiles...),
 		sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
+		kytheFiles:    append(a.kytheFiles, b.kytheFiles...),
 	}
 }
 
@@ -314,6 +329,10 @@
 	if flags.coverage {
 		coverageFiles = make(android.Paths, 0, len(srcFiles))
 	}
+	var kytheFiles android.Paths
+	if flags.emitXrefs {
+		kytheFiles = make(android.Paths, 0, len(srcFiles))
+	}
 
 	commonFlags := strings.Join([]string{
 		flags.globalFlags,
@@ -401,6 +420,7 @@
 		coverage := flags.coverage
 		dump := flags.sAbiDump
 		rule := cc
+		emitXref := flags.emitXrefs
 
 		switch srcFile.Ext() {
 		case ".s":
@@ -412,6 +432,7 @@
 			tidy = false
 			coverage = false
 			dump = false
+			emitXref = false
 		case ".c":
 			ccCmd = "clang"
 			moduleCflags = cflags
@@ -450,6 +471,22 @@
 			},
 		})
 
+		if emitXref {
+			kytheFile := android.ObjPathWithExt(ctx, subdir, srcFile, "kzip")
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        kytheExtract,
+				Description: "Xref C++ extractor " + srcFile.Rel(),
+				Output:      kytheFile,
+				Input:       srcFile,
+				Implicits:   cFlagsDeps,
+				OrderOnly:   pathDeps,
+				Args: map[string]string{
+					"cFlags": moduleCflags,
+				},
+			})
+			kytheFiles = append(kytheFiles, kytheFile)
+		}
+
 		if tidy {
 			tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
 			tidyFiles = append(tidyFiles, tidyFile)
@@ -493,6 +530,7 @@
 		tidyFiles:     tidyFiles,
 		coverageFiles: coverageFiles,
 		sAbiDumpFiles: sAbiDumpFiles,
+		kytheFiles:    kytheFiles,
 	}
 }
 
diff --git a/cc/cc.go b/cc/cc.go
index 2cee807..cc2e65f 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -77,6 +77,7 @@
 		ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
 	})
 
+	android.RegisterSingletonType("kythe_extract_all", kytheExtractAllFactory)
 	pctx.Import("android/soong/cc/config")
 }
 
@@ -162,6 +163,7 @@
 	Tidy      bool
 	Coverage  bool
 	SAbiDump  bool
+	EmitXrefs bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
 
 	RequiredInstructionSet string
 	DynamicLinker          string
@@ -340,17 +342,22 @@
 	blueprint.BaseDependencyTag
 	name    string
 	library bool
+	shared  bool
 
 	reexportFlags bool
 
 	explicitlyVersioned bool
 }
 
+type xref interface {
+	XrefCcFiles() android.Paths
+}
+
 var (
-	sharedDepTag          = dependencyTag{name: "shared", library: true}
-	sharedExportDepTag    = dependencyTag{name: "shared", library: true, reexportFlags: true}
-	earlySharedDepTag     = dependencyTag{name: "early_shared", library: true}
-	lateSharedDepTag      = dependencyTag{name: "late shared", library: true}
+	sharedDepTag          = dependencyTag{name: "shared", library: true, shared: true}
+	sharedExportDepTag    = dependencyTag{name: "shared", library: true, shared: true, reexportFlags: true}
+	earlySharedDepTag     = dependencyTag{name: "early_shared", library: true, shared: true}
+	lateSharedDepTag      = dependencyTag{name: "late shared", library: true, shared: true}
 	staticDepTag          = dependencyTag{name: "static", library: true}
 	staticExportDepTag    = dependencyTag{name: "static", library: true, reexportFlags: true}
 	lateStaticDepTag      = dependencyTag{name: "late static", library: true}
@@ -375,6 +382,21 @@
 	testPerSrcDepTag      = dependencyTag{name: "test_per_src"}
 )
 
+func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
+	ccDepTag, ok := depTag.(dependencyTag)
+	return ok && ccDepTag.shared
+}
+
+func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
+	ccDepTag, ok := depTag.(dependencyTag)
+	return ok && ccDepTag == runtimeDepTag
+}
+
+func IsTestPerSrcDepTag(depTag blueprint.DependencyTag) bool {
+	ccDepTag, ok := depTag.(dependencyTag)
+	return ok && ccDepTag == testPerSrcDepTag
+}
+
 // Module contains the properties and members used by all C/C++ module types, and implements
 // the blueprint.Module interface.  It delegates to compiler, linker, and installer interfaces
 // to construct the output file.  Behavior can be customized with a Customizer interface
@@ -408,9 +430,6 @@
 
 	outputFile android.OptionalPath
 
-	// Test output files, in the case of a test module using `test_per_src`.
-	testPerSrcOutputFiles []android.Path
-
 	cachedToolchain config.Toolchain
 
 	subAndroidMkOnce map[subAndroidMkProvider]bool
@@ -427,16 +446,14 @@
 	staticVariant *Module
 
 	makeLinkType string
+	// Kythe (source file indexer) paths for this compilation module
+	kytheFiles android.Paths
 }
 
 func (c *Module) OutputFile() android.OptionalPath {
 	return c.outputFile
 }
 
-func (c *Module) TestPerSrcOutputFiles() []android.Path {
-	return c.testPerSrcOutputFiles
-}
-
 func (c *Module) UnstrippedOutputFile() android.Path {
 	if c.linker != nil {
 		return c.linker.unstrippedOutputFilePath()
@@ -657,6 +674,10 @@
 	return isBionic(name)
 }
 
+func (c *Module) XrefCcFiles() android.Paths {
+	return c.kytheFiles
+}
+
 type baseModuleContext struct {
 	android.BaseModuleContext
 	moduleContextImpl
@@ -950,28 +971,20 @@
 	return results
 }
 
+func (c *Module) IsTestPerSrcAllTestsVariation() bool {
+	test, ok := c.linker.(testPerSrc)
+	return ok && test.isAllTestsVariation()
+}
+
 func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
 	// Handle the case of a test module split by `test_per_src` mutator.
-	if test, ok := c.linker.(testPerSrc); ok {
-		// The `test_per_src` mutator adds an extra variant named "", depending on all the
-		// other `test_per_src` variants of the test module. Collect the output files of
-		// these dependencies and record them in the `testPerSrcOutputFiles` for later use
-		// (see e.g. `apexBundle.GenerateAndroidBuildActions`).
-		if test.isAllTestsVariation() {
-			var testPerSrcOutputFiles []android.Path
-			for _, dep := range actx.GetDirectDepsWithTag(testPerSrcDepTag) {
-				if ccDep, ok := dep.(*Module); ok {
-					depOutputFile := ccDep.OutputFile().Path()
-					testPerSrcOutputFiles =
-						append(testPerSrcOutputFiles, depOutputFile)
-				}
-			}
-			c.testPerSrcOutputFiles = testPerSrcOutputFiles
-			// Set outputFile to an empty path, as this module does not produce an
-			// output file per se.
-			c.outputFile = android.OptionalPath{}
-			return
-		}
+	//
+	// The `test_per_src` mutator adds an extra variation named "", depending on all the other
+	// `test_per_src` variations of the test module. Set `outputFile` to an empty path for this
+	// module and return early, as this module does not produce an output file per se.
+	if c.IsTestPerSrcAllTestsVariation() {
+		c.outputFile = android.OptionalPath{}
+		return
 	}
 
 	c.makeLinkType = c.getMakeLinkType(actx)
@@ -995,6 +1008,7 @@
 
 	flags := Flags{
 		Toolchain: c.toolchain(ctx),
+		EmitXrefs: ctx.Config().EmitXrefRules(),
 	}
 	if c.compiler != nil {
 		flags = c.compiler.compilerFlags(ctx, flags, deps)
@@ -1060,6 +1074,7 @@
 		if ctx.Failed() {
 			return
 		}
+		c.kytheFiles = objs.kytheFiles
 	}
 
 	if c.linker != nil {
@@ -2050,12 +2065,14 @@
 }
 
 // Overrides ApexModule.IsInstallabeToApex()
-// Only shared libraries are installable to APEX.
+// Only shared/runtime libraries and "test_per_src" tests are installable to APEX.
 func (c *Module) IsInstallableToApex() bool {
 	if shared, ok := c.linker.(interface {
 		shared() bool
 	}); ok {
 		return shared.shared()
+	} else if _, ok := c.linker.(testPerSrc); ok {
+		return true
 	}
 	return false
 }
@@ -2366,6 +2383,31 @@
 	return ctx.Config().PlatformSdkVersion()
 }
 
+func kytheExtractAllFactory() android.Singleton {
+	return &kytheExtractAllSingleton{}
+}
+
+type kytheExtractAllSingleton struct {
+}
+
+func (ks *kytheExtractAllSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	var xrefTargets android.Paths
+	ctx.VisitAllModules(func(module android.Module) {
+		if ccModule, ok := module.(xref); ok {
+			xrefTargets = append(xrefTargets, ccModule.XrefCcFiles()...)
+		}
+	})
+	// TODO(asmundak): Perhaps emit a rule to output a warning if there were no xrefTargets
+	if len(xrefTargets) > 0 {
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   blueprint.Phony,
+			Output: android.PathForPhony(ctx, "xref_cxx"),
+			Inputs: xrefTargets,
+			//Default: true,
+		})
+	}
+}
+
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var BoolPtr = proptools.BoolPtr
diff --git a/cc/compiler.go b/cc/compiler.go
index 0f9599e..ffb6ad2 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"strconv"
 	"strings"
 
 	"github.com/google/blueprint/proptools"
@@ -308,27 +309,10 @@
 		flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
 			"-isystem "+getCurrentIncludePath(ctx).String(),
 			"-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
-
-		// TODO: Migrate to API suffixed triple?
-		// Traditionally this has come from android/api-level.h, but with the
-		// libc headers unified it must be set by the build system since we
-		// don't have per-API level copies of that header now.
-		version := ctx.sdkVersion()
-		if version == "current" {
-			version = "__ANDROID_API_FUTURE__"
-		}
-		flags.GlobalFlags = append(flags.GlobalFlags,
-			"-D__ANDROID_API__="+version)
 	}
 
 	if ctx.useVndk() {
-		// sdkVersion() returns VNDK version for vendor modules.
-		version := ctx.sdkVersion()
-		if version == "current" {
-			version = "__ANDROID_API_FUTURE__"
-		}
-		flags.GlobalFlags = append(flags.GlobalFlags,
-			"-D__ANDROID_API__="+version, "-D__ANDROID_VNDK__")
+		flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_VNDK__")
 	}
 
 	if ctx.inRecovery() {
@@ -364,6 +348,15 @@
 	flags.LdFlags = config.ClangFilterUnknownCflags(flags.LdFlags)
 
 	target := "-target " + tc.ClangTriple()
+	if ctx.Os().Class == android.Device {
+		version := ctx.sdkVersion()
+		if version == "" || version == "current" {
+			target += strconv.Itoa(android.FutureApiLevel)
+		} else {
+			target += version
+		}
+	}
+
 	gccPrefix := "-B" + config.ToolPath(tc)
 
 	flags.CFlags = append(flags.CFlags, target, gccPrefix)
diff --git a/cc/library.go b/cc/library.go
index 7cbfdb5..2b7c9a1 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -110,6 +110,9 @@
 		// Symbol tags that should be ignored from the symbol file
 		Exclude_symbol_tags []string
 	}
+
+	// Order symbols in .bss section by their sizes.  Only useful for shared libraries.
+	Sort_bss_symbols_by_size *bool
 }
 
 type LibraryMutatedProperties struct {
@@ -758,6 +761,18 @@
 	linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
 	linkerDeps = append(linkerDeps, objs.tidyFiles...)
 
+	if Bool(library.Properties.Sort_bss_symbols_by_size) {
+		unsortedOutputFile := android.PathForModuleOut(ctx, "unsorted", fileName)
+		TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
+			deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
+			linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, unsortedOutputFile, implicitOutputs)
+
+		symbolOrderingFile := android.PathForModuleOut(ctx, "unsorted", fileName+".symbol_order")
+		symbolOrderingFlag := library.baseLinker.sortBssSymbolsBySize(ctx, unsortedOutputFile, symbolOrderingFile, builderFlags)
+		builderFlags.ldFlags += " " + symbolOrderingFlag
+		linkerDeps = append(linkerDeps, symbolOrderingFile)
+	}
+
 	TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
 		deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
 		linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs)
diff --git a/cc/linker.go b/cc/linker.go
index fa3b0a6..daacec1 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -147,9 +147,6 @@
 
 	// local file name to pass to the linker as --version_script
 	Version_script *string `android:"path,arch_variant"`
-
-	// Local file name to pass to the linker as --symbol-ordering-file
-	Symbol_ordering_file *string `android:"arch_variant"`
 }
 
 func NewBaseLinker(sanitize *sanitize) *baseLinker {
@@ -442,16 +439,6 @@
 		}
 	}
 
-	if !linker.dynamicProperties.BuildStubs {
-		symbolOrderingFile := ctx.ExpandOptionalSource(
-			linker.Properties.Symbol_ordering_file, "Symbol_ordering_file")
-		if symbolOrderingFile.Valid() {
-			flags.LdFlags = append(flags.LdFlags,
-				"-Wl,--symbol-ordering-file,"+symbolOrderingFile.String())
-			flags.LdFlagsDeps = append(flags.LdFlagsDeps, symbolOrderingFile.Path())
-		}
-	}
-
 	return flags
 }
 
@@ -487,3 +474,29 @@
 		},
 	})
 }
+
+// Rule to generate .bss symbol ordering file.
+
+var (
+	_                      = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh")
+	gen_sorted_bss_symbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
+		blueprint.RuleParams{
+			Command:     "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}",
+			CommandDeps: []string{"$genSortedBssSymbolsPath"},
+		},
+		"crossCompile")
+)
+
+func (linker *baseLinker) sortBssSymbolsBySize(ctx ModuleContext, in android.Path, symbolOrderingFile android.ModuleOutPath, flags builderFlags) string {
+	crossCompile := gccCmd(flags.toolchain, "")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        gen_sorted_bss_symbols,
+		Description: "generate bss symbol order " + symbolOrderingFile.Base(),
+		Output:      symbolOrderingFile,
+		Input:       in,
+		Args: map[string]string{
+			"crossCompile": crossCompile,
+		},
+	})
+	return "-Wl,--symbol-ordering-file," + symbolOrderingFile.String()
+}
diff --git a/cc/makevars.go b/cc/makevars.go
index a42429f..f9c58b9 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -266,9 +266,9 @@
 	}
 
 	clangPrefix := secondPrefix + "CLANG_" + typePrefix
-	clangExtras := "-target " + toolchain.ClangTriple()
-	clangExtras += " -B" + config.ToolPath(toolchain)
+	clangExtras := "-B" + config.ToolPath(toolchain)
 
+	ctx.Strict(clangPrefix+"TRIPLE", toolchain.ClangTriple())
 	ctx.Strict(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{
 		toolchain.ClangCflags(),
 		"${config.CommonClangGlobalCflags}",
diff --git a/cc/util.go b/cc/util.go
index 2e1bb25..0d1b2f0 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -74,6 +74,7 @@
 		coverage:        in.Coverage,
 		tidy:            in.Tidy,
 		sAbiDump:        in.SAbiDump,
+		emitXrefs:       in.EmitXrefs,
 
 		systemIncludeFlags: strings.Join(in.SystemIncludeFlags, " "),
 
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 0eaed76..0bc3606 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -416,7 +416,26 @@
 		fmt.Fprintln(writer, "!")
 		fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
 		fmt.Fprintln(writer, "")
-		time.Sleep(5 * time.Second)
+		select {
+		case <-time.After(5 * time.Second):
+		case <-ctx.Done():
+			return
+		}
+	}
+
+	if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
+		writer := ctx.Writer
+		fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is deprecated, and will be removed shortly.")
+		fmt.Fprintln(writer, "!")
+		fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
+		fmt.Fprintln(writer, "!")
+		fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
+		fmt.Fprintln(writer, "")
+		select {
+		case <-time.After(30 * time.Second):
+		case <-ctx.Done():
+			return
+		}
 	}
 
 	toBuild := build.BuildAll
diff --git a/java/app.go b/java/app.go
index a679e88..674e5ec 100644
--- a/java/app.go
+++ b/java/app.go
@@ -191,9 +191,12 @@
 	}
 }
 
+func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	a.generateAndroidBuildActions(ctx)
+}
+
 func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
-	a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
+	a.checkPlatformAPI(ctx)
 	a.generateAndroidBuildActions(ctx)
 }
 
@@ -422,6 +425,9 @@
 func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
 	var apkDeps android.Paths
 
+	a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
+	a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
+
 	// Check if the install APK name needs to be overridden.
 	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
 
@@ -584,8 +590,6 @@
 			a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName)
 		}
 	}
-	a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
-	a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
 	a.generateAndroidBuildActions(ctx)
 
 	a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites)
diff --git a/java/app_test.go b/java/app_test.go
index 32de019..f6a307e 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -72,6 +72,7 @@
 			ctx := testApp(t, moduleType+` {
 					name: "foo",
 					srcs: ["a.java"],
+					sdk_version: "current"
 				}
 			`)
 
@@ -117,6 +118,7 @@
 					name: "foo",
 					srcs: ["a.java"],
 					package_splits: ["v4", "v7,hdpi"],
+					sdk_version: "current"
 				}`)
 
 	foo := ctx.ModuleForTests("foo", "android_common")
@@ -139,6 +141,40 @@
 	}
 }
 
+func TestPlatformAPIs(t *testing.T) {
+	testJava(t, `
+		android_app {
+			name: "foo",
+			srcs: ["a.java"],
+			platform_apis: true,
+		}
+	`)
+
+	testJava(t, `
+		android_app {
+			name: "foo",
+			srcs: ["a.java"],
+			sdk_version: "current",
+		}
+	`)
+
+	testJavaError(t, "platform_apis must be true when sdk_version is empty.", `
+		android_app {
+			name: "bar",
+			srcs: ["b.java"],
+		}
+	`)
+
+	testJavaError(t, "platform_apis must be false when sdk_version is not empty.", `
+		android_app {
+			name: "bar",
+			srcs: ["b.java"],
+			sdk_version: "system_current",
+			platform_apis: true,
+		}
+	`)
+}
+
 func TestResourceDirs(t *testing.T) {
 	testCases := []struct {
 		name      string
@@ -169,6 +205,7 @@
 	bp := `
 			android_app {
 				name: "foo",
+				sdk_version: "current",
 				%s
 			}
 		`
@@ -349,12 +386,14 @@
 	bp := `
 			android_app {
 				name: "foo",
+				sdk_version: "current",
 				resource_dirs: ["foo/res"],
 				static_libs: ["lib", "lib3"],
 			}
 
 			android_app {
 				name: "bar",
+				sdk_version: "current",
 				resource_dirs: ["bar/res"],
 			}
 
@@ -461,6 +500,7 @@
 		platformSdkCodename   string
 		platformSdkFinal      bool
 		expectedMinSdkVersion string
+		platformApis          bool
 	}{
 		{
 			name:                  "current final SDK",
@@ -481,6 +521,7 @@
 		{
 			name:                  "default final SDK",
 			sdkVersion:            "",
+			platformApis:          true,
 			platformSdkInt:        27,
 			platformSdkCodename:   "REL",
 			platformSdkFinal:      true,
@@ -489,6 +530,7 @@
 		{
 			name:                  "default non-final SDK",
 			sdkVersion:            "",
+			platformApis:          true,
 			platformSdkInt:        27,
 			platformSdkCodename:   "OMR1",
 			platformSdkFinal:      false,
@@ -504,11 +546,16 @@
 	for _, moduleType := range []string{"android_app", "android_library"} {
 		for _, test := range testCases {
 			t.Run(moduleType+" "+test.name, func(t *testing.T) {
+				platformApiProp := ""
+				if test.platformApis {
+					platformApiProp = "platform_apis: true,"
+				}
 				bp := fmt.Sprintf(`%s {
 					name: "foo",
 					srcs: ["a.java"],
 					sdk_version: "%s",
-				}`, moduleType, test.sdkVersion)
+					%s
+				}`, moduleType, test.sdkVersion, platformApiProp)
 
 				config := testConfig(nil)
 				config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
@@ -630,18 +677,21 @@
 		android_app {
 			name: "app",
 			jni_libs: ["libjni"],
+			sdk_version: "current",
 		}
 
 		android_app {
 			name: "app_noembed",
 			jni_libs: ["libjni"],
 			use_embedded_native_libs: false,
+			sdk_version: "current",
 		}
 
 		android_app {
 			name: "app_embed",
 			jni_libs: ["libjni"],
 			use_embedded_native_libs: true,
+			sdk_version: "current",
 		}
 
 		android_test {
@@ -715,6 +765,7 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			certificateOverride: "",
@@ -726,7 +777,8 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
-					certificate: ":new_certificate"
+					certificate: ":new_certificate",
+					sdk_version: "current",
 				}
 
 				android_app_certificate {
@@ -743,7 +795,8 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
-					certificate: "expiredkey"
+					certificate: "expiredkey",
+					sdk_version: "current",
 				}
 			`,
 			certificateOverride: "",
@@ -755,7 +808,8 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
-					certificate: "expiredkey"
+					certificate: "expiredkey",
+					sdk_version: "current",
 				}
 
 				android_app_certificate {
@@ -801,6 +855,7 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			packageNameOverride: "",
@@ -815,6 +870,7 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			packageNameOverride: "foo:bar",
@@ -856,11 +912,13 @@
 		android_app {
 			name: "foo",
 			srcs: ["a.java"],
+			sdk_version: "current",
 		}
 
 		android_test {
 			name: "bar",
 			instrumentation_for: "foo",
+			sdk_version: "current",
 		}
 		`
 	config := testConfig(nil)
@@ -885,6 +943,7 @@
 			srcs: ["a.java"],
 			certificate: "expiredkey",
 			overrides: ["qux"],
+			sdk_version: "current",
 		}
 
 		override_android_app {
@@ -984,6 +1043,7 @@
 		android_app {
 			name: "foo",
 			srcs: ["a.java"],
+			sdk_version: "current",
 		}
 
 		override_android_app {
@@ -1253,18 +1313,21 @@
 			name: "foo",
 			srcs: ["a.java"],
 			api_packages: ["foo"],
+			sdk_version: "current",
 		}
 
 		java_sdk_library {
 			name: "bar",
 			srcs: ["a.java"],
 			api_packages: ["bar"],
+			sdk_version: "current",
 		}
 
 		android_app {
 			name: "app",
 			srcs: ["a.java"],
 			uses_libs: ["foo"],
+			sdk_version: "current",
 			optional_uses_libs: [
 				"bar",
 				"baz",
@@ -1339,6 +1402,7 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			noCode: false,
@@ -1348,6 +1412,7 @@
 			bp: `
 				android_app {
 					name: "foo",
+					sdk_version: "current",
 				}
 			`,
 			noCode: true,
@@ -1358,11 +1423,13 @@
 				android_app {
 					name: "foo",
 					static_libs: ["lib"],
+					sdk_version: "current",
 				}
 
 				java_library {
 					name: "lib",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			noCode: false,
@@ -1373,10 +1440,12 @@
 				android_app {
 					name: "foo",
 					static_libs: ["lib"],
+					sdk_version: "current",
 				}
 
 				java_library {
 					name: "lib",
+					sdk_version: "current",
 				}
 			`,
 			// TODO(jungjw): this should probably be true
@@ -1406,6 +1475,7 @@
 			jni_libs: ["libjni"],
 			notice: "APP_NOTICE",
 			embed_notices: true,
+			sdk_version: "current",
 		}
 
 		// No embed_notice flag
@@ -1414,6 +1484,7 @@
 			srcs: ["a.java"],
 			jni_libs: ["libjni"],
 			notice: "APP_NOTICE",
+			sdk_version: "current",
 		}
 
 		// No NOTICE files
@@ -1421,6 +1492,7 @@
 			name: "baz",
 			srcs: ["a.java"],
 			embed_notices: true,
+			sdk_version: "current",
 		}
 
 		cc_library {
@@ -1435,6 +1507,7 @@
 			srcs: [
 				":gen",
 			],
+			sdk_version: "current",
 		}
 
 		genrule {
@@ -1510,6 +1583,7 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			uncompressedPlatform:  true,
@@ -1522,6 +1596,7 @@
 					name: "foo",
 					use_embedded_dex: true,
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			uncompressedPlatform:  true,
@@ -1534,6 +1609,7 @@
 					name: "foo",
 					privileged: true,
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}
 			`,
 			uncompressedPlatform:  true,
diff --git a/java/builder.go b/java/builder.go
index 22eff7c..f174cf0 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -62,6 +62,37 @@
 		"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
 		"outDir", "annoDir", "javaVersion")
 
+	_ = pctx.VariableFunc("kytheCorpus",
+		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
+	// Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about
+	// "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
+	// to field java.nio.Buffer.address"
+	kytheExtract = pctx.AndroidStaticRule("kythe",
+		blueprint.RuleParams{
+			Command: `${config.ZipSyncCmd} -d $srcJarDir ` +
+				`-l $srcJarDir/list -f "*.java" $srcJars && ` +
+				`( [ ! -s $srcJarDir/list -a ! -s $out.rsp ] || ` +
+				`KYTHE_ROOT_DIRECTORY=. KYTHE_OUTPUT_FILE=$out ` +
+				`KYTHE_CORPUS=${kytheCorpus} ` +
+				`${config.SoongJavacWrapper} ${config.JavaCmd} ` +
+				`--add-opens=java.base/java.nio=ALL-UNNAMED ` +
+				`-jar ${config.JavaKytheExtractorJar} ` +
+				`${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
+				`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
+				`-source $javaVersion -target $javaVersion ` +
+				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list)`,
+			CommandDeps: []string{
+				"${config.JavaCmd}",
+				"${config.JavaKytheExtractorJar}",
+				"${config.ZipSyncCmd}",
+			},
+			CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+			Rspfile:          "$out.rsp",
+			RspfileContent:   "$in",
+		},
+		"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
+		"outDir", "annoDir", "javaVersion")
+
 	turbine = pctx.AndroidStaticRule("turbine",
 		blueprint.RuleParams{
 			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -196,6 +227,61 @@
 		"errorprone", "errorprone")
 }
 
+// Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars
+// to compile with given set of builder flags, etc.
+func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath,
+	srcFiles, srcJars android.Paths,
+	flags javaBuilderFlags, deps android.Paths,
+	intermediatesDir string) {
+
+	deps = append(deps, srcJars...)
+
+	var bootClasspath string
+	if flags.javaVersion == "1.9" {
+		var systemModuleDeps android.Paths
+		bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device())
+		deps = append(deps, systemModuleDeps...)
+	} else {
+		deps = append(deps, flags.bootClasspath...)
+		if len(flags.bootClasspath) == 0 && ctx.Device() {
+			// explicitly specify -bootclasspath "" if the bootclasspath is empty to
+			// ensure java does not fall back to the default bootclasspath.
+			bootClasspath = `-bootclasspath ""`
+		} else {
+			bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath")
+		}
+	}
+
+	deps = append(deps, flags.classpath...)
+	deps = append(deps, flags.processorPath...)
+
+	processor := "-proc:none"
+	if flags.processor != "" {
+		processor = "-processor " + flags.processor
+	}
+
+	ctx.Build(pctx,
+		android.BuildParams{
+			Rule:        kytheExtract,
+			Description: "Xref Java extractor",
+			Output:      xrefFile,
+			Inputs:      srcFiles,
+			Implicits:   deps,
+			Args: map[string]string{
+				"annoDir":       android.PathForModuleOut(ctx, intermediatesDir, "anno").String(),
+				"bootClasspath": bootClasspath,
+				"classpath":     flags.classpath.FormJavaClassPath("-classpath"),
+				"javacFlags":    flags.javacFlags,
+				"javaVersion":   flags.javaVersion,
+				"outDir":        android.PathForModuleOut(ctx, "javac", "classes.xref").String(),
+				"processorpath": flags.processorPath.FormJavaClassPath("-processorpath"),
+				"processor":     processor,
+				"srcJarDir":     android.PathForModuleOut(ctx, intermediatesDir, "srcjars.xref").String(),
+				"srcJars":       strings.Join(srcJars.Strings(), " "),
+			},
+		})
+}
+
 func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
diff --git a/java/config/config.go b/java/config/config.go
index 6a0a10a..cb13744 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -94,6 +94,7 @@
 	pctx.SourcePathVariable("JlinkCmd", "${JavaToolchain}/jlink")
 	pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod")
 	pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar")
+	pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar")
 	pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
 
 	pctx.SourcePathVariable("GenKotlinBuildFileCmd", "build/soong/scripts/gen-kotlin-build-file.sh")
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 19e92b7..2a142ba 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -298,6 +298,7 @@
 		FlagForEachArg("--dex-location=", image.dexLocations).
 		Flag("--generate-debug-info").
 		Flag("--generate-build-id").
+		Flag("--image-format=lz4hc").
 		FlagWithOutput("--oat-symbols=", symbolsFile).
 		Flag("--strip").
 		FlagWithOutput("--oat-file=", outputPath.ReplaceExtension(ctx, "oat")).
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 22b7bb9..5550a4c 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -30,6 +30,7 @@
 				android_app {
 					name: "foo",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}`,
 			enabled: true,
 		},
@@ -57,6 +58,7 @@
 			bp: `
 				android_app {
 					name: "foo",
+					sdk_version: "current",
 				}`,
 			enabled: false,
 		},
@@ -66,11 +68,13 @@
 				android_app {
 					name: "foo",
 					static_libs: ["lib"],
+					sdk_version: "current",
 				}
 
 				java_library {
 					name: "lib",
 					srcs: ["a.java"],
+					sdk_version: "current",
 				}`,
 			enabled: true,
 		},
diff --git a/java/java.go b/java/java.go
index 5f4a090..fea38b5 100644
--- a/java/java.go
+++ b/java/java.go
@@ -50,6 +50,21 @@
 	android.RegisterModuleType("dex_import", DexImportFactory)
 
 	android.RegisterSingletonType("logtags", LogtagsSingleton)
+	android.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
+}
+
+func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
+	if sc, ok := ctx.Module().(sdkContext); ok {
+		usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
+		if usePlatformAPI != (sc.sdkVersion() == "") {
+			if usePlatformAPI {
+				ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
+			} else {
+				ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.")
+			}
+		}
+
+	}
 }
 
 // TODO:
@@ -178,8 +193,8 @@
 	// list of module-specific flags that will be used for dex compiles
 	Dxflags []string `android:"arch_variant"`
 
-	// if not blank, set to the version of the sdk to compile against.  Defaults to compiling against the current
-	// sdk if platform_apis is not set.
+	// if not blank, set to the version of the sdk to compile against.
+	// Defaults to compiling against the current platform.
 	Sdk_version *string
 
 	// if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
@@ -190,7 +205,8 @@
 	// Defaults to sdk_version if not set.
 	Target_sdk_version *string
 
-	// if true, compile against the platform APIs instead of an SDK.
+	// It must be true only if sdk_version is empty.
+	// This field works in only android_app, otherwise nothing happens.
 	Platform_apis *bool
 
 	Aidl struct {
@@ -343,6 +359,9 @@
 
 	hiddenAPI
 	dexpreopter
+
+	// list of the xref extraction files
+	kytheFiles android.Paths
 }
 
 func (j *Module) OutputFiles(tag string) (android.Paths, error) {
@@ -383,6 +402,10 @@
 	CompiledSrcJars() android.Paths
 }
 
+type xref interface {
+	XrefJavaFiles() android.Paths
+}
+
 func (j *Module) CompiledSrcs() android.Paths {
 	return j.compiledJavaSrcs
 }
@@ -391,6 +414,10 @@
 	return j.compiledSrcJars
 }
 
+func (j *Module) XrefJavaFiles() android.Paths {
+	return j.kytheFiles
+}
+
 var _ SrcDependency = (*Module)(nil)
 
 func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
@@ -1139,6 +1166,12 @@
 			TransformJavaToClasses(ctx, classes, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
 			jars = append(jars, classes)
 		}
+		if ctx.Config().EmitXrefRules() {
+			extractionFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".kzip")
+			emitXrefRule(ctx, extractionFile, uniqueSrcFiles, srcJars, flags, extraJarDeps, "xref")
+			j.kytheFiles = append(j.kytheFiles, extractionFile)
+
+		}
 		if ctx.Failed() {
 			return
 		}
@@ -2213,6 +2246,30 @@
 	return module
 }
 
+func kytheExtractJavaFactory() android.Singleton {
+	return &kytheExtractJavaSingleton{}
+}
+
+type kytheExtractJavaSingleton struct {
+}
+
+func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	var xrefTargets android.Paths
+	ctx.VisitAllModules(func(module android.Module) {
+		if javaModule, ok := module.(xref); ok {
+			xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...)
+		}
+	})
+	// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
+	if len(xrefTargets) > 0 {
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   blueprint.Phony,
+			Output: android.PathForPhony(ctx, "xref_java"),
+			Inputs: xrefTargets,
+		})
+	}
+}
+
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var String = proptools.String
diff --git a/java/java_test.go b/java/java_test.go
index f95f88b..81d1f2c 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -222,6 +222,29 @@
 	android.FailIfErrored(t, errs)
 }
 
+func testJavaError(t *testing.T, pattern string, bp string) {
+	t.Helper()
+	config := testConfig(nil)
+	ctx := testContext(bp, nil)
+
+	pathCtx := android.PathContextForTesting(config, nil)
+	setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
+
+	ctx.Register()
+	_, errs := ctx.ParseBlueprintsFiles("Android.bp")
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+	_, errs = ctx.PrepareBuildActions(config)
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+
+	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+}
+
 func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
 	t.Helper()
 	config := testConfig(nil)
diff --git a/scripts/gen_sorted_bss_symbols.sh b/scripts/gen_sorted_bss_symbols.sh
new file mode 100755
index 0000000..244ed0d
--- /dev/null
+++ b/scripts/gen_sorted_bss_symbols.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -e
+
+# Copyright 2019 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.
+
+# Script to generate a symbol ordering file that sorts bss section symbols by
+# their sizes.
+# Inputs:
+#  Environment:
+#   CROSS_COMPILE: prefix added to nm tools
+#  Arguments:
+#   $1: Input ELF file
+#   $2: Output symbol ordering file
+
+set -o pipefail
+
+${CROSS_COMPILE}nm --size-sort $1 | awk '{if ($2 == "b" || $2 == "B") print $3}' > $2
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 266130f..6b9eac1 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -169,7 +169,7 @@
 	// Variables to export into the environment of Kati/Ninja
 	exportEnvVars := []string{
 		// So that we can use the correct TARGET_PRODUCT if it's been
-		// modified by PRODUCT-*/APP-* arguments
+		// modified by a buildspec.mk
 		"TARGET_PRODUCT",
 		"TARGET_BUILD_VARIANT",
 		"TARGET_BUILD_APPS",
diff --git a/ui/terminal/smart_status.go b/ui/terminal/smart_status.go
index 8659d4d..57f71ab 100644
--- a/ui/terminal/smart_status.go
+++ b/ui/terminal/smart_status.go
@@ -59,21 +59,24 @@
 // current build status similarly to Ninja's built-in terminal
 // output.
 func NewSmartStatusOutput(w io.Writer, formatter formatter) status.StatusOutput {
-	tableHeight, _ := strconv.Atoi(os.Getenv(tableHeightEnVar))
-
 	s := &smartStatusOutput{
 		writer:    w,
 		formatter: formatter,
 
 		haveBlankLine: true,
 
-		tableMode:            tableHeight > 0,
-		requestedTableHeight: tableHeight,
+		tableMode: true,
 
 		done:     make(chan bool),
 		sigwinch: make(chan os.Signal),
 	}
 
+	if env, ok := os.LookupEnv(tableHeightEnVar); ok {
+		h, _ := strconv.Atoi(env)
+		s.tableMode = h > 0
+		s.requestedTableHeight = h
+	}
+
 	s.updateTermSize()
 
 	if s.tableMode {
@@ -297,6 +300,14 @@
 
 		if s.tableMode {
 			tableHeight := s.requestedTableHeight
+			if tableHeight == 0 {
+				tableHeight = s.termHeight / 4
+				if tableHeight < 1 {
+					tableHeight = 1
+				} else if tableHeight > 10 {
+					tableHeight = 10
+				}
+			}
 			if tableHeight > s.termHeight-1 {
 				tableHeight = s.termHeight - 1
 			}