Merge "soong: use optimal FPU for Cortex-A7"
diff --git a/Android.bp b/Android.bp
index 0e3ac02..2ae993f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -232,6 +232,7 @@
 toolchain_library {
     name: "libatomic",
     defaults: ["linux_bionic_supported"],
+    vendor_available: true,
     arch: {
         arm: {
             instruction_set: "arm",
@@ -242,6 +243,7 @@
 toolchain_library {
     name: "libgcc",
     defaults: ["linux_bionic_supported"],
+    vendor_available: true,
     arch: {
         arm: {
             instruction_set: "arm",
diff --git a/cc/androidmk.go b/cc/androidmk.go
index fa7ce42..59a1db8 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -26,6 +26,7 @@
 type AndroidMkContext interface {
 	Target() android.Target
 	subAndroidMk(*android.AndroidMkData, interface{})
+	vndk() bool
 }
 
 type subAndroidMkProvider interface {
@@ -56,13 +57,16 @@
 		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 != "" {
+		if c.Target().Os == android.Android && c.Properties.Sdk_version != "" && !c.vndk() {
 			fmt.Fprintln(w, "LOCAL_SDK_VERSION := "+c.Properties.Sdk_version)
 			fmt.Fprintln(w, "LOCAL_NDK_STL_VARIANT := none")
 		} else {
 			// These are already included in LOCAL_SHARED_LIBRARIES
 			fmt.Fprintln(w, "LOCAL_CXX_STL := none")
 		}
+		if c.vndk() {
+			fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
+		}
 		return nil
 	})
 
@@ -74,6 +78,10 @@
 	c.subAndroidMk(&ret, c.linker)
 	c.subAndroidMk(&ret, c.installer)
 
+	if c.vndk() {
+		ret.SubName += ".vendor"
+	}
+
 	return ret, nil
 }
 
@@ -118,6 +126,8 @@
 			if host {
 				fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", ctx.Target().Os.String())
 				fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
+			} else if ctx.vndk() {
+				fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
 			}
 
 			library.androidMkWriteExportedFlags(w)
@@ -301,7 +311,7 @@
 
 func (c *llndkStubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ret.Class = "SHARED_LIBRARIES"
-	ret.SubName = llndkLibrarySuffix
+	ret.SubName = ".vendor"
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
 		c.libraryDecorator.androidMkWriteExportedFlags(w)
@@ -311,6 +321,7 @@
 		fmt.Fprintln(w, "LOCAL_SYSTEM_SHARED_LIBRARIES :=")
 		fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
 		fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
+		fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
 
 		return nil
 	})
diff --git a/cc/binary.go b/cc/binary.go
index 2578311..b4610ed 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -108,7 +108,7 @@
 	deps = binary.baseLinker.linkerDeps(ctx, deps)
 	if ctx.toolchain().Bionic() {
 		if !Bool(binary.baseLinker.Properties.Nocrt) {
-			if !ctx.sdk() && !ctx.vndk() {
+			if !ctx.sdk() {
 				if binary.static() {
 					deps.CrtBegin = "crtbegin_static"
 				} else {
diff --git a/cc/cc.go b/cc/cc.go
index ae203a3..63caf3a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -35,6 +35,7 @@
 
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("link", linkageMutator).Parallel()
+		ctx.BottomUp("image", vendorMutator).Parallel()
 		ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
 		ctx.BottomUp("begin", beginMutator).Parallel()
@@ -143,9 +144,24 @@
 	// cppflags, conlyflags, ldflags, or include_dirs
 	No_default_compiler_flags *bool
 
+	// whether this module should be allowed to install onto /vendor as
+	// well as /system. The two variants will be built separately, one
+	// like normal, and the other limited to the set of libraries and
+	// headers that are exposed to /vendor modules.
+	//
+	// The vendor variant may be used with a different (newer) /system,
+	// so it shouldn't have any unversioned runtime dependencies, or
+	// make assumptions about the system that may not be true in the
+	// future.
+	//
+	// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
+	Vendor_available *bool
+
 	AndroidMkSharedLibs []string `blueprint:"mutated"`
 	HideFromMake        bool     `blueprint:"mutated"`
 	PreventInstall      bool     `blueprint:"mutated"`
+
+	UseVndk bool `blueprint:"mutated"`
 }
 
 type UnusedProperties struct {
@@ -320,6 +336,10 @@
 	return false
 }
 
+func (c *Module) vndk() bool {
+	return c.Properties.UseVndk
+}
+
 type baseModuleContext struct {
 	android.BaseContext
 	moduleContextImpl
@@ -335,6 +355,12 @@
 	moduleContextImpl
 }
 
+// Vendor returns true for vendor modules so that they get installed onto the
+// correct partition
+func (ctx *moduleContext) Vendor() bool {
+	return ctx.ModuleContext.Vendor() || ctx.moduleContextImpl.mod.Properties.UseVndk
+}
+
 type moduleContextImpl struct {
 	mod *Module
 	ctx BaseModuleContext
@@ -371,7 +397,7 @@
 }
 
 func (ctx *moduleContextImpl) sdk() bool {
-	if ctx.ctx.Device() {
+	if ctx.ctx.Device() && !ctx.vndk() {
 		return ctx.mod.Properties.Sdk_version != ""
 	}
 	return false
@@ -389,7 +415,7 @@
 }
 
 func (ctx *moduleContextImpl) vndk() bool {
-	return ctx.ctx.Os() == android.Android && ctx.ctx.Vendor() && ctx.ctx.DeviceConfig().CompileVndk()
+	return ctx.mod.vndk()
 }
 
 func (ctx *moduleContextImpl) selectedStl() string {
@@ -772,6 +798,10 @@
 			// Host code is not restricted
 			return
 		}
+		if from.Properties.UseVndk {
+			// Vendor code is already limited by the vendor mutator
+			return
+		}
 		if from.Properties.Sdk_version == "" {
 			// Platform code can link to anything
 			return
@@ -1060,6 +1090,57 @@
 	return android.InitDefaultsModule(module, module, props...)
 }
 
+const (
+	// coreMode is the variant used for framework-private libraries, or
+	// SDK libraries. (which framework-private libraries can use)
+	coreMode = "core"
+
+	// vendorMode is the variant used for /vendor code that compiles
+	// against the VNDK.
+	vendorMode = "vendor"
+)
+
+func vendorMutator(mctx android.BottomUpMutatorContext) {
+	if mctx.Os() != android.Android {
+		return
+	}
+
+	m, ok := mctx.Module().(*Module)
+	if !ok {
+		return
+	}
+
+	// Sanity check
+	if Bool(m.Properties.Vendor_available) && mctx.Vendor() {
+		mctx.PropertyErrorf("vendor_available",
+			"doesn't make sense at the same time as `vendor: true` or `proprietary: true`")
+		return
+	}
+
+	if !mctx.DeviceConfig().CompileVndk() {
+		// If the device isn't compiling against the VNDK, we always
+		// use the core mode.
+		mctx.CreateVariations(coreMode)
+	} else if _, ok := m.linker.(*llndkStubDecorator); ok {
+		// LL-NDK stubs only exist in the vendor variant, since the
+		// real libraries will be used in the core variant.
+		mctx.CreateVariations(vendorMode)
+	} else if Bool(m.Properties.Vendor_available) {
+		// This will be available in both /system and /vendor
+		mod := mctx.CreateVariations(coreMode, vendorMode)
+		mod[1].(*Module).Properties.UseVndk = true
+	} else if mctx.Vendor() && m.Properties.Sdk_version == "" {
+		// This will be available in /vendor only
+		mod := mctx.CreateVariations(vendorMode)
+		mod[0].(*Module).Properties.UseVndk = true
+	} else {
+		// This is either in /system (or similar: /data), or is a
+		// modules built with the NDK. Modules built with the NDK
+		// will be restricted using the existing link type checks.
+		mctx.CreateVariations(coreMode)
+	}
+}
+
 // lastUniqueElements returns all unique elements of a slice, keeping the last copy of each
 // modifies the slice contents in place, and returns a subslice of the original slice
 func lastUniqueElements(list []string) []string {
diff --git a/cc/compiler.go b/cc/compiler.go
index 9fc2747..aed4480 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -113,6 +113,18 @@
 		// release builds
 		Cflags []string `android:"arch_variant"`
 	} `android:"arch_variant"`
+
+	Target struct {
+		Vendor struct {
+			// list of source files that should only be used in the
+			// vendor variant of the C/C++ module.
+			Srcs []string
+
+			// list of source files that should not be used to
+			// build the vendor variant of the C/C++ module.
+			Exclude_srcs []string
+		}
+	}
 }
 
 func NewBaseCompiler() *baseCompiler {
@@ -429,6 +441,14 @@
 	pathDeps := deps.GeneratedHeaders
 	pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
 
+	if ctx.vndk() {
+		compiler.Properties.Srcs = append(compiler.Properties.Srcs,
+			compiler.Properties.Target.Vendor.Srcs...)
+
+		compiler.Properties.Exclude_srcs = append(compiler.Properties.Exclude_srcs,
+			compiler.Properties.Target.Vendor.Exclude_srcs...)
+	}
+
 	srcs := ctx.ExpandSources(compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
 	srcs = append(srcs, deps.GeneratedSources...)
 
diff --git a/cc/installer.go b/cc/installer.go
index c4de589..112a7ea 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -68,6 +68,9 @@
 	if !ctx.Host() && !ctx.Arch().Native {
 		subDir = filepath.Join(subDir, ctx.Arch().ArchType.String())
 	}
+	if installer.location == InstallInData && ctx.vndk() {
+		subDir = filepath.Join(subDir, "vendor")
+	}
 	return android.PathForModuleInstall(ctx, subDir, installer.Properties.Relative_install_path, installer.relative)
 }
 
diff --git a/cc/library.go b/cc/library.go
index e9e796e..0ba7088 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -84,6 +84,16 @@
 	// be added to the include path (using -I) for this module and any module that links
 	// against this module
 	Export_include_dirs []string `android:"arch_variant"`
+
+	Target struct {
+		Vendor struct {
+			// list of exported include directories, like
+			// export_include_dirs, that will be applied to the
+			// vendor variant of this library. This will overwrite
+			// any other declarations.
+			Export_include_dirs []string
+		}
+	}
 }
 
 func init() {
@@ -144,8 +154,16 @@
 	flagsDeps android.Paths
 }
 
+func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
+	if ctx.Vendor() && f.Properties.Target.Vendor.Export_include_dirs != nil {
+		return android.PathsForModuleSrc(ctx, f.Properties.Target.Vendor.Export_include_dirs)
+	} else {
+		return android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
+	}
+}
+
 func (f *flagExporter) exportIncludes(ctx ModuleContext, inc string) {
-	includeDirs := android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
+	includeDirs := f.exportedIncludes(ctx)
 	for _, dir := range includeDirs.Strings() {
 		f.flags = append(f.flags, inc+dir)
 	}
@@ -277,7 +295,7 @@
 }
 
 func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
-	exportIncludeDirs := android.PathsForModuleSrc(ctx, library.flagExporter.Properties.Export_include_dirs)
+	exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
 	if len(exportIncludeDirs) > 0 {
 		flags.GlobalFlags = append(flags.GlobalFlags, includeDirsToFlags(exportIncludeDirs))
 	}
@@ -369,7 +387,7 @@
 		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
 	} else if library.shared() {
 		if ctx.toolchain().Bionic() && !Bool(library.baseLinker.Properties.Nocrt) {
-			if !ctx.sdk() && !ctx.vndk() {
+			if !ctx.sdk() {
 				deps.CrtBegin = "crtbegin_so"
 				deps.CrtEnd = "crtend_so"
 			} else {
diff --git a/cc/linker.go b/cc/linker.go
index 4d21d99..5a3b478 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -143,7 +143,7 @@
 			if linker.Properties.System_shared_libs != nil {
 				deps.LateSharedLibs = append(deps.LateSharedLibs,
 					linker.Properties.System_shared_libs...)
-			} else if !ctx.sdk() {
+			} else if !ctx.sdk() && !ctx.vndk() {
 				deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm")
 			}
 		}
@@ -154,6 +154,9 @@
 				"libm",
 			)
 		}
+		if ctx.vndk() {
+			deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm")
+		}
 	}
 
 	if ctx.Windows() {
diff --git a/cc/makevars.go b/cc/makevars.go
index cad76f9..ce2ac5a 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -57,8 +57,6 @@
 	} else {
 		ctx.Strict("BOARD_VNDK_VERSION", "")
 	}
-	ctx.Strict("VNDK_LIBRARIES", strings.Join(config.VndkLibraries(), " "))
-	ctx.Strict("LLNDK_LIBRARIES", strings.Join(config.LLndkLibraries(), " "))
 
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", asanCflags)
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", asanLdflags)
diff --git a/scripts/setup_go_workspace_for_soong.sh b/scripts/setup_go_workspace_for_soong.sh
new file mode 100755
index 0000000..4b118ef
--- /dev/null
+++ b/scripts/setup_go_workspace_for_soong.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+set -e
+
+#mounts the components of soong into a directory structure that Go tools and editors expect
+
+#move to the script's directory
+cd "$(dirname $0)"
+SCRIPT_PATH="$PWD"
+
+#find the root of the Repo checkout
+cd "${SCRIPT_PATH}"/../../..
+ANDROID_PATH="${PWD}"
+OUTPUT_PATH="$(echo ${GOPATH} | sed 's/\:.*//')" #if GOPATH contains multiple paths, use the first one
+
+if [ -z "${OUTPUT_PATH}" ]; then
+  echo "Error; could not determine the desired location at which to create a Go-compatible workspace. Please update GOPATH to specify the desired destination directory"
+  exit 1
+fi
+
+function confirm() {
+  while true; do
+    echo "Will create GOPATH-compatible directory structure at ${OUTPUT_PATH}"
+    echo -n "Ok [Y/n]?"
+    read decision
+    if [ "${decision}" == "y" -o "${decision}" == "Y" -o "${decision}" == "" ]; then
+      return 0
+    else
+      if [ "${decision}" == "n" ]; then
+        return 1
+      else
+        echo "Invalid choice ${decision}; choose either 'y' or 'n'"
+      fi
+    fi
+  done
+}
+
+function bindAll() {
+  bindOne "${ANDROID_PATH}/build/blueprint" "${OUTPUT_PATH}/src/github.com/google/blueprint"
+  bindOne "${ANDROID_PATH}/build/soong" "${OUTPUT_PATH}/src/android/soong"
+
+  bindOne "${ANDROID_PATH}/art/build" "${OUTPUT_PATH}/src/android/soong/art"
+  bindOne "${ANDROID_PATH}/external/llvm/soong" "${OUTPUT_PATH}/src/android/soong/llvm"
+  bindOne "${ANDROID_PATH}/external/clang/soong" "${OUTPUT_PATH}/src/android/soong/clang"
+  echo
+  echo "Created GOPATH-compatible directory structure at ${OUTPUT_PATH}"
+}
+
+function bindOne() {
+  #causes $newPath to mirror $existingPath
+  existingPath="$1"
+  newPath="$2"
+  mkdir -p "$newPath"
+  echoAndDo bindfs "${existingPath}" "${newPath}"
+}
+
+function echoAndDo() {
+  echo "$@"
+  eval "$@"
+}
+
+if confirm; then
+  echo
+  bindAll
+else
+  echo "skipping due to user request"
+  exit 1
+fi