Merge "Merge Coral/Flame into AOSP master"
diff --git a/OWNERS b/OWNERS
index 797229f..4ae045d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,4 +4,3 @@
 per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
 per-file tidy.go = srhines@google.com, chh@google.com
 per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
-per-file rust/config/whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/androidmk/Android.bp b/androidmk/Android.bp
index 79fe530..4110073 100644
--- a/androidmk/Android.bp
+++ b/androidmk/Android.bp
@@ -19,12 +19,23 @@
 blueprint_go_binary {
     name: "androidmk",
     srcs: [
-        "cmd/androidmk/android.go",
-        "cmd/androidmk/androidmk.go",
-        "cmd/androidmk/values.go",
+        "cmd/androidmk.go",
+    ],
+    deps: [
+        "androidmk-lib",
+    ],
+}
+
+bootstrap_go_package {
+    name: "androidmk-lib",
+    pkgPath: "android/soong/androidmk/androidmk",
+    srcs: [
+        "androidmk/android.go",
+        "androidmk/androidmk.go",
+        "androidmk/values.go",
     ],
     testSrcs: [
-        "cmd/androidmk/androidmk_test.go",
+        "androidmk/androidmk_test.go",
     ],
     deps: [
         "androidmk-parser",
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/androidmk/android.go
similarity index 99%
rename from androidmk/cmd/androidmk/android.go
rename to androidmk/androidmk/android.go
index fcadd03..be52879 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package androidmk
 
 import (
 	"android/soong/android"
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
similarity index 93%
rename from androidmk/cmd/androidmk/androidmk.go
rename to androidmk/androidmk/androidmk.go
index d2a84d1..9d0c3ac 100644
--- a/androidmk/cmd/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -12,14 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package androidmk
 
 import (
 	"bytes"
-	"flag"
 	"fmt"
-	"io/ioutil"
-	"os"
 	"strings"
 	"text/scanner"
 
@@ -30,13 +27,6 @@
 	bpparser "github.com/google/blueprint/parser"
 )
 
-var usage = func() {
-	fmt.Fprintf(os.Stderr, "usage: androidmk [flags] <inputFile>\n"+
-		"\nandroidmk parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n")
-	flag.PrintDefaults()
-	os.Exit(1)
-}
-
 // TODO: non-expanded variables with expressions
 
 type bpFile struct {
@@ -118,31 +108,7 @@
 	eq   bool
 }
 
-func main() {
-	flag.Usage = usage
-	flag.Parse()
-	if len(flag.Args()) != 1 {
-		usage()
-	}
-	filePathToRead := flag.Arg(0)
-	b, err := ioutil.ReadFile(filePathToRead)
-	if err != nil {
-		fmt.Println(err.Error())
-		return
-	}
-
-	output, errs := convertFile(os.Args[1], bytes.NewBuffer(b))
-	if len(errs) > 0 {
-		for _, err := range errs {
-			fmt.Fprintln(os.Stderr, "ERROR: ", err)
-		}
-		os.Exit(1)
-	}
-
-	fmt.Print(output)
-}
-
-func convertFile(filename string, buffer *bytes.Buffer) (string, []error) {
+func ConvertFile(filename string, buffer *bytes.Buffer) (string, []error) {
 	p := mkparser.NewParser(filename, buffer)
 
 	nodes, errs := p.Parse()
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
similarity index 99%
rename from androidmk/cmd/androidmk/androidmk_test.go
rename to androidmk/androidmk/androidmk_test.go
index dbb7fde..7e1a72c 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package androidmk
 
 import (
 	"bytes"
@@ -1350,7 +1350,7 @@
 			t.Error(err)
 		}
 
-		got, errs := convertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
+		got, errs := ConvertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
 		if len(errs) > 0 {
 			t.Errorf("Unexpected errors: %q", errs)
 			continue
diff --git a/androidmk/cmd/androidmk/values.go b/androidmk/androidmk/values.go
similarity index 99%
rename from androidmk/cmd/androidmk/values.go
rename to androidmk/androidmk/values.go
index 90f2e74..6b18a65 100644
--- a/androidmk/cmd/androidmk/values.go
+++ b/androidmk/androidmk/values.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package androidmk
 
 import (
 	"fmt"
diff --git a/androidmk/cmd/androidmk.go b/androidmk/cmd/androidmk.go
new file mode 100644
index 0000000..00488eb
--- /dev/null
+++ b/androidmk/cmd/androidmk.go
@@ -0,0 +1,56 @@
+// 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.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"os"
+
+	"android/soong/androidmk/androidmk"
+)
+
+var usage = func() {
+	fmt.Fprintf(os.Stderr, "usage: androidmk [flags] <inputFile>\n"+
+		"\nandroidmk parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n")
+	flag.PrintDefaults()
+	os.Exit(1)
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+	if len(flag.Args()) != 1 {
+		usage()
+	}
+	filePathToRead := flag.Arg(0)
+	b, err := ioutil.ReadFile(filePathToRead)
+	if err != nil {
+		fmt.Println(err.Error())
+		return
+	}
+
+	output, errs := androidmk.ConvertFile(os.Args[1], bytes.NewBuffer(b))
+	if len(errs) > 0 {
+		for _, err := range errs {
+			fmt.Fprintln(os.Stderr, "ERROR: ", err)
+		}
+		os.Exit(1)
+	}
+
+	fmt.Print(output)
+}
diff --git a/androidmk/partner_androidmk/Android.bp b/androidmk/partner_androidmk/Android.bp
new file mode 100644
index 0000000..532116a
--- /dev/null
+++ b/androidmk/partner_androidmk/Android.bp
@@ -0,0 +1,49 @@
+// Copyright 2015 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.
+
+//
+// Sample project for creating an extended androidmk
+//
+
+blueprint_go_binary {
+    name: "partner_androidmk",
+    srcs: [
+        "partner_androidmk/androidmk.go",
+    ],
+    testSrcs: [
+        "partner_androidmk/androidmk_test.go",
+    ],
+    deps: [
+        "androidmk-lib",
+        "partner_bpfix_extensions",
+    ],
+}
+
+blueprint_go_binary {
+    name: "partner_bpfix",
+    srcs: [
+        "partner_bpfix/bpfix.go",
+    ],
+    deps: [
+        "bpfix-cmd",
+        "partner_bpfix_extensions",
+    ],
+}
+
+bootstrap_go_package {
+    name: "partner_bpfix_extensions",
+    pkgPath: "partner/android/bpfix/extensions",
+    srcs: ["fixes/headers.go"],
+    deps: ["bpfix-lib"],
+}
diff --git a/androidmk/partner_androidmk/fixes/headers.go b/androidmk/partner_androidmk/fixes/headers.go
new file mode 100644
index 0000000..169dab6
--- /dev/null
+++ b/androidmk/partner_androidmk/fixes/headers.go
@@ -0,0 +1,120 @@
+package extensions
+
+import (
+	"strings"
+
+	"github.com/google/blueprint/parser"
+
+	"android/soong/bpfix/bpfix"
+)
+
+var fixSteps = bpfix.FixStepsExtension{
+	Name: "partner-include-dirs",
+	Steps: []bpfix.FixStep{
+		{
+			Name: "fixIncludeDirs",
+			Fix:  fixIncludeDirs,
+		},
+	},
+}
+
+func init() {
+	bpfix.RegisterFixStepExtension(&fixSteps)
+}
+
+type includeDirFix struct {
+	libName  string
+	libType  string
+	variable string
+	subdir   string
+}
+
+var commonIncludeDirs = []includeDirFix{
+	{
+		libName:  "my_header_lib",
+		libType:  "header_libs",
+		variable: "TARGET_OUT_HEADERS",
+		subdir:   "/my_headers",
+	},
+}
+
+func findHeaderLib(e parser.Expression) (*includeDirFix, bool) {
+	if op, ok := e.(*parser.Operator); ok {
+		if op.Operator != '+' {
+			return nil, false
+		}
+		arg0, ok := op.Args[0].(*parser.Variable)
+		arg1, ok1 := op.Args[1].(*parser.String)
+		if !ok || !ok1 {
+			return nil, false
+		}
+		for _, lib := range commonIncludeDirs {
+			if arg0.Name == lib.variable && arg1.Value == lib.subdir {
+				return &lib, true
+			}
+		}
+	}
+	return nil, false
+}
+func searchThroughOperatorList(mod *parser.Module, e parser.Expression) {
+	if list, ok := e.(*parser.List); ok {
+		newList := make([]parser.Expression, 0, len(list.Values))
+		for _, item := range list.Values {
+			if lib, found := findHeaderLib(item); found {
+				if lib.libName != "" {
+					addLibrary(mod, lib.libType, lib.libName)
+				}
+			} else {
+				newList = append(newList, item)
+			}
+		}
+		list.Values = newList
+	}
+	if op, ok := e.(*parser.Operator); ok {
+		searchThroughOperatorList(mod, op.Args[0])
+		searchThroughOperatorList(mod, op.Args[1])
+	}
+}
+func getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) {
+	prop, ok := mod.GetProperty(name)
+	if !ok {
+		return nil, false
+	}
+	list, ok = prop.Value.(*parser.List)
+	return list, ok
+}
+func addLibrary(mod *parser.Module, libType string, libName string) {
+	var list, ok = getLiteralListProperty(mod, libType)
+	if !ok {
+		list = new(parser.List)
+		prop := new(parser.Property)
+		prop.Name = libType
+		prop.Value = list
+		mod.Properties = append(mod.Properties, prop)
+	} else {
+		for _, v := range list.Values {
+			if stringValue, ok := v.(*parser.String); ok && stringValue.Value == libName {
+				return
+			}
+		}
+	}
+	lib := new(parser.String)
+	lib.Value = libName
+	list.Values = append(list.Values, lib)
+}
+func fixIncludeDirs(f *bpfix.Fixer) error {
+	tree := f.Tree()
+	for _, def := range tree.Defs {
+		mod, ok := def.(*parser.Module)
+		if !ok {
+			continue
+		}
+		if !strings.HasPrefix(mod.Type, "cc_") {
+			continue
+		}
+		if prop, ok := mod.GetProperty("include_dirs"); ok {
+			searchThroughOperatorList(mod, prop.Value)
+		}
+	}
+	return nil
+}
diff --git a/androidmk/partner_androidmk/partner_androidmk/androidmk.go b/androidmk/partner_androidmk/partner_androidmk/androidmk.go
new file mode 100644
index 0000000..af8cdf3
--- /dev/null
+++ b/androidmk/partner_androidmk/partner_androidmk/androidmk.go
@@ -0,0 +1,58 @@
+// 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.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"os"
+
+	"android/soong/androidmk/androidmk"
+
+	_ "partner/android/bpfix/extensions"
+)
+
+var usage = func() {
+	fmt.Fprintf(os.Stderr, "usage: %s [flags] <inputFile>\n"+
+		"\n%s parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n", os.Args[0], os.Args[0])
+	flag.PrintDefaults()
+	os.Exit(1)
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+	if len(flag.Args()) != 1 {
+		usage()
+	}
+	filePathToRead := flag.Arg(0)
+	b, err := ioutil.ReadFile(filePathToRead)
+	if err != nil {
+		fmt.Println(err.Error())
+		return
+	}
+
+	output, errs := androidmk.ConvertFile(os.Args[1], bytes.NewBuffer(b))
+	if len(errs) > 0 {
+		for _, err := range errs {
+			fmt.Fprintln(os.Stderr, "ERROR: ", err)
+		}
+		os.Exit(1)
+	}
+
+	fmt.Print(output)
+}
diff --git a/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go b/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go
new file mode 100644
index 0000000..ff04e88
--- /dev/null
+++ b/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go
@@ -0,0 +1,73 @@
+// Copyright 2016 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 main
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+
+	"android/soong/androidmk/androidmk"
+	"android/soong/bpfix/bpfix"
+
+	_ "partner/android/bpfix/extensions"
+)
+
+var testCases = []struct {
+	desc     string
+	in       string
+	expected string
+}{
+	{
+		desc: "headers replacement",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := test
+LOCAL_SRC_FILES := a.c
+LOCAL_C_INCLUDES := test1 $(TARGET_OUT_HEADERS)/my_headers test2
+include $(BUILD_SHARED_LIBRARY)`,
+		expected: `
+cc_library_shared {
+    name: "test",
+	srcs: ["a.c"],
+	include_dirs: [
+		"test1",
+
+		"test2",
+	],
+	header_libs: ["my_header_lib"]
+}`,
+	},
+}
+
+func TestEndToEnd(t *testing.T) {
+	for i, test := range testCases {
+		expected, err := bpfix.Reformat(test.expected)
+		if err != nil {
+			t.Error(err)
+		}
+
+		got, errs := androidmk.ConvertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
+		if len(errs) > 0 {
+			t.Errorf("Unexpected errors: %q", errs)
+			continue
+		}
+
+		if got != expected {
+			t.Errorf("failed testcase '%s'\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n", test.desc, strings.TrimSpace(test.in), expected, got)
+		}
+	}
+}
diff --git a/androidmk/partner_androidmk/partner_bpfix/bpfix.go b/androidmk/partner_androidmk/partner_bpfix/bpfix.go
new file mode 100644
index 0000000..2c8e0a8
--- /dev/null
+++ b/androidmk/partner_androidmk/partner_bpfix/bpfix.go
@@ -0,0 +1,27 @@
+// 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.
+
+// This file provides a command-line interface to bpfix
+
+package main
+
+import (
+	"android/soong/bpfix/bpfix/cmd"
+
+	_ "partner/android/bpfix/extensions"
+)
+
+func main() {
+	cmd.Run()
+}
diff --git a/bpfix/Android.bp b/bpfix/Android.bp
index 90a453d..aec9ff9 100644
--- a/bpfix/Android.bp
+++ b/bpfix/Android.bp
@@ -19,7 +19,18 @@
 blueprint_go_binary {
     name: "bpfix",
     srcs: [
-        "cmd/bpfix.go",
+        "cmd/main.go",
+    ],
+    deps: [
+        "bpfix-cmd",
+    ],
+}
+
+bootstrap_go_package {
+    name: "bpfix-cmd",
+    pkgPath: "android/soong/bpfix/bpfix/cmd",
+    srcs: [
+        "cmd-lib/bpfix.go",
     ],
     deps: [
         "bpfix-lib",
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 5f1cce8..9cba80a 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -45,66 +45,76 @@
 // A FixRequest specifies the details of which fixes to apply to an individual file
 // A FixRequest doesn't specify whether to do a dry run or where to write the results; that's in cmd/bpfix.go
 type FixRequest struct {
-	steps []fixStep
+	steps []FixStep
+}
+type FixStepsExtension struct {
+	Name  string
+	Steps []FixStep
 }
 
-type fixStep struct {
-	name string
-	fix  func(f *Fixer) error
+type FixStep struct {
+	Name string
+	Fix  func(f *Fixer) error
 }
 
-var fixSteps = []fixStep{
+var fixStepsExtensions = []*FixStepsExtension(nil)
+
+func RegisterFixStepExtension(extension *FixStepsExtension) {
+	fixStepsExtensions = append(fixStepsExtensions, extension)
+}
+
+var fixSteps = []FixStep{
 	{
-		name: "simplifyKnownRedundantVariables",
-		fix:  runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther),
+		Name: "simplifyKnownRedundantVariables",
+		Fix:  runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther),
 	},
 	{
-		name: "rewriteIncorrectAndroidmkPrebuilts",
-		fix:  rewriteIncorrectAndroidmkPrebuilts,
+		Name: "rewriteIncorrectAndroidmkPrebuilts",
+		Fix:  rewriteIncorrectAndroidmkPrebuilts,
 	},
 	{
-		name: "rewriteCtsModuleTypes",
-		fix:  rewriteCtsModuleTypes,
+		Name: "rewriteCtsModuleTypes",
+		Fix:  rewriteCtsModuleTypes,
 	},
 	{
-		name: "rewriteIncorrectAndroidmkAndroidLibraries",
-		fix:  rewriteIncorrectAndroidmkAndroidLibraries,
+		Name: "rewriteIncorrectAndroidmkAndroidLibraries",
+		Fix:  rewriteIncorrectAndroidmkAndroidLibraries,
 	},
 	{
-		name: "rewriteTestModuleTypes",
-		fix:  rewriteTestModuleTypes,
+		Name: "rewriteTestModuleTypes",
+		Fix:  rewriteTestModuleTypes,
 	},
 	{
-		name: "rewriteAndroidmkJavaLibs",
-		fix:  rewriteAndroidmkJavaLibs,
+		Name: "rewriteAndroidmkJavaLibs",
+		Fix:  rewriteAndroidmkJavaLibs,
 	},
 	{
-		name: "rewriteJavaStaticLibs",
-		fix:  rewriteJavaStaticLibs,
+		Name: "rewriteJavaStaticLibs",
+		Fix:  rewriteJavaStaticLibs,
 	},
 	{
-		name: "rewritePrebuiltEtc",
-		fix:  rewriteAndroidmkPrebuiltEtc,
+		Name: "rewritePrebuiltEtc",
+		Fix:  rewriteAndroidmkPrebuiltEtc,
 	},
 	{
-		name: "mergeMatchingModuleProperties",
-		fix:  runPatchListMod(mergeMatchingModuleProperties),
+		Name: "mergeMatchingModuleProperties",
+		Fix:  runPatchListMod(mergeMatchingModuleProperties),
 	},
 	{
-		name: "reorderCommonProperties",
-		fix:  runPatchListMod(reorderCommonProperties),
+		Name: "reorderCommonProperties",
+		Fix:  runPatchListMod(reorderCommonProperties),
 	},
 	{
-		name: "removeTags",
-		fix:  runPatchListMod(removeTags),
+		Name: "removeTags",
+		Fix:  runPatchListMod(removeTags),
 	},
 	{
-		name: "rewriteAndroidTest",
-		fix:  rewriteAndroidTest,
+		Name: "rewriteAndroidTest",
+		Fix:  rewriteAndroidTest,
 	},
 	{
-		name: "rewriteAndroidAppImport",
-		fix:  rewriteAndroidAppImport,
+		Name: "rewriteAndroidAppImport",
+		Fix:  rewriteAndroidAppImport,
 	},
 }
 
@@ -113,8 +123,27 @@
 }
 
 func (r FixRequest) AddAll() (result FixRequest) {
-	result.steps = append([]fixStep(nil), r.steps...)
+	result.steps = append([]FixStep(nil), r.steps...)
 	result.steps = append(result.steps, fixSteps...)
+	for _, extension := range fixStepsExtensions {
+		result.steps = append(result.steps, extension.Steps...)
+	}
+	return result
+}
+
+func (r FixRequest) AddBase() (result FixRequest) {
+	result.steps = append([]FixStep(nil), r.steps...)
+	result.steps = append(result.steps, fixSteps...)
+	return result
+}
+
+func (r FixRequest) AddMatchingExtensions(pattern string) (result FixRequest) {
+	result.steps = append([]FixStep(nil), r.steps...)
+	for _, extension := range fixStepsExtensions {
+		if match, _ := filepath.Match(pattern, extension.Name); match {
+			result.steps = append(result.steps, extension.Steps...)
+		}
+	}
 	return result
 }
 
@@ -122,6 +151,10 @@
 	tree *parser.File
 }
 
+func (f Fixer) Tree() *parser.File {
+	return f.tree
+}
+
 func NewFixer(tree *parser.File) *Fixer {
 	fixer := &Fixer{tree}
 
@@ -198,7 +231,7 @@
 
 func (f *Fixer) fixTreeOnce(config FixRequest) error {
 	for _, fix := range config.steps {
-		err := fix.fix(f)
+		err := fix.Fix(f)
 		if err != nil {
 			return err
 		}
diff --git a/bpfix/cmd/bpfix.go b/bpfix/cmd-lib/bpfix.go
similarity index 97%
rename from bpfix/cmd/bpfix.go
rename to bpfix/cmd-lib/bpfix.go
index ccdae16..98122f2 100644
--- a/bpfix/cmd/bpfix.go
+++ b/bpfix/cmd-lib/bpfix.go
@@ -12,11 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// This file provides a command-line interface to bpfix
+// This file provides a bpfix command-line library
 
 // TODO(jeffrygaston) should this file be consolidated with bpfmt.go?
 
-package main
+package cmd
 
 import (
 	"bytes"
@@ -128,7 +128,7 @@
 	filepath.Walk(path, makeFileVisitor(fixRequest))
 }
 
-func main() {
+func Run() {
 	flag.Parse()
 
 	fixRequest := bpfix.NewFixRequest().AddAll()
diff --git a/bpfix/cmd/main.go b/bpfix/cmd/main.go
new file mode 100644
index 0000000..8ca16b4
--- /dev/null
+++ b/bpfix/cmd/main.go
@@ -0,0 +1,25 @@
+// 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.
+
+// This file provides a wrapper to the bpfix command-line library
+
+package main
+
+import (
+	"android/soong/bpfix/bpfix/cmd"
+)
+
+func main() {
+	cmd.Run()
+}
diff --git a/cc/cc.go b/cc/cc.go
index 2a75ba9..ce4f545 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -215,6 +215,10 @@
 	// Allows this module to use non-APEX version of libraries. Useful
 	// for building binaries that are started before APEXes are activated.
 	Bootstrap *bool
+
+	// Even if DeviceConfig().VndkUseCoreVariant() is set, this module must use vendor variant.
+	// see soong/cc/config/vndk.go
+	MustUseVendorVariant bool `blueprint:"mutated"`
 }
 
 type VendorProperties struct {
@@ -577,7 +581,7 @@
 
 func (c *Module) isLlndk(config android.Config) bool {
 	// Returns true for both LLNDK (public) and LLNDK-private libs.
-	return inList(c.Name(), *llndkLibraries(config))
+	return inList(c.BaseModuleName(), *llndkLibraries(config))
 }
 
 func (c *Module) isLlndkPublic(config android.Config) bool {
@@ -587,7 +591,7 @@
 
 func (c *Module) isVndkPrivate(config android.Config) bool {
 	// Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private.
-	return inList(c.Name(), *vndkPrivateLibraries(config))
+	return inList(c.BaseModuleName(), *vndkPrivateLibraries(config))
 }
 
 func (c *Module) isVndk() bool {
@@ -630,7 +634,7 @@
 }
 
 func (c *Module) mustUseVendorVariant() bool {
-	return c.isVndkSp() || inList(c.Name(), config.VndkMustUseVendorVariantList)
+	return c.isVndkSp() || c.Properties.MustUseVendorVariant
 }
 
 func (c *Module) getVndkExtendsModuleName() string {
@@ -2104,7 +2108,6 @@
 }
 
 func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
-	name := actx.ModuleName()
 	if c.useVndk() {
 		if lib, ok := c.linker.(*llndkStubDecorator); ok {
 			if Bool(lib.Properties.Vendor_available) {
@@ -2126,7 +2129,7 @@
 		// TODO(b/114741097): use the correct ndk stl once build errors have been fixed
 		//family, link := getNdkStlFamilyAndLinkType(c)
 		//return fmt.Sprintf("native:ndk:%s:%s", family, link)
-	} else if inList(name, *vndkUsingCoreVariantLibraries(actx.Config())) {
+	} else if actx.DeviceConfig().VndkUseCoreVariant() && !c.mustUseVendorVariant() {
 		return "native:platform_vndk"
 	} else {
 		return "native:platform"
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 0649c2d..8418ec7 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -264,6 +264,13 @@
 	}
 }
 
+func checkVndkOutput(t *testing.T, ctx *android.TestContext, output string, expected []string) {
+	t.Helper()
+	vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
+	actual := strings.FieldsFunc(strings.ReplaceAll(vndkSnapshot.Output(output).Args["content"], "\\n", "\n"), func(r rune) bool { return r == '\n' })
+	assertArrayString(t, actual, expected)
+}
+
 func TestVndk(t *testing.T) {
 	config := android.TestArchConfig(buildDir, nil)
 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -336,6 +343,69 @@
 	checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLib2ndPath, variant2nd)
 	checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLibPath, variant)
 	checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLib2ndPath, variant2nd)
+
+	checkVndkOutput(t, ctx, "vndk/llndk.libraries.txt", []string{"libc.so", "libdl.so", "libft2.so", "libm.so"})
+	checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk_private.so"})
+	checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{"libft2.so", "libvndk_private.so", "libvndk_sp_private.so"})
+	checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp.so", "libvndk_sp_private.so"})
+	checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", nil)
+	// merged & tagged & filtered-out(libclang_rt)
+	checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
+		"LLNDK: libc.so",
+		"LLNDK: libdl.so",
+		"LLNDK: libft2.so",
+		"LLNDK: libm.so",
+		"VNDK-SP: libc++.so",
+		"VNDK-SP: libvndk_sp.so",
+		"VNDK-SP: libvndk_sp_private.so",
+		"VNDK-core: libvndk.so",
+		"VNDK-core: libvndk_private.so",
+		"VNDK-private: libft2.so",
+		"VNDK-private: libvndk_private.so",
+		"VNDK-private: libvndk_sp_private.so",
+	})
+}
+
+func TestVndkUsingCoreVariant(t *testing.T) {
+	config := android.TestArchConfig(buildDir, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
+
+	setVndkMustUseVendorVariantListForTest(config, []string{"libvndk"})
+
+	ctx := testCcWithConfig(t, `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk2",
+			vendor_available: false,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+	`, config)
+
+	checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk2.so"})
+	checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{"libvndk2.so"})
 }
 
 func TestVndkDepError(t *testing.T) {
@@ -1366,9 +1436,9 @@
 	assertArrayString(t, *vndkSpLibraries(config),
 		[]string{"libc++", "libvndksp"})
 	assertArrayString(t, *llndkLibraries(config),
-		[]string{"libc", "libdl", "libllndk", "libllndkprivate", "libm"})
+		[]string{"libc", "libdl", "libft2", "libllndk", "libllndkprivate", "libm"})
 	assertArrayString(t, *vndkPrivateLibraries(config),
-		[]string{"libllndkprivate", "libvndkprivate"})
+		[]string{"libft2", "libllndkprivate", "libvndkprivate"})
 
 	vendorVariant27 := "android_arm64_armv8-a_vendor.27_shared"
 
diff --git a/cc/testing.go b/cc/testing.go
index 6fa6ea7..fafaeb0 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -145,6 +145,18 @@
 			symbol_file: "",
 		}
 		cc_library {
+			name: "libft2",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			recovery_available: true,
+		}
+		llndk_library {
+			name: "libft2",
+			symbol_file: "",
+			vendor_available: false,
+		}
+		cc_library {
 			name: "libc++_static",
 			no_libcrt: true,
 			nocrt: true,
diff --git a/cc/vndk.go b/cc/vndk.go
index 2c1856e..994c4d1 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -194,14 +194,16 @@
 }
 
 var (
-	vndkCoreLibrariesKey             = android.NewOnceKey("vndkCoreLibrarires")
-	vndkSpLibrariesKey               = android.NewOnceKey("vndkSpLibrarires")
-	llndkLibrariesKey                = android.NewOnceKey("llndkLibrarires")
-	vndkPrivateLibrariesKey          = android.NewOnceKey("vndkPrivateLibrarires")
-	vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibrarires")
-	modulePathsKey                   = android.NewOnceKey("modulePaths")
-	vndkSnapshotOutputsKey           = android.NewOnceKey("vndkSnapshotOutputs")
-	vndkLibrariesLock                sync.Mutex
+	vndkCoreLibrariesKey                = android.NewOnceKey("vndkCoreLibrarires")
+	vndkSpLibrariesKey                  = android.NewOnceKey("vndkSpLibrarires")
+	llndkLibrariesKey                   = android.NewOnceKey("llndkLibrarires")
+	vndkPrivateLibrariesKey             = android.NewOnceKey("vndkPrivateLibrarires")
+	vndkUsingCoreVariantLibrariesKey    = android.NewOnceKey("vndkUsingCoreVariantLibrarires")
+	modulePathsKey                      = android.NewOnceKey("modulePaths")
+	vndkSnapshotOutputsKey              = android.NewOnceKey("vndkSnapshotOutputs")
+	vndkMustUseVendorVariantListKey     = android.NewOnceKey("vndkMustUseVendorVariantListKey")
+	testVndkMustUseVendorVariantListKey = android.NewOnceKey("testVndkMustUseVendorVariantListKey")
+	vndkLibrariesLock                   sync.Mutex
 
 	headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
 )
@@ -248,6 +250,26 @@
 	}).(*android.RuleBuilderInstalls)
 }
 
+func vndkMustUseVendorVariantList(cfg android.Config) []string {
+	return cfg.Once(vndkMustUseVendorVariantListKey, func() interface{} {
+		override := cfg.Once(testVndkMustUseVendorVariantListKey, func() interface{} {
+			return []string(nil)
+		}).([]string)
+		if override != nil {
+			return override
+		}
+		return config.VndkMustUseVendorVariantList
+	}).([]string)
+}
+
+// test may call this to override global configuration(config.VndkMustUseVendorVariantList)
+// when it is called, it must be before the first call to vndkMustUseVendorVariantList()
+func setVndkMustUseVendorVariantListForTest(config android.Config, mustUseVendorVariantList []string) {
+	config.Once(testVndkMustUseVendorVariantListKey, func() interface{} {
+		return mustUseVendorVariantList
+	})
+}
+
 func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
 	lib := m.linker.(*llndkStubDecorator)
 	name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
@@ -276,7 +298,10 @@
 	defer vndkLibrariesLock.Unlock()
 
 	modulePaths := modulePaths(mctx.Config())
-	if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, config.VndkMustUseVendorVariantList) {
+	if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
+		m.Properties.MustUseVendorVariant = true
+	}
+	if mctx.DeviceConfig().VndkUseCoreVariant() && !m.mustUseVendorVariant() {
 		vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
 		if !inList(name, *vndkUsingCoreVariantLibraries) {
 			*vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
@@ -390,6 +415,8 @@
 		return
 	}
 
+	c.buildVndkLibrariesTxtFiles(ctx)
+
 	outputs := vndkSnapshotOutputs(ctx.Config())
 
 	snapshotDir := "vndk-snapshot"
@@ -629,3 +656,88 @@
 	installSnapshotFileFromContent(modulePathTxtBuilder.String(),
 		filepath.Join(configsDir, "module_paths.txt"))
 }
+
+func installListFile(ctx android.SingletonContext, list []string, pathComponents ...string) android.OutputPath {
+	out := android.PathForOutput(ctx, pathComponents...)
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Output:      out,
+		Description: "Writing " + out.String(),
+		Args: map[string]string{
+			"content": strings.Join(list, "\\n"),
+		},
+	})
+	return out
+}
+
+func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
+	var (
+		llndk, vndkcore, vndksp, vndkprivate, vndkcorevariant, merged []string
+	)
+	vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
+	config := ctx.Config()
+	ctx.VisitAllModules(func(m android.Module) {
+		if !m.Enabled() {
+			return
+		}
+		c, ok := m.(*Module)
+		if !ok || c.Os().Class != android.Device {
+			return
+		}
+		lib, ok := c.linker.(interface{ shared() bool })
+		if !ok || !lib.shared() {
+			return
+		}
+
+		if !c.OutputFile().Valid() {
+			return
+		}
+
+		filename := c.OutputFile().Path().Base()
+		if c.isLlndk(config) {
+			llndk = append(llndk, filename)
+			if c.isVndkPrivate(config) {
+				vndkprivate = append(vndkprivate, filename)
+			}
+		} else if c.vndkVersion() == vndkVersion && c.isVndk() && !c.isVndkExt() {
+			if c.isVndkSp() {
+				vndksp = append(vndksp, filename)
+			} else {
+				vndkcore = append(vndkcore, filename)
+			}
+			if c.isVndkPrivate(config) {
+				vndkprivate = append(vndkprivate, filename)
+			}
+			if ctx.DeviceConfig().VndkUseCoreVariant() && !c.mustUseVendorVariant() {
+				vndkcorevariant = append(vndkcorevariant, filename)
+			}
+		}
+	})
+	llndk = android.SortedUniqueStrings(llndk)
+	vndkcore = android.SortedUniqueStrings(vndkcore)
+	vndksp = android.SortedUniqueStrings(vndksp)
+	vndkprivate = android.SortedUniqueStrings(vndkprivate)
+	vndkcorevariant = android.SortedUniqueStrings(vndkcorevariant)
+
+	installListFile(ctx, llndk, "vndk", "llndk.libraries.txt")
+	installListFile(ctx, vndkcore, "vndk", "vndkcore.libraries.txt")
+	installListFile(ctx, vndksp, "vndk", "vndksp.libraries.txt")
+	installListFile(ctx, vndkprivate, "vndk", "vndkprivate.libraries.txt")
+	installListFile(ctx, vndkcorevariant, "vndk", "vndkcorevariant.libraries.txt")
+
+	// merged & tagged & filtered-out(libclang_rt)
+	filterOutLibClangRt := func(libList []string) (filtered []string) {
+		for _, lib := range libList {
+			if !strings.HasPrefix(lib, "libclang_rt.") {
+				filtered = append(filtered, lib)
+			}
+		}
+		return
+	}
+	merged = append(merged, addPrefix(filterOutLibClangRt(llndk), "LLNDK: ")...)
+	merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
+	merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
+	merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
+
+	installListFile(ctx, merged, "vndk", "vndk.libraries.txt")
+}
diff --git a/rust/OWNERS b/rust/OWNERS
new file mode 100644
index 0000000..82713f9
--- /dev/null
+++ b/rust/OWNERS
@@ -0,0 +1,5 @@
+# Additional owner/reviewers for rust rules, including parent directory owners.
+per-file * = chh@google.com, ivanlozano@google.com, jeffv@google.com, srhines@google.com
+
+# Limited owners/reviewers of the whitelist.
+per-file whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/rust/config/whitelist.go b/rust/config/whitelist.go
index 4646264..8025bcf 100644
--- a/rust/config/whitelist.go
+++ b/rust/config/whitelist.go
@@ -2,7 +2,7 @@
 
 var (
 	RustAllowedPaths = []string{
-		"external/rust/crates",
+		"external/rust",
 		"external/crosvm",
 		"external/adhd",
 	}