Merge "Have genrule use $genDir as sbox's --output-root"
diff --git a/android/androidmk.go b/android/androidmk.go
index 2cae1c3..19d5ea6 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -25,7 +25,6 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -77,7 +76,7 @@
 
 	sort.Sort(AndroidModulesByName{androidMkModulesList, ctx})
 
-	transMk := PathForOutput(ctx, "Android"+proptools.String(config.ProductVariables.Make_suffix)+".mk")
+	transMk := PathForOutput(ctx, "Android"+String(config.ProductVariables.Make_suffix)+".mk")
 	if ctx.Failed() {
 		return
 	}
diff --git a/android/module.go b/android/module.go
index b8c9ab2..2a8837b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -152,7 +152,7 @@
 
 type nameProperties struct {
 	// The name of the module.  Must be unique across all modules.
-	Name string
+	Name *string
 }
 
 type commonProperties struct {
@@ -351,12 +351,12 @@
 // Name returns the name of the module.  It may be overridden by individual module types, for
 // example prebuilts will prepend prebuilt_ to the name.
 func (a *ModuleBase) Name() string {
-	return a.nameProperties.Name
+	return String(a.nameProperties.Name)
 }
 
 // BaseModuleName returns the name of the module as specified in the blueprints file.
 func (a *ModuleBase) BaseModuleName() string {
-	return a.nameProperties.Name
+	return String(a.nameProperties.Name)
 }
 
 func (a *ModuleBase) base() *ModuleBase {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index f29f865..d3f9704 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -32,7 +32,7 @@
 type PrebuiltProperties struct {
 	// When prefer is set to true the prebuilt will be used instead of any source module with
 	// a matching name.
-	Prefer bool `android:"arch_variant"`
+	Prefer *bool `android:"arch_variant"`
 
 	SourceExists bool `blueprint:"mutated"`
 	UsePrebuilt  bool `blueprint:"mutated"`
@@ -146,7 +146,7 @@
 	}
 
 	// TODO: use p.Properties.Name and ctx.ModuleDir to override preference
-	if p.properties.Prefer {
+	if Bool(p.properties.Prefer) {
 		return true
 	}
 
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 194faab..065d0aa 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -64,8 +64,9 @@
 				if len(c.Properties.AndroidMkSharedLibs) > 0 {
 					fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(c.Properties.AndroidMkSharedLibs, " "))
 				}
-				if c.Target().Os == android.Android && c.Properties.Sdk_version != "" && !c.useVndk() {
-					fmt.Fprintln(w, "LOCAL_SDK_VERSION := "+c.Properties.Sdk_version)
+				if c.Target().Os == android.Android &&
+					String(c.Properties.Sdk_version) != "" && !c.useVndk() {
+					fmt.Fprintln(w, "LOCAL_SDK_VERSION := "+String(c.Properties.Sdk_version))
 					fmt.Fprintln(w, "LOCAL_NDK_STL_VARIANT := none")
 				} else {
 					// These are already included in LOCAL_SHARED_LIBRARIES
@@ -244,7 +245,7 @@
 	ctx.subAndroidMk(ret, test.binaryDecorator)
 	ret.Class = "NATIVE_TESTS"
 	if Bool(test.Properties.Test_per_src) {
-		ret.SubName = "_" + test.binaryDecorator.Properties.Stem
+		ret.SubName = "_" + String(test.binaryDecorator.Properties.Stem)
 	}
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
@@ -276,9 +277,10 @@
 	}
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
-		if stripper.StripProperties.Strip.None {
+		if Bool(stripper.StripProperties.Strip.None) {
+
 			fmt.Fprintln(w, "LOCAL_STRIP_MODULE := false")
-		} else if stripper.StripProperties.Strip.Keep_symbols {
+		} else if Bool(stripper.StripProperties.Strip.Keep_symbols) {
 			fmt.Fprintln(w, "LOCAL_STRIP_MODULE := keep_symbols")
 		} else {
 			fmt.Fprintln(w, "LOCAL_STRIP_MODULE := mini-debug-info")
diff --git a/cc/binary.go b/cc/binary.go
index 30e017f..5f81866 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -15,8 +15,6 @@
 package cc
 
 import (
-	"github.com/google/blueprint/proptools"
-
 	"android/soong/android"
 )
 
@@ -25,19 +23,19 @@
 	Static_executable *bool `android:"arch_variant"`
 
 	// set the name of the output
-	Stem string `android:"arch_variant"`
+	Stem *string `android:"arch_variant"`
 
 	// append to the name of the output
-	Suffix string `android:"arch_variant"`
+	Suffix *string `android:"arch_variant"`
 
 	// if set, add an extra objcopy --prefix-symbols= step
-	Prefix_symbols string
+	Prefix_symbols *string
 
 	// local file name to pass to the linker as --version_script
 	Version_script *string `android:"arch_variant"`
 
 	// if set, install a symlink to the preferred architecture
-	Symlink_preferred_arch bool
+	Symlink_preferred_arch *bool
 
 	// install symlinks to the binary.  Symlink names will have the suffix and the binary
 	// extension (if any) appended
@@ -97,11 +95,11 @@
 
 func (binary *binaryDecorator) getStem(ctx BaseModuleContext) string {
 	stem := ctx.baseModuleName()
-	if binary.Properties.Stem != "" {
-		stem = binary.Properties.Stem
+	if String(binary.Properties.Stem) != "" {
+		stem = String(binary.Properties.Stem)
 	}
 
-	return stem + binary.Properties.Suffix
+	return stem + String(binary.Properties.Suffix)
 }
 
 func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
@@ -185,7 +183,7 @@
 	if !ctx.toolchain().Bionic() {
 		if ctx.Os() == android.Linux {
 			if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) {
-				binary.Properties.Static_executable = proptools.BoolPtr(true)
+				binary.Properties.Static_executable = BoolPtr(true)
 			}
 		} else {
 			// Static executables are not supported on Darwin or Windows
@@ -315,10 +313,10 @@
 		binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
 	}
 
-	if binary.Properties.Prefix_symbols != "" {
+	if String(binary.Properties.Prefix_symbols) != "" {
 		afterPrefixSymbols := outputFile
 		outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
-		TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
+		TransformBinaryPrefixSymbols(ctx, String(binary.Properties.Prefix_symbols), outputFile,
 			flagsToBuilderFlags(flags), afterPrefixSymbols)
 	}
 
@@ -342,11 +340,11 @@
 	binary.baseInstaller.install(ctx, file)
 	for _, symlink := range binary.Properties.Symlinks {
 		binary.symlinks = append(binary.symlinks,
-			symlink+binary.Properties.Suffix+ctx.toolchain().ExecutableSuffix())
+			symlink+String(binary.Properties.Suffix)+ctx.toolchain().ExecutableSuffix())
 	}
 
-	if binary.Properties.Symlink_preferred_arch {
-		if binary.Properties.Stem == "" && binary.Properties.Suffix == "" {
+	if Bool(binary.Properties.Symlink_preferred_arch) {
+		if String(binary.Properties.Stem) == "" && String(binary.Properties.Suffix) == "" {
 			ctx.PropertyErrorf("symlink_preferred_arch", "must also specify stem or suffix")
 		}
 		if ctx.TargetPrimary() {
diff --git a/cc/cc.go b/cc/cc.go
index 60c8f41..86a60c9 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -148,7 +148,7 @@
 	Objs []string `android:"arch_variant"`
 
 	// if set, add an extra objcopy --prefix-symbols= step
-	Prefix_symbols string
+	Prefix_symbols *string
 }
 
 // Properties used to compile all C or C++ modules
@@ -157,7 +157,7 @@
 	Clang *bool `android:"arch_variant"`
 
 	// Minimum sdk version supported when compiling against the ndk
-	Sdk_version string
+	Sdk_version *string
 
 	AndroidMkSharedLibs []string `blueprint:"mutated"`
 	HideFromMake        bool     `blueprint:"mutated"`
@@ -449,7 +449,7 @@
 
 func (ctx *moduleContextImpl) useSdk() bool {
 	if ctx.ctx.Device() && !ctx.useVndk() {
-		return ctx.mod.Properties.Sdk_version != ""
+		return String(ctx.mod.Properties.Sdk_version) != ""
 	}
 	return false
 }
@@ -459,7 +459,7 @@
 		if ctx.useVndk() {
 			return "current"
 		} else {
-			return ctx.mod.Properties.Sdk_version
+			return String(ctx.mod.Properties.Sdk_version)
 		}
 	}
 	return ""
@@ -711,7 +711,7 @@
 		if err != nil {
 			ctx.PropertyErrorf("sdk_version", err.Error())
 		}
-		c.Properties.Sdk_version = version
+		c.Properties.Sdk_version = StringPtr(version)
 	}
 }
 
@@ -960,7 +960,7 @@
 		}
 		return
 	}
-	if from.Properties.Sdk_version == "" {
+	if String(from.Properties.Sdk_version) == "" {
 		// Platform code can link to anything
 		return
 	}
@@ -981,7 +981,7 @@
 		// the NDK.
 		return
 	}
-	if to.Properties.Sdk_version == "" {
+	if String(to.Properties.Sdk_version) == "" {
 		// NDK code linking to platform code is never okay.
 		ctx.ModuleErrorf("depends on non-NDK-built library %q",
 			ctx.OtherModuleName(to))
@@ -992,31 +992,31 @@
 	// API level, as it is only valid to link against older or equivalent
 	// APIs.
 
-	if from.Properties.Sdk_version == "current" {
+	if String(from.Properties.Sdk_version) == "current" {
 		// Current can link against anything.
 		return
-	} else if to.Properties.Sdk_version == "current" {
+	} else if String(to.Properties.Sdk_version) == "current" {
 		// Current can't be linked against by anything else.
 		ctx.ModuleErrorf("links %q built against newer API version %q",
 			ctx.OtherModuleName(to), "current")
 	}
 
-	fromApi, err := strconv.Atoi(from.Properties.Sdk_version)
+	fromApi, err := strconv.Atoi(String(from.Properties.Sdk_version))
 	if err != nil {
 		ctx.PropertyErrorf("sdk_version",
 			"Invalid sdk_version value (must be int): %q",
-			from.Properties.Sdk_version)
+			String(from.Properties.Sdk_version))
 	}
-	toApi, err := strconv.Atoi(to.Properties.Sdk_version)
+	toApi, err := strconv.Atoi(String(to.Properties.Sdk_version))
 	if err != nil {
 		ctx.PropertyErrorf("sdk_version",
 			"Invalid sdk_version value (must be int): %q",
-			to.Properties.Sdk_version)
+			String(to.Properties.Sdk_version))
 	}
 
 	if toApi > fromApi {
 		ctx.ModuleErrorf("links %q built against newer API version %q",
-			ctx.OtherModuleName(to), to.Properties.Sdk_version)
+			ctx.OtherModuleName(to), String(to.Properties.Sdk_version))
 	}
 }
 
@@ -1410,7 +1410,7 @@
 		vendor := mod[1].(*Module)
 		vendor.Properties.UseVndk = true
 		squashVendorSrcs(vendor)
-	} else if mctx.InstallOnVendorPartition() && m.Properties.Sdk_version == "" {
+	} else if mctx.InstallOnVendorPartition() && String(m.Properties.Sdk_version) == "" {
 		// This will be available in /vendor only
 		mod := mctx.CreateVariations(vendorMode)
 		vendor := mod[0].(*Module)
@@ -1432,3 +1432,6 @@
 }
 
 var Bool = proptools.Bool
+var BoolPtr = proptools.BoolPtr
+var String = proptools.String
+var StringPtr = proptools.StringPtr
diff --git a/cc/cc_test.go b/cc/cc_test.go
index b7c2395..14b4245 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -9,8 +9,6 @@
 	"sort"
 	"strings"
 	"testing"
-
-	"github.com/google/blueprint/proptools"
 )
 
 var buildDir string
@@ -40,7 +38,7 @@
 
 func testCc(t *testing.T, bp string) *android.TestContext {
 	config := android.TestArchConfig(buildDir, nil)
-	config.ProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
+	config.ProductVariables.DeviceVndkVersion = StringPtr("current")
 
 	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
diff --git a/cc/compiler.go b/cc/compiler.go
index c40e179..268a663 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -89,12 +89,12 @@
 	// C standard version to use. Can be a specific version (such as "gnu11"),
 	// "experimental" (which will use draft versions like C1x when available),
 	// or the empty string (which will use the default).
-	C_std string
+	C_std *string
 
 	// C++ standard version to use. Can be a specific version (such as
 	// "gnu++11"), "experimental" (which will use draft versions like C++1z when
 	// available), or the empty string (which will use the default).
-	Cpp_std string
+	Cpp_std *string
 
 	// if set to false, use -std=c++* instead of -std=gnu++*
 	Gnu_extensions *bool
@@ -143,7 +143,7 @@
 
 	Proto struct {
 		// Link statically against the protobuf runtime
-		Static bool `android:"arch_variant"`
+		Static *bool `android:"arch_variant"`
 	} `android:"arch_variant"`
 
 	// Stores the original list of source files before being cleared by library reuse
@@ -193,7 +193,7 @@
 	android.ExtractSourcesDeps(ctx, compiler.Properties.Srcs)
 
 	if compiler.hasSrcExt(".proto") {
-		deps = protoDeps(ctx, deps, &compiler.Proto, compiler.Properties.Proto.Static)
+		deps = protoDeps(ctx, deps, &compiler.Proto, Bool(compiler.Properties.Proto.Static))
 	}
 
 	return deps
@@ -275,7 +275,7 @@
 			"-D__ANDROID_API__=__ANDROID_API_FUTURE__", "-D__ANDROID_VNDK__")
 	}
 
-	instructionSet := proptools.String(compiler.Properties.Instruction_set)
+	instructionSet := String(compiler.Properties.Instruction_set)
 	if flags.RequiredInstructionSet != "" {
 		instructionSet = flags.RequiredInstructionSet
 	}
@@ -364,21 +364,21 @@
 
 	if !ctx.useSdk() {
 		cStd := config.CStdVersion
-		if compiler.Properties.C_std == "experimental" {
+		if String(compiler.Properties.C_std) == "experimental" {
 			cStd = config.ExperimentalCStdVersion
-		} else if compiler.Properties.C_std != "" {
-			cStd = compiler.Properties.C_std
+		} else if String(compiler.Properties.C_std) != "" {
+			cStd = String(compiler.Properties.C_std)
 		}
 
-		cppStd := compiler.Properties.Cpp_std
-		switch compiler.Properties.Cpp_std {
+		cppStd := String(compiler.Properties.Cpp_std)
+		switch String(compiler.Properties.Cpp_std) {
 		case "":
 			cppStd = config.CppStdVersion
 		case "experimental":
 			cppStd = config.ExperimentalCppStdVersion
 		case "c++17", "gnu++17":
 			// Map c++17 and gnu++17 to their 1z equivalents, until 17 is finalized.
-			cppStd = strings.Replace(compiler.Properties.Cpp_std, "17", "1z", 1)
+			cppStd = strings.Replace(String(compiler.Properties.Cpp_std), "17", "1z", 1)
 		}
 
 		if !flags.Clang {
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 2c439f0..6703969 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -77,6 +77,7 @@
 			"-mfpu=vfpv3-d16",
 		},
 		"armv7-a-neon": []string{
+			"-march=armv7-a",
 			"-mfloat-abi=softfp",
 			"-mfpu=neon",
 		},
@@ -88,9 +89,6 @@
 	}
 
 	armCpuVariantCflags = map[string][]string{
-		"": []string{
-			"-march=armv7-a",
-		},
 		"cortex-a7": []string{
 			"-mcpu=cortex-a7",
 			"-mfpu=neon-vfpv4",
diff --git a/cc/installer.go b/cc/installer.go
index 92076e5..33f29f2 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -24,7 +24,7 @@
 
 type InstallerProperties struct {
 	// install to a subdirectory of the default install path for the module
-	Relative_install_path string `android:"arch_variant"`
+	Relative_install_path *string `android:"arch_variant"`
 }
 
 type installLocation int
@@ -72,7 +72,8 @@
 	if installer.location == InstallInData && ctx.useVndk() {
 		dir = filepath.Join(dir, "vendor")
 	}
-	return android.PathForModuleInstall(ctx, dir, installer.subDir, installer.Properties.Relative_install_path, installer.relative)
+	return android.PathForModuleInstall(ctx, dir, installer.subDir,
+		String(installer.Properties.Relative_install_path), installer.relative)
 }
 
 func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
diff --git a/cc/library.go b/cc/library.go
index 5aac04b..d4ed7c6 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -57,12 +57,12 @@
 
 	Aidl struct {
 		// export headers generated from .aidl sources
-		Export_aidl_headers bool
+		Export_aidl_headers *bool
 	}
 
 	Proto struct {
 		// export headers generated from .proto sources
-		Export_proto_headers bool
+		Export_proto_headers *bool
 	}
 	Target struct {
 		Vendor struct {
@@ -71,7 +71,7 @@
 		}
 	}
 
-	Static_ndk_lib bool
+	Static_ndk_lib *bool
 }
 
 type LibraryMutatedProperties struct {
@@ -663,7 +663,7 @@
 	library.reexportFlags(deps.ReexportedFlags)
 	library.reexportDeps(deps.ReexportedFlagsDeps)
 
-	if library.Properties.Aidl.Export_aidl_headers {
+	if Bool(library.Properties.Aidl.Export_aidl_headers) {
 		if library.baseCompiler.hasSrcExt(".aidl") {
 			flags := []string{
 				"-I" + android.PathForModuleGen(ctx, "aidl").String(),
@@ -675,7 +675,7 @@
 		}
 	}
 
-	if library.Properties.Proto.Export_proto_headers {
+	if Bool(library.Properties.Proto.Export_proto_headers) {
 		if library.baseCompiler.hasSrcExt(".proto") {
 			flags := []string{
 				"-I" + android.ProtoSubDir(ctx).String(),
@@ -731,7 +731,7 @@
 		library.baseInstaller.install(ctx, file)
 	}
 
-	if library.Properties.Static_ndk_lib && library.static() {
+	if Bool(library.Properties.Static_ndk_lib) && library.static() {
 		installPath := getNdkSysrootBase(ctx).Join(
 			ctx, "usr/lib", ctx.toolchain().ClangTriple(), file.Base())
 
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index de0caa5..40373cc 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -39,23 +39,23 @@
 type llndkLibraryProperties struct {
 	// Relative path to the symbol map.
 	// An example file can be seen here: TODO(danalbert): Make an example.
-	Symbol_file string
+	Symbol_file *string
 
 	// Whether to export any headers as -isystem instead of -I. Mainly for use by
 	// bionic/libc.
-	Export_headers_as_system bool
+	Export_headers_as_system *bool
 
 	// Which headers to process with versioner. This really only handles
 	// bionic/libc/include right now.
 	Export_preprocessed_headers []string
 
 	// Whether the system library uses symbol versions.
-	Unversioned bool
+	Unversioned *bool
 
 	// whether this module can be directly depended upon by libs that are installed to /vendor.
 	// When set to false, this module can only be depended on by VNDK libraries, not vendor
 	// libraries. This effectively hides this module from vendors. Default value is true.
-	Vendor_available bool
+	Vendor_available *bool
 
 	// list of llndk headers to re-export include directories from.
 	Export_llndk_headers []string `android:"arch_variant"`
@@ -76,7 +76,7 @@
 }
 
 func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
-	objs, versionScript := compileStubLibrary(ctx, flags, stub.Properties.Symbol_file, "current", "--vndk")
+	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), "current", "--vndk")
 	stub.versionScriptPath = versionScript
 	return objs
 }
@@ -121,7 +121,7 @@
 func (stub *llndkStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
 	objs Objects) android.Path {
 
-	if !stub.Properties.Unversioned {
+	if !Bool(stub.Properties.Unversioned) {
 		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
 		flags.LdFlags = append(flags.LdFlags, linkerScriptFlag)
 	}
@@ -135,7 +135,7 @@
 		}
 
 		includePrefix := "-I "
-		if stub.Properties.Export_headers_as_system {
+		if Bool(stub.Properties.Export_headers_as_system) {
 			includePrefix = "-isystem "
 		}
 
@@ -143,7 +143,7 @@
 		stub.reexportDeps(timestampFiles)
 	}
 
-	if stub.Properties.Export_headers_as_system {
+	if Bool(stub.Properties.Export_headers_as_system) {
 		stub.exportIncludes(ctx, "-isystem")
 		stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
 	}
@@ -156,12 +156,12 @@
 	library.BuildOnlyShared()
 	module.stl = nil
 	module.sanitize = nil
-	library.StripProperties.Strip.None = true
+	library.StripProperties.Strip.None = BoolPtr(true)
 
 	stub := &llndkStubDecorator{
 		libraryDecorator: library,
 	}
-	stub.Properties.Vendor_available = true
+	stub.Properties.Vendor_available = BoolPtr(true)
 	module.compiler = stub
 	module.linker = stub
 	module.installer = nil
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 1f8c3de..8f1ecbd 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -56,16 +56,16 @@
 	//
 	// Will install $SYSROOT/usr/include/foo/bar/baz.h. If `from` were instead
 	// "include/foo", it would have installed $SYSROOT/usr/include/bar/baz.h.
-	From string
+	From *string
 
 	// Install path within the sysroot. This is relative to usr/include.
-	To string
+	To *string
 
 	// List of headers to install. Glob compatible. Common case is "include/**/*.h".
 	Srcs []string
 
 	// Path to the NOTICE file associated with the headers.
-	License string
+	License *string
 }
 
 type headerModule struct {
@@ -113,15 +113,16 @@
 }
 
 func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	if m.properties.License == "" {
+	if String(m.properties.License) == "" {
 		ctx.PropertyErrorf("license", "field is required")
 	}
 
-	m.licensePath = android.PathForModuleSrc(ctx, m.properties.License)
+	m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
 
 	srcFiles := ctx.ExpandSources(m.properties.Srcs, nil)
 	for _, header := range srcFiles {
-		installDir := getHeaderInstallDir(ctx, header, m.properties.From, m.properties.To)
+		installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
+			String(m.properties.To))
 		installedPath := ctx.InstallFile(installDir, header.Base(), header)
 		installPath := installDir.Join(ctx, header.Base())
 		if installPath != installedPath {
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 9d96f02..066fb98 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -76,17 +76,17 @@
 type libraryProperties struct {
 	// Relative path to the symbol map.
 	// An example file can be seen here: TODO(danalbert): Make an example.
-	Symbol_file string
+	Symbol_file *string
 
 	// The first API level a library was available. A library will be generated
 	// for every API level beginning with this one.
-	First_version string
+	First_version *string
 
 	// The first API level that library should have the version script applied.
 	// This defaults to the value of first_version, and should almost never be
 	// used. This is only needed to work around platform bugs like
 	// https://github.com/android-ndk/ndk/issues/265.
-	Unversioned_until string
+	Unversioned_until *string
 
 	// Private property for use by the mutator that splits per-API level.
 	ApiLevel string `blueprint:"mutated"`
@@ -158,11 +158,11 @@
 
 func shouldUseVersionScript(stub *stubDecorator) (bool, error) {
 	// unversioned_until is normally empty, in which case we should use the version script.
-	if stub.properties.Unversioned_until == "" {
+	if String(stub.properties.Unversioned_until) == "" {
 		return true, nil
 	}
 
-	if stub.properties.Unversioned_until == "current" {
+	if String(stub.properties.Unversioned_until) == "current" {
 		if stub.properties.ApiLevel == "current" {
 			return true, nil
 		} else {
@@ -174,7 +174,7 @@
 		return true, nil
 	}
 
-	unversionedUntil, err := strconv.Atoi(stub.properties.Unversioned_until)
+	unversionedUntil, err := strconv.Atoi(String(stub.properties.Unversioned_until))
 	if err != nil {
 		return true, err
 	}
@@ -190,7 +190,7 @@
 func generateStubApiVariants(mctx android.BottomUpMutatorContext, c *stubDecorator) {
 	platformVersion := mctx.AConfig().PlatformSdkVersionInt()
 
-	firstSupportedVersion, err := normalizeNdkApiLevel(mctx, c.properties.First_version,
+	firstSupportedVersion, err := normalizeNdkApiLevel(mctx, String(c.properties.First_version),
 		mctx.Arch())
 	if err != nil {
 		mctx.PropertyErrorf("first_version", err.Error())
@@ -290,11 +290,12 @@
 }
 
 func (c *stubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
-	if !strings.HasSuffix(c.properties.Symbol_file, ".map.txt") {
+	if !strings.HasSuffix(String(c.properties.Symbol_file), ".map.txt") {
 		ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
 	}
 
-	objs, versionScript := compileStubLibrary(ctx, flags, c.properties.Symbol_file, c.properties.ApiLevel, "")
+	objs, versionScript := compileStubLibrary(ctx, flags, String(c.properties.Symbol_file),
+		c.properties.ApiLevel, "")
 	c.versionScriptPath = versionScript
 	return objs
 }
@@ -349,7 +350,7 @@
 	library.BuildOnlyShared()
 	module.stl = nil
 	module.sanitize = nil
-	library.StripProperties.Strip.None = true
+	library.StripProperties.Strip.None = BoolPtr(true)
 
 	stub := &stubDecorator{
 		libraryDecorator: library,
diff --git a/cc/object.go b/cc/object.go
index 2246dd3..d0f4f20 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -83,9 +83,9 @@
 	if len(objs.objFiles) == 1 {
 		outputFile = objs.objFiles[0]
 
-		if object.Properties.Prefix_symbols != "" {
+		if String(object.Properties.Prefix_symbols) != "" {
 			output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
-			TransformBinaryPrefixSymbols(ctx, object.Properties.Prefix_symbols, outputFile,
+			TransformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), outputFile,
 				builderFlags, output)
 			outputFile = output
 		}
@@ -93,9 +93,9 @@
 		output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
 		outputFile = output
 
-		if object.Properties.Prefix_symbols != "" {
+		if String(object.Properties.Prefix_symbols) != "" {
 			input := android.PathForModuleOut(ctx, "unprefixed", ctx.ModuleName()+objectExtension)
-			TransformBinaryPrefixSymbols(ctx, object.Properties.Prefix_symbols, input,
+			TransformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
 				builderFlags, output)
 			output = input
 		}
diff --git a/cc/proto.go b/cc/proto.go
index a235398..e7f1d41 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -16,7 +16,6 @@
 
 import (
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 )
@@ -58,7 +57,7 @@
 func protoDeps(ctx BaseModuleContext, deps Deps, p *android.ProtoProperties, static bool) Deps {
 	var lib string
 
-	switch proptools.String(p.Proto.Type) {
+	switch String(p.Proto.Type) {
 	case "full":
 		if ctx.useSdk() {
 			lib = "libprotobuf-cpp-full-ndk"
@@ -75,7 +74,7 @@
 		}
 	default:
 		ctx.PropertyErrorf("proto.type", "unknown proto type %q",
-			proptools.String(p.Proto.Type))
+			String(p.Proto.Type))
 	}
 
 	if static {
diff --git a/cc/rs.go b/cc/rs.go
index 0e411aa..c2335dd 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -19,7 +19,6 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -81,7 +80,7 @@
 }
 
 func rsFlags(ctx ModuleContext, flags Flags, properties *BaseCompilerProperties) Flags {
-	targetApi := proptools.String(properties.Renderscript.Target_api)
+	targetApi := String(properties.Renderscript.Target_api)
 	if targetApi == "" && ctx.useSdk() {
 		switch ctx.sdkVersion() {
 		case "current", "system_current", "test_current":
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 5d7f617..aeaaf16 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -78,7 +78,7 @@
 type SanitizeProperties struct {
 	// enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
 	Sanitize struct {
-		Never bool `android:"arch_variant"`
+		Never *bool `android:"arch_variant"`
 
 		// main sanitizers
 		Address *bool `android:"arch_variant"`
@@ -131,11 +131,11 @@
 
 	// Don't apply sanitizers to NDK code.
 	if ctx.useSdk() {
-		s.Never = true
+		s.Never = BoolPtr(true)
 	}
 
 	// Never always wins.
-	if s.Never {
+	if Bool(s.Never) {
 		return
 	}
 
@@ -540,7 +540,7 @@
 		if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
 			mctx.VisitDepsDepthFirst(func(module android.Module) {
 				if d, ok := module.(*Module); ok && d.sanitize != nil &&
-					!d.sanitize.Properties.Sanitize.Never &&
+					!Bool(d.sanitize.Properties.Sanitize.Never) &&
 					!d.sanitize.isSanitizerExplicitlyDisabled(t) {
 					if (t == cfi && d.static()) || t != cfi {
 						d.sanitize.Properties.SanitizeDep = true
diff --git a/cc/strip.go b/cc/strip.go
index bc16bbc..0bb29c1 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -14,12 +14,14 @@
 
 package cc
 
-import "android/soong/android"
+import (
+	"android/soong/android"
+)
 
 type StripProperties struct {
 	Strip struct {
-		None         bool
-		Keep_symbols bool
+		None         *bool
+		Keep_symbols *bool
 	}
 }
 
@@ -28,7 +30,7 @@
 }
 
 func (stripper *stripper) needsStrip(ctx ModuleContext) bool {
-	return !ctx.AConfig().EmbeddedInMake() && !stripper.StripProperties.Strip.None
+	return !ctx.AConfig().EmbeddedInMake() && !Bool(stripper.StripProperties.Strip.None)
 }
 
 func (stripper *stripper) strip(ctx ModuleContext, in, out android.ModuleOutPath,
@@ -36,7 +38,7 @@
 	if ctx.Darwin() {
 		TransformDarwinStrip(ctx, in, out)
 	} else {
-		flags.stripKeepSymbols = stripper.StripProperties.Strip.Keep_symbols
+		flags.stripKeepSymbols = Bool(stripper.StripProperties.Strip.Keep_symbols)
 		// TODO(ccross): don't add gnu debuglink for user builds
 		flags.stripAddGnuDebuglink = true
 		TransformStrip(ctx, in, out, flags)
diff --git a/cc/test.go b/cc/test.go
index 53c984a..7b9dcb9 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -100,7 +100,7 @@
 
 func (test *testBinary) setSrc(name, src string) {
 	test.baseCompiler.Properties.Srcs = []string{src}
-	test.binaryDecorator.Properties.Stem = name
+	test.binaryDecorator.Properties.Stem = StringPtr(name)
 }
 
 var _ testPerSrc = (*testBinary)(nil)
@@ -236,7 +236,7 @@
 
 	if !Bool(test.Properties.No_named_install_directory) {
 		test.binaryDecorator.baseInstaller.relative = ctx.ModuleName()
-	} else if test.binaryDecorator.baseInstaller.Properties.Relative_install_path == "" {
+	} else if String(test.binaryDecorator.baseInstaller.Properties.Relative_install_path) == "" {
 		ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
 	}
 
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 9b83f18..2bb4018 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -15,8 +15,6 @@
 package cc
 
 import (
-	"github.com/google/blueprint/proptools"
-
 	"android/soong/android"
 )
 
@@ -45,7 +43,7 @@
 	}
 	module.compiler = toolchainLibrary
 	module.linker = toolchainLibrary
-	module.Properties.Clang = proptools.BoolPtr(false)
+	module.Properties.Clang = BoolPtr(false)
 	module.stl = nil
 	module.sanitize = nil
 	module.installer = nil
diff --git a/cc/vndk.go b/cc/vndk.go
index 860678d..03297df 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -85,7 +85,7 @@
 		// Non-VNDK modules (those installed to /vendor) can't depend on modules marked with
 		// vendor_available: false.
 		violation := false
-		if lib, ok := to.linker.(*llndkStubDecorator); ok && !lib.Properties.Vendor_available {
+		if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) {
 			violation = true
 		} else {
 			if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) {
@@ -138,7 +138,7 @@
 				llndkLibraries = append(llndkLibraries, name)
 				sort.Strings(llndkLibraries)
 			}
-			if !lib.Properties.Vendor_available {
+			if !Bool(lib.Properties.Vendor_available) {
 				if !inList(name, vndkPrivateLibraries) {
 					vndkPrivateLibraries = append(vndkPrivateLibraries, name)
 					sort.Strings(vndkPrivateLibraries)
diff --git a/java/config/config.go b/java/config/config.go
index 654d935..d4994a1 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -55,13 +55,8 @@
 	pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
 
 	pctx.VariableFunc("JavaHome", func(config interface{}) (string, error) {
-		if override := config.(android.Config).Getenv("OVERRIDE_ANDROID_JAVA_HOME"); override != "" {
-			return override, nil
-		}
-		if config.(android.Config).UseOpenJDK9() {
-			return "prebuilts/jdk/jdk9/${hostPrebuiltTag}", nil
-		}
-		return "prebuilts/jdk/jdk8/${hostPrebuiltTag}", nil
+		// This is set up and guaranteed by soong_ui
+		return config.(android.Config).Getenv("ANDROID_JAVA_HOME"), nil
 	})
 
 	pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
diff --git a/python/androidmk.go b/python/androidmk.go
index 25abdc9..4c94450 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -48,11 +48,25 @@
 
 func (p *binaryDecorator) AndroidMk(base *Module, ret *android.AndroidMkData) {
 	ret.Class = "EXECUTABLES"
+
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+		if len(p.binaryProperties.Test_suites) > 0 {
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+				strings.Join(p.binaryProperties.Test_suites, " "))
+		}
+	})
 	base.subAndroidMk(ret, p.baseInstaller)
 }
 
 func (p *testDecorator) AndroidMk(base *Module, ret *android.AndroidMkData) {
 	ret.Class = "NATIVE_TESTS"
+
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+		if len(p.binaryDecorator.binaryProperties.Test_suites) > 0 {
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+				strings.Join(p.binaryDecorator.binaryProperties.Test_suites, " "))
+		}
+	})
 	base.subAndroidMk(ret, p.binaryDecorator.baseInstaller)
 }
 
diff --git a/python/binary.go b/python/binary.go
index c2e38bf..95b0606 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -40,6 +40,10 @@
 
 	// append to the name of the output binary.
 	Suffix string `android:"arch_variant"`
+
+	// list of compatibility suites (for example "cts", "vts") that the module should be
+	// installed into.
+	Test_suites []string `android:"arch_variant"`
 }
 
 type binaryDecorator struct {
diff --git a/ui/build/config.go b/ui/build/config.go
index 191a102..940bb2f 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -104,6 +104,9 @@
 		"MAKEFLAGS",
 		"MAKELEVEL",
 		"MFLAGS",
+
+		// Set in envsetup.sh, reset in makefiles
+		"ANDROID_JAVA_TOOLCHAIN",
 	)
 
 	// Tell python not to spam the source tree with .pyc files.
@@ -117,14 +120,12 @@
 		log.Fatalln("Error verifying tree state:", err)
 	}
 
-	if srcDir, err := filepath.Abs("."); err == nil {
-		if strings.ContainsRune(srcDir, ' ') {
-			log.Println("You are building in a directory whose absolute path contains a space character:")
-			log.Println()
-			log.Printf("%q\n", srcDir)
-			log.Println()
-			log.Fatalln("Directory names containing spaces are not supported")
-		}
+	if srcDir := absPath(ctx, "."); strings.ContainsRune(srcDir, ' ') {
+		log.Println("You are building in a directory whose absolute path contains a space character:")
+		log.Println()
+		log.Printf("%q\n", srcDir)
+		log.Println()
+		log.Fatalln("Directory names containing spaces are not supported")
 	}
 
 	if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
@@ -143,6 +144,27 @@
 		log.Fatalln("Directory names containing spaces are not supported")
 	}
 
+	// Configure Java-related variables, including adding it to $PATH
+	javaHome := func() string {
+		if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
+			return override
+		}
+		if v, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK9"); ok && v != "" {
+			return filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
+		}
+		return filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
+	}()
+	absJavaHome := absPath(ctx, javaHome)
+
+	newPath := []string{filepath.Join(absJavaHome, "bin")}
+	if path, ok := ret.environ.Get("PATH"); ok && path != "" {
+		newPath = append(newPath, path)
+	}
+	ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
+	ret.environ.Set("JAVA_HOME", absJavaHome)
+	ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
+	ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
+
 	return Config{ret}
 }
 
diff --git a/ui/build/sandbox_darwin.go b/ui/build/sandbox_darwin.go
index 2cf6e20..7e75167 100644
--- a/ui/build/sandbox_darwin.go
+++ b/ui/build/sandbox_darwin.go
@@ -16,7 +16,6 @@
 
 import (
 	"os/exec"
-	"path/filepath"
 )
 
 type Sandbox string
@@ -50,14 +49,8 @@
 
 func (c *Cmd) wrapSandbox() {
 	homeDir, _ := c.Environment.Get("HOME")
-	outDir, err := filepath.Abs(c.config.OutDir())
-	if err != nil {
-		c.ctx.Fatalln("Failed to get absolute path of OUT_DIR:", err)
-	}
-	distDir, err := filepath.Abs(c.config.DistDir())
-	if err != nil {
-		c.ctx.Fatalln("Failed to get absolute path of DIST_DIR:", err)
-	}
+	outDir := absPath(c.ctx, c.config.OutDir())
+	distDir := absPath(c.ctx, c.config.DistDir())
 
 	c.Args[0] = c.Path
 	c.Path = sandboxExecPath
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 8220597..d3bcf87 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -77,9 +77,7 @@
 		var cfg microfactory.Config
 		cfg.Map("github.com/google/blueprint", "build/blueprint")
 
-		if absPath, err := filepath.Abs("."); err == nil {
-			cfg.TrimPath = absPath
-		}
+		cfg.TrimPath = absPath(ctx, ".")
 
 		minibp := filepath.Join(config.SoongOutDir(), ".minibootstrap/minibp")
 		if _, err := microfactory.Build(&cfg, minibp, "github.com/google/blueprint/bootstrap/minibp"); err != nil {
diff --git a/ui/build/util.go b/ui/build/util.go
index 2555e8a..f698ccd 100644
--- a/ui/build/util.go
+++ b/ui/build/util.go
@@ -24,6 +24,14 @@
 	"unsafe"
 )
 
+func absPath(ctx Context, p string) string {
+	ret, err := filepath.Abs(p)
+	if err != nil {
+		ctx.Fatalf("Failed to get absolute path: %v", err)
+	}
+	return ret
+}
+
 // indexList finds the index of a string in a []string
 func indexList(s string, list []string) int {
 	for i, l := range list {