Merge "Export TSAN_RUNTIME_LIBRARY make variable"
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 75c3eec..331bb4f 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -103,6 +103,7 @@
 			"LOCAL_AIDL_INCLUDES":         "aidl_includes",
 			"LOCAL_AAPT_FLAGS":            "aaptflags",
 			"LOCAL_PACKAGE_SPLITS":        "package_splits",
+			"LOCAL_COMPATIBILITY_SUITE":   "test_suites",
 		})
 	addStandardProperties(bpparser.BoolType,
 		map[string]string{
diff --git a/cc/androidmk.go b/cc/androidmk.go
index f45fbbe..7acc244 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -200,6 +200,14 @@
 		ret.SubName = "_" + test.binaryDecorator.Properties.Stem
 	}
 
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
+		if len(test.Properties.Test_suites) > 0 {
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITES :=",
+				strings.Join(test.Properties.Test_suites, " "))
+		}
+		return nil
+	})
+
 	var testFiles []string
 	for _, d := range test.data {
 		rel := d.Rel()
diff --git a/cc/builder.go b/cc/builder.go
index f3a4bcb..cdfea92 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -109,7 +109,7 @@
 		},
 		"objcopyCmd", "prefix")
 
-	stripPath = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
+	_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
 
 	strip = pctx.AndroidStaticRule("strip",
 		blueprint.RuleParams{
@@ -127,7 +127,7 @@
 			Description: "empty file $out",
 		})
 
-	copyGccLibPath = pctx.SourcePathVariable("copyGccLibPath", "build/soong/scripts/copygcclib.sh")
+	_ = pctx.SourcePathVariable("copyGccLibPath", "build/soong/scripts/copygcclib.sh")
 
 	copyGccLib = pctx.AndroidStaticRule("copyGccLib",
 		blueprint.RuleParams{
@@ -139,7 +139,7 @@
 		},
 		"ccCmd", "cFlags", "libName")
 
-	tocPath = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
+	_ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
 
 	toc = pctx.AndroidStaticRule("toc",
 		blueprint.RuleParams{
@@ -159,7 +159,7 @@
 		},
 		"cFlags", "tidyFlags")
 
-	yasmCmd = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
+	_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
 
 	yasm = pctx.AndroidStaticRule("yasm",
 		blueprint.RuleParams{
diff --git a/cc/cc.go b/cc/cc.go
index 4c69723..b27e8ee 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -675,7 +675,7 @@
 						variantLibs = append(variantLibs, entry+ndkLibrarySuffix)
 					}
 				} else {
-					nonvariantLibs = append(variantLibs, entry)
+					nonvariantLibs = append(nonvariantLibs, entry)
 				}
 			}
 			return nonvariantLibs, variantLibs
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index 1c47ec9..83b6d69 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -163,9 +163,15 @@
 	translateToCMake(cppParameters, f, false, true)
 
 	// Add project executable.
-	f.WriteString(fmt.Sprintf("\nadd_executable(%s ${SOURCE_FILES})\n", ccModule.ModuleBase.Name()))
+	f.WriteString(fmt.Sprintf("\nadd_executable(%s ${SOURCE_FILES})\n",
+		cleanExecutableName(ccModule.ModuleBase.Name())))
 }
 
+func cleanExecutableName(s string) string {
+	return strings.Replace(s, "@", "-", -1)
+}
+
+
 func translateToCMake(c compilerParameters, f *os.File, cflags bool, cppflags bool) {
 	writeAllSystemDirectories(c.systemHeaderSearchPath, f)
 	writeAllIncludeDirectories(c.headerSearchPath, f)
@@ -189,16 +195,26 @@
 	return fmt.Sprintf("${ANDROID_ROOT}/%s", p)
 }
 
-func writeAllIncludeDirectories(includes map[string]bool, f *os.File) {
-	for include := range includes {
-		f.WriteString(fmt.Sprintf("include_directories(\"%s\")\n", buildCMakePath(include)))
+func writeAllIncludeDirectories(includes []string, f *os.File) {
+	if len(includes) == 0 {
+		return
 	}
+	f.WriteString("include_directories(\n")
+	for _, include := range includes {
+		f.WriteString(fmt.Sprintf("                    \"%s\"\n", buildCMakePath(include)))
+	}
+	f.WriteString(")\n")
 }
 
-func writeAllSystemDirectories(includes map[string]bool, f *os.File) {
-	for include := range includes {
-		f.WriteString(fmt.Sprintf("include_directories(SYSTEM \"%s\")\n", buildCMakePath(include)))
+func writeAllSystemDirectories(includes []string, f *os.File) {
+	if len(includes) == 0 {
+		return
 	}
+	f.WriteString("include_directories(SYSTEM \n")
+	for _, include := range includes {
+		f.WriteString(fmt.Sprintf("                           \"%s\"\n", buildCMakePath(include)))
+	}
+	f.WriteString(")\n")
 }
 
 func writeAllFlags(flags []string, f *os.File, tag string) {
@@ -218,17 +234,14 @@
 )
 
 type compilerParameters struct {
-	headerSearchPath       map[string]bool
-	systemHeaderSearchPath map[string]bool
+	headerSearchPath       []string
+	systemHeaderSearchPath []string
 	flags                  []string
 	sysroot                string
 }
 
 func makeCompilerParameters() compilerParameters {
 	return compilerParameters{
-		headerSearchPath:       make(map[string]bool),
-		systemHeaderSearchPath: make(map[string]bool),
-		flags:   make([]string, 0),
 		sysroot: "",
 	}
 }
@@ -267,7 +280,8 @@
 
 		switch categorizeParameter(param) {
 		case headerSearchPath:
-			compilerParameters.headerSearchPath[strings.TrimPrefix(param, "-I")] = true
+			compilerParameters.headerSearchPath =
+				append(compilerParameters.headerSearchPath, strings.TrimPrefix(param, "-I"))
 		case variable:
 			if evaluated, error := evalVariable(ctx, param); error == nil {
 				if outputDebugInfo {
@@ -284,7 +298,8 @@
 			}
 		case systemHeaderSearchPath:
 			if i < len(params)-1 {
-				compilerParameters.systemHeaderSearchPath[params[i+1]] = true
+				compilerParameters.systemHeaderSearchPath =
+					append(compilerParameters.systemHeaderSearchPath, params[i+1])
 			} else if outputDebugInfo {
 				f.WriteString("# Found a header search path marker with no path")
 			}
@@ -343,8 +358,8 @@
 }
 
 func concatenateParams(c1 *compilerParameters, c2 compilerParameters) {
-	concatenateMaps(c1.headerSearchPath, c2.headerSearchPath)
-	concatenateMaps(c1.systemHeaderSearchPath, c2.systemHeaderSearchPath)
+	c1.headerSearchPath = append(c1.headerSearchPath, c2.headerSearchPath...)
+	c1.systemHeaderSearchPath = append(c1.systemHeaderSearchPath, c2.systemHeaderSearchPath...)
 	if c2.sysroot != "" {
 		c1.sysroot = c2.sysroot
 	}
@@ -359,13 +374,6 @@
 	return "", err
 }
 
-// Concatenate two maps into one. Results are stored in first operand.
-func concatenateMaps(map1 map[string]bool, map2 map[string]bool) {
-	for key, value := range map2 {
-		map1[key] = value
-	}
-}
-
 func getCMakeListsForModule(module *Module, ctx blueprint.SingletonContext) string {
 	return filepath.Join(getAndroidSrcRootDirectory(ctx),
 		cLionOutputProjectsDirectory,
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index fe47ddf..23186e7 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -66,9 +66,6 @@
 		"-fuse-ld=gold",
 		"-Wl,--icf=safe",
 		"-Wl,--no-undefined-version",
-
-		// Disable transitive dependency library symbol resolving.
-		"-Wl,--allow-shlib-undefined",
 	}
 
 	arm64Cppflags = []string{
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 10f4cea..30ab1c6 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -91,6 +91,10 @@
 
 		// http://b/29823425 Disable -Wexpansion-to-defined for Clang update to r271374
 		"-Wno-expansion-to-defined",
+
+		// http://b/36463318 Clang executes with an absolute path, so clang-provided
+		// headers are now absolute.
+		"-fdebug-prefix-map=$$PWD/=",
 	}, " "))
 
 	pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{
diff --git a/cc/test.go b/cc/test.go
index d3556bf..145b5b0 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -20,6 +20,7 @@
 	"strings"
 
 	"android/soong/android"
+
 	"github.com/google/blueprint"
 )
 
@@ -41,6 +42,10 @@
 	// list of files or filegroup modules that provide data that should be installed alongside
 	// the test
 	Data []string
+
+	// list of compatibility suites (for example "cts", "vts") that the module should be
+	// installed into.
+	Test_suites []string
 }
 
 func init() {
diff --git a/cmd/fileslist/Android.bp b/cmd/fileslist/Android.bp
new file mode 100644
index 0000000..cbf939a
--- /dev/null
+++ b/cmd/fileslist/Android.bp
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+blueprint_go_binary {
+    name: "fileslist",
+    srcs: [
+        "fileslist.go",
+    ],
+}
diff --git a/cmd/fileslist/fileslist.go b/cmd/fileslist/fileslist.go
new file mode 100755
index 0000000..1cf948f
--- /dev/null
+++ b/cmd/fileslist/fileslist.go
@@ -0,0 +1,165 @@
+// Copyright 2017 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.
+
+// fileslist.py replacement written in GO, which utilizes multi-cores.
+
+package main
+
+import (
+	"crypto/sha256"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+)
+
+const (
+	MAX_DEFAULT_PARA = 24
+)
+
+func defaultPara() int {
+	ret := runtime.NumCPU()
+	if ret > MAX_DEFAULT_PARA {
+		return MAX_DEFAULT_PARA
+	}
+	return ret
+}
+
+var (
+	para = flag.Int("para", defaultPara(), "Number of goroutines")
+)
+
+// Represents each file.
+type Node struct {
+	SHA256 string
+	Name   string // device side path.
+	Size   int64
+	path   string // host side path.
+	stat   os.FileInfo
+}
+
+func newNode(hostPath string, devicePath string, stat os.FileInfo) Node {
+	return Node{Name: devicePath, path: hostPath, stat: stat}
+}
+
+// Scan a Node and returns true if it should be added to the result.
+func (n *Node) scan() bool {
+	n.Size = n.stat.Size()
+
+	// Calculate SHA256.
+	f, err := os.Open(n.path)
+	if err != nil {
+		// If the file can't be read, it's probably a symlink to an absolute path...
+		// Returns the following to mimic the behavior of fileslist.py.
+		n.SHA256 = "----------------------------------------------------------------"
+		return true
+	}
+	defer f.Close()
+
+	h := sha256.New()
+	if _, err := io.Copy(h, f); err != nil {
+		panic(err)
+	}
+	n.SHA256 = fmt.Sprintf("%x", h.Sum(nil))
+	return true
+}
+
+func main() {
+	flag.Parse()
+
+	allOutput := make([]Node, 0, 1024) // Store all outputs.
+	mutex := &sync.Mutex{}             // Guard allOutput
+
+	ch := make(chan Node) // Pass nodes to goroutines.
+
+	var wg sync.WaitGroup // To wait for all goroutines.
+	wg.Add(*para)
+
+	// Scan files in multiple goroutines.
+	for i := 0; i < *para; i++ {
+		go func() {
+			defer wg.Done()
+
+			output := make([]Node, 0, 1024) // Local output list.
+			for node := range ch {
+				if node.scan() {
+					output = append(output, node)
+				}
+			}
+			// Add to the global output list.
+			mutex.Lock()
+			allOutput = append(allOutput, output...)
+			mutex.Unlock()
+		}()
+	}
+
+	// Walk the directories and find files to scan.
+	for _, dir := range flag.Args() {
+		absDir, err := filepath.Abs(dir)
+		if err != nil {
+			panic(err)
+		}
+		deviceRoot := filepath.Clean(absDir + "/..")
+		err = filepath.Walk(dir, func(path string, stat os.FileInfo, err error) error {
+			if err != nil {
+				panic(err)
+			}
+			if stat.IsDir() {
+				return nil
+			}
+			absPath, err := filepath.Abs(path)
+			if err != nil {
+				panic(err)
+			}
+			devicePath, err := filepath.Rel(deviceRoot, absPath)
+			if err != nil {
+				panic(err)
+			}
+			devicePath = "/" + devicePath
+			ch <- newNode(absPath, devicePath, stat)
+			return nil
+		})
+		if err != nil {
+			panic(err)
+		}
+	}
+
+	// Wait until all the goroutines finish.
+	close(ch)
+	wg.Wait()
+
+	// Sort the entries and dump as json.
+	sort.Slice(allOutput, func(i, j int) bool {
+		if allOutput[i].Size > allOutput[j].Size {
+			return true
+		}
+		if allOutput[i].Size == allOutput[j].Size && strings.Compare(allOutput[i].Name, allOutput[j].Name) > 0 {
+			return true
+		}
+		return false
+	})
+
+	j, err := json.MarshalIndent(allOutput, "", "  ")
+	if err != nil {
+		panic(nil)
+	}
+
+	fmt.Printf("%s\n", j)
+}