Merge "Add a unified status reporting UI"
diff --git a/Android.bp b/Android.bp
index 2daa958..26aeac2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -221,6 +221,7 @@
     srcs: [
         "java/aapt2.go",
         "java/aar.go",
+        "java/android_manifest.go",
         "java/android_resources.go",
         "java/androidmk.go",
         "java/app_builder.go",
diff --git a/android/arch.go b/android/arch.go
index ebe9897..d84c829 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -330,6 +330,10 @@
 			// Windows builds always prefer 32-bit
 			prefer32 = true
 		}
+		// only the primary arch in the recovery partition
+		if module.InstallInRecovery() {
+			targets = []Target{mctx.Config().Targets[Device][0]}
+		}
 		targets, err := decodeMultilib(multilib, targets, prefer32)
 		if err != nil {
 			mctx.ModuleErrorf("%s", err.Error())
diff --git a/android/makevars.go b/android/makevars.go
index 3094a48..accc4d3 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -20,6 +20,7 @@
 	"io/ioutil"
 	"os"
 	"strconv"
+	"strings"
 
 	"github.com/google/blueprint/proptools"
 )
@@ -240,8 +241,16 @@
 	return c.ctx
 }
 
+var ninjaDescaper = strings.NewReplacer("$$", "$")
+
 func (c *makeVarsContext) Eval(ninjaStr string) (string, error) {
-	return c.ctx.Eval(c.pctx, ninjaStr)
+	s, err := c.ctx.Eval(c.pctx, ninjaStr)
+	if err != nil {
+		return "", err
+	}
+	// SingletonContext.Eval returns an exapnded string that is valid for a ninja file, de-escape $$ to $ for use
+	// in a Makefile
+	return ninjaDescaper.Replace(s), nil
 }
 
 func (c *makeVarsContext) addVariableRaw(name, value string, strict, sort bool) {
diff --git a/android/testing.go b/android/testing.go
index f5d33e1..ca7e7ce 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -92,6 +92,16 @@
 	return TestingModule{module}
 }
 
+func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
+	var variants []string
+	ctx.VisitAllModules(func(m blueprint.Module) {
+		if ctx.ModuleName(m) == name {
+			variants = append(variants, ctx.ModuleSubDir(m))
+		}
+	})
+	return variants
+}
+
 // MockFileSystem causes the Context to replace all reads with accesses to the provided map of
 // filenames to contents stored as a byte slice.
 func (ctx *TestContext) MockFileSystem(files map[string][]byte) {
diff --git a/android/variable.go b/android/variable.go
index 4cd5313..5edcdbc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -92,6 +92,9 @@
 		Eng struct {
 			Cflags   []string
 			Cppflags []string
+			Lto      struct {
+				Never *bool
+			}
 		}
 
 		Pdk struct {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 1b12ad4..3d162e7 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -75,16 +75,19 @@
 		toolchain_library {
 			name: "libatomic",
 			vendor_available: true,
+			recovery_available: true,
 		}
 
 		toolchain_library {
 			name: "libcompiler_rt-extras",
 			vendor_available: true,
+			recovery_available: true,
 		}
 
 		toolchain_library {
 			name: "libgcc",
 			vendor_available: true,
+			recovery_available: true,
 		}
 
 		cc_library {
@@ -92,6 +95,7 @@
 			no_libgcc: true,
 			nocrt: true,
 			system_shared_libs: [],
+			recovery_available: true,
 		}
 		llndk_library {
 			name: "libc",
@@ -102,6 +106,7 @@
 			no_libgcc: true,
 			nocrt: true,
 			system_shared_libs: [],
+			recovery_available: true,
 		}
 		llndk_library {
 			name: "libm",
@@ -112,6 +117,7 @@
 			no_libgcc: true,
 			nocrt: true,
 			system_shared_libs: [],
+			recovery_available: true,
 		}
 		llndk_library {
 			name: "libdl",
@@ -124,6 +130,7 @@
 			system_shared_libs: [],
 			stl: "none",
 			vendor_available: true,
+			recovery_available: true,
 		}
 		cc_library {
 			name: "libc++",
@@ -132,6 +139,7 @@
 			system_shared_libs: [],
 			stl: "none",
 			vendor_available: true,
+			recovery_available: true,
 			vndk: {
 				enabled: true,
 				support_system_process: true,
@@ -144,14 +152,17 @@
 			system_shared_libs: [],
 			stl: "none",
 			vendor_available: true,
+			recovery_available: true,
 		}
 
 		cc_object {
 			name: "crtbegin_so",
+			recovery_available: true,
 		}
 
 		cc_object {
 			name: "crtend_so",
+			recovery_available: true,
 		}
 
 		cc_library {
@@ -1651,3 +1662,28 @@
 	}
 
 }
+
+func TestRecovery(t *testing.T) {
+	ctx := testCc(t, `
+		cc_library_shared {
+			name: "librecovery",
+			recovery: true,
+		}
+		cc_library_shared {
+			name: "librecovery32",
+			recovery: true,
+			compile_multilib:"32",
+		}
+	`)
+
+	variants := ctx.ModuleVariantsForTests("librecovery")
+	const arm64 = "android_arm64_armv8-a_recovery_shared"
+	if len(variants) != 1 || !android.InList(arm64, variants) {
+		t.Errorf("variants of librecovery must be \"%s\" only, but was %#v", arm64, variants)
+	}
+
+	variants = ctx.ModuleVariantsForTests("librecovery32")
+	if android.InList(arm64, variants) {
+		t.Errorf("multilib was set to 32 for librecovery32, but its variants has %s.", arm64)
+	}
+}
diff --git a/java/aar.go b/java/aar.go
index 91e2f7f..0cfc585 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -27,6 +27,7 @@
 	ExportPackage() android.Path
 	ExportedProguardFlagFiles() android.Paths
 	ExportedStaticPackages() android.Paths
+	ExportedManifest() android.Path
 }
 
 func init() {
@@ -74,8 +75,8 @@
 	return a.exportPackage
 }
 
-func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext) (flags []string, deps android.Paths,
-	resDirs, overlayDirs []globbedResourceDir, overlayFiles, rroDirs android.Paths, manifestPath android.Path) {
+func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, manifestPath android.Path) (flags []string,
+	deps android.Paths, resDirs, overlayDirs []globbedResourceDir, rroDirs android.Paths) {
 
 	hasVersionCode := false
 	hasVersionName := false
@@ -116,21 +117,12 @@
 		assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...)
 	}
 
-	// App manifest file
-	manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
-	manifestPath = android.PathForModuleSrc(ctx, manifestFile)
 	linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
 	linkDeps = append(linkDeps, manifestPath)
 
 	linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
 	linkDeps = append(linkDeps, assetFiles...)
 
-	transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, sdkContext)
-
-	overlayFiles = append(overlayFiles, transitiveStaticLibs...)
-	linkDeps = append(linkDeps, libDeps...)
-	linkFlags = append(linkFlags, libFlags...)
-
 	// SDK version flags
 	minSdkVersion := sdkVersionOrDefault(ctx, sdkContext.minSdkVersion())
 
@@ -156,7 +148,7 @@
 		linkFlags = append(linkFlags, "--version-name ", versionName)
 	}
 
-	return linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath
+	return linkFlags, linkDeps, resDirs, overlayDirs, rroDirs
 }
 
 func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkContext sdkContext) {
@@ -169,8 +161,18 @@
 }
 
 func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {
-	linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath := a.aapt2Flags(ctx, sdkContext)
+	transitiveStaticLibs, staticLibManifests, libDeps, libFlags := aaptLibs(ctx, sdkContext)
 
+	// App manifest file
+	manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
+	manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
+
+	manifestPath := manifestMerger(ctx, manifestSrcPath, sdkContext, staticLibManifests)
+
+	linkFlags, linkDeps, resDirs, overlayDirs, rroDirs := a.aapt2Flags(ctx, sdkContext, manifestPath)
+
+	linkFlags = append(linkFlags, libFlags...)
+	linkDeps = append(linkDeps, libDeps...)
 	linkFlags = append(linkFlags, extraLinkFlags...)
 
 	packageRes := android.PathForModuleOut(ctx, "package-res.apk")
@@ -188,7 +190,7 @@
 		compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
 	}
 
-	compiledOverlay = append(compiledOverlay, overlayFiles...)
+	compiledOverlay = append(compiledOverlay, transitiveStaticLibs...)
 
 	aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
 		linkFlags, linkDeps, compiledRes, compiledOverlay)
@@ -203,8 +205,8 @@
 }
 
 // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
-func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, deps android.Paths,
-	flags []string) {
+func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, staticLibManifests,
+	deps android.Paths, flags []string) {
 
 	var sharedLibs android.Paths
 
@@ -229,6 +231,7 @@
 			if exportPackage != nil {
 				transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
 				transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
+				staticLibManifests = append(staticLibManifests, aarDep.ExportedManifest())
 			}
 		}
 	})
@@ -246,7 +249,7 @@
 
 	transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
 
-	return transitiveStaticLibs, deps, flags
+	return transitiveStaticLibs, staticLibManifests, deps, flags
 }
 
 type AndroidLibrary struct {
@@ -269,6 +272,10 @@
 	return a.exportedStaticPackages
 }
 
+func (a *AndroidLibrary) ExportedManifest() android.Path {
+	return a.manifestPath
+}
+
 var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
 
 func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -382,6 +389,10 @@
 	return a.exportedStaticPackages
 }
 
+func (a *AARImport) ExportedManifest() android.Path {
+	return a.manifest
+}
+
 func (a *AARImport) Prebuilt() *android.Prebuilt {
 	return &a.prebuilt
 }
@@ -459,7 +470,9 @@
 	linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
 	linkDeps = append(linkDeps, a.manifest)
 
-	transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, sdkContext(a))
+	transitiveStaticLibs, staticLibManifests, libDeps, libFlags := aaptLibs(ctx, sdkContext(a))
+
+	_ = staticLibManifests
 
 	linkDeps = append(linkDeps, libDeps...)
 	linkFlags = append(linkFlags, libFlags...)
diff --git a/java/android_manifest.go b/java/android_manifest.go
new file mode 100644
index 0000000..8fcdcba
--- /dev/null
+++ b/java/android_manifest.go
@@ -0,0 +1,71 @@
+// 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 java
+
+import (
+	"android/soong/java/config"
+
+	"github.com/google/blueprint"
+
+	"android/soong/android"
+)
+
+var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer",
+	blueprint.RuleParams{
+		Command:     `${config.ManifestFixerCmd} --minSdkVersion ${minSdkVersion} $usesLibraries $in $out`,
+		CommandDeps: []string{"${config.ManifestFixerCmd}"},
+	},
+	"minSdkVersion", "usesLibraries")
+
+var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
+	blueprint.RuleParams{
+		Command: `${config.JavaCmd} -classpath ${config.ManifestMergerClasspath} com.android.manifmerger.Merger ` +
+			`--main $in $libs --out $out`,
+		CommandDeps: config.ManifestMergerClasspath,
+	},
+	"libs")
+
+func manifestMerger(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
+	staticLibManifests android.Paths) android.Path {
+
+	// Inject minSdkVersion into the manifest
+	fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   manifestFixerRule,
+		Input:  manifest,
+		Output: fixedManifest,
+		Args: map[string]string{
+			"minSdkVersion": sdkVersionOrDefault(ctx, sdkContext.minSdkVersion()),
+		},
+	})
+	manifest = fixedManifest
+
+	// Merge static aar dependency manifests if necessary
+	if len(staticLibManifests) > 0 {
+		mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml")
+		ctx.Build(pctx, android.BuildParams{
+			Rule:      manifestMergerRule,
+			Input:     manifest,
+			Implicits: staticLibManifests,
+			Output:    mergedManifest,
+			Args: map[string]string{
+				"libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--uses-library "),
+			},
+		})
+		manifest = mergedManifest
+	}
+
+	return manifest
+}
diff --git a/java/app.go b/java/app.go
index a6a06fd..7ad525d 100644
--- a/java/app.go
+++ b/java/app.go
@@ -72,6 +72,10 @@
 	return nil
 }
 
+func (a *AndroidApp) ExportedManifest() android.Path {
+	return a.manifestPath
+}
+
 var _ AndroidLibraryDependency = (*AndroidApp)(nil)
 
 type certificate struct {
diff --git a/java/app_test.go b/java/app_test.go
index 6770119..c7c94ec 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -71,7 +71,10 @@
 
 			foo := ctx.ModuleForTests("foo", "android_common")
 
-			expectedLinkImplicits := []string{"AndroidManifest.xml"}
+			var expectedLinkImplicits []string
+
+			manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
+			expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
 
 			frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
 			expectedLinkImplicits = append(expectedLinkImplicits,
diff --git a/java/config/config.go b/java/config/config.go
index 2fa48cb..ae497a6 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -42,6 +42,16 @@
 		"android.car",
 		"android.car7",
 	}
+
+	ManifestMergerClasspath = []string{
+		"prebuilts/gradle-plugin/com/android/tools/build/manifest-merger/26.1.0/manifest-merger-26.1.0.jar",
+		"prebuilts/gradle-plugin/com/android/tools/common/26.1.0/common-26.1.0.jar",
+		"prebuilts/gradle-plugin/com/android/tools/sdk-common/26.1.0/sdk-common-26.1.0.jar",
+		"prebuilts/gradle-plugin/com/android/tools/sdklib/26.1.0/sdklib-26.1.0.jar",
+		"prebuilts/gradle-plugin/org/jetbrains/kotlin/kotlin-runtime/1.0.5/kotlin-runtime-1.0.5.jar",
+		"prebuilts/gradle-plugin/org/jetbrains/kotlin/kotlin-stdlib/1.1.3/kotlin-stdlib-1.1.3.jar",
+		"prebuilts/misc/common/guava/guava-21.0.jar",
+	}
 )
 
 func init() {
@@ -134,4 +144,7 @@
 	hostBinToolVariableWithPrebuilt("Aapt2Cmd", "prebuilts/sdk/tools", "aapt2")
 
 	pctx.SourcePathVariable("ManifestFixerCmd", "build/soong/scripts/manifest_fixer.py")
+
+	pctx.SourcePathsVariable("ManifestMergerJars", " ", ManifestMergerClasspath...)
+	pctx.SourcePathsVariable("ManifestMergerClasspath", ":", ManifestMergerClasspath...)
 }
diff --git a/java/config/makevars.go b/java/config/makevars.go
index d378877..275f496 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -73,4 +73,8 @@
 	ctx.Strict("EXTRACT_JAR_PACKAGES", "${ExtractJarPackagesCmd}")
 
 	ctx.Strict("MANIFEST_FIXER", "${ManifestFixerCmd}")
+
+	ctx.Strict("ANDROID_MANIFEST_MERGER_DEPS", "${ManifestMergerJars}")
+	ctx.Strict("ANDROID_MANIFEST_MERGER",
+		"${JavaCmd} -classpath ${ManifestMergerClasspath} com.android.manifmerger.Merger")
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e4cfd41..e65af65 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -46,6 +46,7 @@
 	publicApiStubsTag = dependencyTag{name: "public"}
 	systemApiStubsTag = dependencyTag{name: "system"}
 	testApiStubsTag   = dependencyTag{name: "test"}
+	implLibTag        = dependencyTag{name: "platform"}
 )
 
 type apiScope int
@@ -127,6 +128,7 @@
 	publicApiStubsPath android.Paths
 	systemApiStubsPath android.Paths
 	testApiStubsPath   android.Paths
+	implLibPath        android.Paths
 }
 
 func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -134,24 +136,27 @@
 	ctx.AddDependency(ctx.Module(), publicApiStubsTag, module.stubsName(apiScopePublic))
 	ctx.AddDependency(ctx.Module(), systemApiStubsTag, module.stubsName(apiScopeSystem))
 	ctx.AddDependency(ctx.Module(), testApiStubsTag, module.stubsName(apiScopeTest))
+	ctx.AddDependency(ctx.Module(), implLibTag, module.implName())
 }
 
 func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// Record the paths to the header jars of the stubs library.
+	// Record the paths to the header jars of the library (stubs and impl).
 	// When this java_sdk_library is dependened from others via "libs" property,
 	// the recorded paths will be returned depending on the link type of the caller.
 	ctx.VisitDirectDeps(func(to android.Module) {
 		otherName := ctx.OtherModuleName(to)
 		tag := ctx.OtherModuleDependencyTag(to)
 
-		if stubs, ok := to.(Dependency); ok {
+		if lib, ok := to.(Dependency); ok {
 			switch tag {
 			case publicApiStubsTag:
-				module.publicApiStubsPath = stubs.HeaderJars()
+				module.publicApiStubsPath = lib.HeaderJars()
 			case systemApiStubsTag:
-				module.systemApiStubsPath = stubs.HeaderJars()
+				module.systemApiStubsPath = lib.HeaderJars()
 			case testApiStubsTag:
-				module.testApiStubsPath = stubs.HeaderJars()
+				module.testApiStubsPath = lib.HeaderJars()
+			case implLibTag:
+				module.implLibPath = lib.HeaderJars()
 			default:
 				ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
 			}
@@ -543,8 +548,10 @@
 // to satisfy SdkLibraryDependency interface
 func (module *sdkLibrary) HeaderJars(linkType linkType) android.Paths {
 	// This module is just a wrapper for the stubs.
-	if linkType == javaSystem || linkType == javaPlatform {
+	if linkType == javaSystem {
 		return module.systemApiStubsPath
+	} else if linkType == javaPlatform {
+		return module.implLibPath
 	} else {
 		return module.publicApiStubsPath
 	}
diff --git a/phony/phony.go b/phony/phony.go
index a39b5d5..0c62e8a 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -23,7 +23,7 @@
 )
 
 func init() {
-	android.RegisterModuleType("phony", phonyFactory)
+	android.RegisterModuleType("phony", PhonyFactory)
 }
 
 type phony struct {
@@ -31,7 +31,7 @@
 	requiredModuleNames []string
 }
 
-func phonyFactory() android.Module {
+func PhonyFactory() android.Module {
 	module := &phony{}
 
 	android.InitAndroidModule(module)
diff --git a/ui/build/config.go b/ui/build/config.go
index d0378ec..1f7656e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -118,6 +118,18 @@
 
 		// Set in envsetup.sh, reset in makefiles
 		"ANDROID_JAVA_TOOLCHAIN",
+
+		// Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
+		"ANDROID_BUILD_TOP",
+		"ANDROID_HOST_OUT",
+		"ANDROID_PRODUCT_OUT",
+		"ANDROID_HOST_OUT_TESTCASES",
+		"ANDROID_TARGET_OUT_TESTCASES",
+		"ANDROID_TOOLCHAIN",
+		"ANDROID_TOOLCHAIN_2ND_ARCH",
+		"ANDROID_DEV_SCRIPTS",
+		"ANDROID_EMULATOR_PREBUILTS",
+		"ANDROID_PRE_BUILD_PATHS",
 	)
 
 	// Tell python not to spam the source tree with .pyc files.