Merge "Drop "android.hidl.manager" -> "android.hidl.base" dependency from class loader context."
diff --git a/Android.bp b/Android.bp
index 3075d67..4d69877 100644
--- a/Android.bp
+++ b/Android.bp
@@ -47,6 +47,7 @@
     defaults: ["linux_bionic_supported"],
     vendor_available: true,
     ramdisk_available: true,
+    vendor_ramdisk_available: true,
     recovery_available: true,
     native_bridge_supported: true,
 
@@ -94,6 +95,7 @@
     defaults: ["linux_bionic_supported"],
     vendor_available: true,
     ramdisk_available: true,
+    vendor_ramdisk_available: true,
     recovery_available: true,
     native_bridge_supported: true,
     sdk_version: "current",
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 210d67a8..c87a945 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -29,10 +29,16 @@
 	"github.com/google/blueprint/bootstrap"
 )
 
+type CqueryRequestType int
+
+const (
+	getAllFiles CqueryRequestType = iota
+)
+
 // Map key to describe bazel cquery requests.
 type cqueryKey struct {
-	label        string
-	starlarkExpr string
+	label       string
+	requestType CqueryRequestType
 }
 
 type BazelContext interface {
@@ -61,6 +67,7 @@
 	bazelPath    string
 	outputBase   string
 	workspaceDir string
+	buildDir     string
 
 	requests     map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
 	requestMutex sync.Mutex         // requests can be written in parallel
@@ -96,8 +103,7 @@
 var _ BazelContext = MockBazelContext{}
 
 func (bazelCtx *bazelContext) GetAllFiles(label string) ([]string, bool) {
-	starlarkExpr := "', '.join([f.path for f in target.files.to_list()])"
-	result, ok := bazelCtx.cquery(label, starlarkExpr)
+	result, ok := bazelCtx.cquery(label, getAllFiles)
 	if ok {
 		bazelOutput := strings.TrimSpace(result)
 		return strings.Split(bazelOutput, ", "), true
@@ -119,11 +125,13 @@
 }
 
 func NewBazelContext(c *config) (BazelContext, error) {
-	if c.Getenv("USE_BAZEL") != "1" {
+	// TODO(cparsons): Assess USE_BAZEL=1 instead once "mixed Soong/Bazel builds"
+	// are production ready.
+	if c.Getenv("USE_BAZEL_ANALYSIS") != "1" {
 		return noopBazelContext{}, nil
 	}
 
-	bazelCtx := bazelContext{requests: make(map[cqueryKey]bool)}
+	bazelCtx := bazelContext{buildDir: c.buildDir, requests: make(map[cqueryKey]bool)}
 	missingEnvVars := []string{}
 	if len(c.Getenv("BAZEL_HOME")) > 1 {
 		bazelCtx.homeDir = c.Getenv("BAZEL_HOME")
@@ -161,8 +169,8 @@
 // If the given request was already made (and the results are available), then
 // returns (result, true). If the request is queued but no results are available,
 // then returns ("", false).
-func (context *bazelContext) cquery(label string, starlarkExpr string) (string, bool) {
-	key := cqueryKey{label, starlarkExpr}
+func (context *bazelContext) cquery(label string, requestType CqueryRequestType) (string, bool) {
+	key := cqueryKey{label, requestType}
 	if result, ok := context.results[key]; ok {
 		return result, true
 	} else {
@@ -184,7 +192,8 @@
 func (context *bazelContext) issueBazelCommand(command string, labels []string,
 	extraFlags ...string) (string, error) {
 
-	cmdFlags := []string{"--output_base=" + context.outputBase, command}
+	cmdFlags := []string{"--bazelrc=build/bazel/common.bazelrc",
+		"--output_base=" + context.outputBase, command}
 	cmdFlags = append(cmdFlags, labels...)
 	cmdFlags = append(cmdFlags, extraFlags...)
 
@@ -202,27 +211,113 @@
 	}
 }
 
+func (context *bazelContext) mainBzlFileContents() []byte {
+	contents := `
+# This file is generated by soong_build. Do not edit.
+def _mixed_build_root_impl(ctx):
+    return [DefaultInfo(files = depset(ctx.files.deps))]
+
+mixed_build_root = rule(
+    implementation = _mixed_build_root_impl,
+    attrs = {"deps" : attr.label_list()},
+)
+`
+	return []byte(contents)
+}
+
+func (context *bazelContext) mainBuildFileContents() []byte {
+	formatString := `
+# This file is generated by soong_build. Do not edit.
+load(":main.bzl", "mixed_build_root")
+
+mixed_build_root(name = "buildroot",
+    deps = [%s],
+)
+`
+	var buildRootDeps []string = nil
+	for val, _ := range context.requests {
+		buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\"", val.label))
+	}
+	buildRootDepsString := strings.Join(buildRootDeps, ",\n            ")
+
+	return []byte(fmt.Sprintf(formatString, buildRootDepsString))
+}
+
+func (context *bazelContext) cqueryStarlarkFileContents() []byte {
+	formatString := `
+# This file is generated by soong_build. Do not edit.
+getAllFilesLabels = {
+  %s
+}
+
+def format(target):
+  if str(target.label) in getAllFilesLabels:
+    return str(target.label) + ">>" + ', '.join([f.path for f in target.files.to_list()])
+  else:
+    # This target was not requested via cquery, and thus must be a dependency
+    # of a requested target.
+    return ""
+`
+	var buildRootDeps []string = nil
+	// TODO(cparsons): Sort by request type instead of assuming all requests
+	// are of GetAllFiles type.
+	for val, _ := range context.requests {
+		buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\" : True", val.label))
+	}
+	buildRootDepsString := strings.Join(buildRootDeps, ",\n  ")
+
+	return []byte(fmt.Sprintf(formatString, buildRootDepsString))
+}
+
 // Issues commands to Bazel to receive results for all cquery requests
 // queued in the BazelContext.
 func (context *bazelContext) InvokeBazel() error {
 	context.results = make(map[cqueryKey]string)
 
-	var labels []string
 	var cqueryOutput string
 	var err error
+	err = ioutil.WriteFile(
+		absolutePath(filepath.Join(context.buildDir, "main.bzl")),
+		context.mainBzlFileContents(), 0666)
+	if err != nil {
+		return err
+	}
+	err = ioutil.WriteFile(
+		absolutePath(filepath.Join(context.buildDir, "BUILD.bazel")),
+		context.mainBuildFileContents(), 0666)
+	if err != nil {
+		return err
+	}
+	cquery_file_relpath := filepath.Join(context.buildDir, "buildroot.cquery")
+	err = ioutil.WriteFile(
+		absolutePath(cquery_file_relpath),
+		context.cqueryStarlarkFileContents(), 0666)
+	if err != nil {
+		return err
+	}
+	buildroot_label := fmt.Sprintf("//%s:buildroot", context.buildDir)
+	cqueryOutput, err = context.issueBazelCommand("cquery",
+		[]string{fmt.Sprintf("deps(%s)", buildroot_label)},
+		"--output=starlark",
+		"--starlark:file="+cquery_file_relpath)
+
+	if err != nil {
+		return err
+	}
+
+	cqueryResults := map[string]string{}
+	for _, outputLine := range strings.Split(cqueryOutput, "\n") {
+		if strings.Contains(outputLine, ">>") {
+			splitLine := strings.SplitN(outputLine, ">>", 2)
+			cqueryResults[splitLine[0]] = splitLine[1]
+		}
+	}
+
 	for val, _ := range context.requests {
-		labels = append(labels, val.label)
-
-		// TODO(cparsons): Combine requests into a batch cquery request.
-		// TODO(cparsons): Use --query_file to avoid command line limits.
-		cqueryOutput, err = context.issueBazelCommand("cquery", []string{val.label},
-			"--output=starlark",
-			"--starlark:expr="+val.starlarkExpr)
-
-		if err != nil {
-			return err
+		if cqueryResult, ok := cqueryResults[val.label]; ok {
+			context.results[val] = string(cqueryResult)
 		} else {
-			context.results[val] = string(cqueryOutput)
+			return fmt.Errorf("missing result for bazel target %s", val.label)
 		}
 	}
 
@@ -231,7 +326,7 @@
 	// bazel actions should either be added to the Ninja file and executed later,
 	// or bazel should handle execution.
 	// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
-	_, err = context.issueBazelCommand("build", labels)
+	_, err = context.issueBazelCommand("build", []string{buildroot_label})
 
 	if err != nil {
 		return err
diff --git a/android/config.go b/android/config.go
index 5f1acf6..dbae7f7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1361,14 +1361,31 @@
 	return IndexList(jar, l.jars)
 }
 
+func copyAndAppend(list []string, item string) []string {
+	// Create the result list to be 1 longer than the input.
+	result := make([]string, len(list)+1)
+
+	// Copy the whole input list into the result.
+	count := copy(result, list)
+
+	// Insert the extra item at the end.
+	result[count] = item
+
+	return result
+}
+
 // Append an (apex, jar) pair to the list.
-func (l *ConfiguredJarList) Append(apex string, jar string) {
-	l.apexes = append(l.apexes, apex)
-	l.jars = append(l.jars, jar)
+func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList {
+	// Create a copy of the backing arrays before appending to avoid sharing backing
+	// arrays that are mutated across instances.
+	apexes := copyAndAppend(l.apexes, apex)
+	jars := copyAndAppend(l.jars, jar)
+
+	return ConfiguredJarList{apexes, jars}
 }
 
 // Filter out sublist.
-func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) {
+func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
 	apexes := make([]string, 0, l.Len())
 	jars := make([]string, 0, l.Len())
 
@@ -1380,13 +1397,7 @@
 		}
 	}
 
-	l.apexes = apexes
-	l.jars = jars
-}
-
-// A copy of itself.
-func (l *ConfiguredJarList) CopyOf() ConfiguredJarList {
-	return ConfiguredJarList{CopyOf(l.apexes), CopyOf(l.jars)}
+	return ConfiguredJarList{apexes, jars}
 }
 
 // A copy of the list of strings containing jar components.
@@ -1469,6 +1480,14 @@
 	return paths
 }
 
+func (l *ConfiguredJarList) String() string {
+	var pairs []string
+	for i := 0; i < l.Len(); i++ {
+		pairs = append(pairs, l.apexes[i]+":"+l.jars[i])
+	}
+	return strings.Join(pairs, ",")
+}
+
 func splitListOfPairsIntoPairOfLists(list []string) ([]string, []string, error) {
 	// Now we need to populate this list by splitting each item in the slice of
 	// pairs and appending them to the appropriate list of apexes or jars.
@@ -1497,10 +1516,10 @@
 	}
 }
 
-func CreateConfiguredJarList(ctx PathContext, list []string) ConfiguredJarList {
+func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
 	apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
 	if err != nil {
-		ReportPathErrorf(ctx, "%s", err)
+		panic(err)
 	}
 
 	return ConfiguredJarList{apexes, jars}
diff --git a/android/config_test.go b/android/config_test.go
index 274d59f..68f68a0 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -91,3 +91,49 @@
 		t.Errorf("Expected false")
 	}
 }
+
+func assertStringEquals(t *testing.T, expected, actual string) {
+	if actual != expected {
+		t.Errorf("expected %q found %q", expected, actual)
+	}
+}
+
+func TestConfiguredJarList(t *testing.T) {
+	list1 := CreateTestConfiguredJarList([]string{"apex1:jarA"})
+
+	t.Run("create", func(t *testing.T) {
+		assertStringEquals(t, "apex1:jarA", list1.String())
+	})
+
+	list2 := list1.Append("apex2", "jarB")
+	t.Run("append", func(t *testing.T) {
+		assertStringEquals(t, "apex1:jarA,apex2:jarB", list2.String())
+	})
+
+	t.Run("append does not modify", func(t *testing.T) {
+		assertStringEquals(t, "apex1:jarA", list1.String())
+	})
+
+	// Make sure that two lists created by appending to the same list do not share storage.
+	list3 := list1.Append("apex3", "jarC")
+	t.Run("append does not share", func(t *testing.T) {
+		assertStringEquals(t, "apex1:jarA,apex2:jarB", list2.String())
+		assertStringEquals(t, "apex1:jarA,apex3:jarC", list3.String())
+	})
+
+	list4 := list3.RemoveList(list1)
+	t.Run("remove", func(t *testing.T) {
+		assertStringEquals(t, "apex3:jarC", list4.String())
+	})
+
+	t.Run("remove does not modify", func(t *testing.T) {
+		assertStringEquals(t, "apex1:jarA,apex3:jarC", list3.String())
+	})
+
+	// Make sure that two lists created by removing from the same list do not share storage.
+	list5 := list3.RemoveList(CreateTestConfiguredJarList([]string{"apex3:jarC"}))
+	t.Run("remove", func(t *testing.T) {
+		assertStringEquals(t, "apex3:jarC", list4.String())
+		assertStringEquals(t, "apex1:jarA", list5.String())
+	})
+}
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index c7223c4..b3cf8d5 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -419,7 +419,9 @@
 ndk_crtend_so.21(minSdkVersion:(no version))
 ndk_crtend_so.27(minSdkVersion:(no version))
 ndk_libc++_static(minSdkVersion:(no version))
+ndk_libc++_static(minSdkVersion:16)
 ndk_libc++abi(minSdkVersion:(no version))
+ndk_libc++abi(minSdkVersion:16)
 net-utils-framework-common(minSdkVersion:current)
 netd_aidl_interface-unstable-java(minSdkVersion:29)
 netd_event_listener_interface-ndk_platform(minSdkVersion:29)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f400936..7e83070 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5791,12 +5791,9 @@
 	var err string
 	var transform func(*dexpreopt.GlobalConfig)
 
-	config := android.TestArchConfig(buildDir, nil, "", nil)
-	ctx := android.PathContextForTesting(config)
-
 	t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"})
+			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"com.android.art.something:some-art-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, "", transform)
 	})
@@ -5804,7 +5801,7 @@
 	t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
 		err = `module "some-art-lib" from updatable apexes \["com.android.art.something"\] is not allowed in the framework boot image`
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"})
+			config.BootJars = android.CreateTestConfiguredJarList([]string{"com.android.art.something:some-art-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, err, transform)
 	})
@@ -5812,7 +5809,7 @@
 	t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
 		err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image`
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"})
+			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"some-updatable-apex:some-updatable-apex-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, err, transform)
 	})
@@ -5820,7 +5817,7 @@
 	t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
 		err = `module "some-non-updatable-apex-lib" is not allowed in the ART boot image`
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
+			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, err, transform)
 	})
@@ -5828,14 +5825,14 @@
 	t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
 		err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"})
+			config.BootJars = android.CreateTestConfiguredJarList([]string{"some-updatable-apex:some-updatable-apex-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, err, transform)
 	})
 
 	t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
+			config.BootJars = android.CreateTestConfiguredJarList([]string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, "", transform)
 	})
@@ -5843,7 +5840,7 @@
 	t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
 		err = "failed to find a dex jar path for module 'nonexistent'"
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"})
+			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"platform:nonexistent"})
 		}
 		testNoUpdatableJarsInBootImage(t, err, transform)
 	})
@@ -5851,7 +5848,7 @@
 	t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
 		err = "failed to find a dex jar path for module 'nonexistent'"
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"})
+			config.BootJars = android.CreateTestConfiguredJarList([]string{"platform:nonexistent"})
 		}
 		testNoUpdatableJarsInBootImage(t, err, transform)
 	})
@@ -5859,14 +5856,14 @@
 	t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
 		err = `module "some-platform-lib" is not allowed in the ART boot image`
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"})
+			config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"platform:some-platform-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, err, transform)
 	})
 
 	t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
 		transform = func(config *dexpreopt.GlobalConfig) {
-			config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"})
+			config.BootJars = android.CreateTestConfiguredJarList([]string{"platform:some-platform-lib"})
 		}
 		testNoUpdatableJarsInBootImage(t, "", transform)
 	})
@@ -5905,7 +5902,7 @@
 	for _, apexBootJar := range apexBootJars {
 		updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar)
 	}
-	config.TestProductVariables.UpdatableBootJars = android.CreateConfiguredJarList(nil, updatableBootJars)
+	config.TestProductVariables.UpdatableBootJars = android.CreateTestConfiguredJarList(updatableBootJars)
 
 	ctx.Register(config)
 
diff --git a/bazel/bazelenv.sh b/bazel/bazelenv.sh
index 2ca8baf..fcf71f1 100755
--- a/bazel/bazelenv.sh
+++ b/bazel/bazelenv.sh
@@ -59,12 +59,16 @@
     export BAZEL_PATH="$(which bazel)"
 fi
 
-export USE_BAZEL=1
+# TODO(cparsons): Use USE_BAZEL=1 instead once "mixed Soong/Bazel builds" are
+# production ready.
+export USE_BAZEL_ANALYSIS=1
+# TODO(cparsons): Retrieve this information in either envsetup.sh or 
+# bazel.sh.
 export BAZEL_HOME="$BASE_DIR/bazelhome"
 export BAZEL_OUTPUT_BASE="$BASE_DIR/output"
 export BAZEL_WORKSPACE="$(gettop)"
 
-echo "USE_BAZEL=${USE_BAZEL}"
+echo "USE_BAZEL_ANALYSIS=${USE_BAZEL_ANALYSIS}"
 echo "BAZEL_PATH=${BAZEL_PATH}"
 echo "BAZEL_HOME=${BAZEL_HOME}"
 echo "BAZEL_OUTPUT_BASE=${BAZEL_OUTPUT_BASE}"
diff --git a/build_test.bash b/build_test.bash
index ee979e7..a53a585 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -43,5 +43,16 @@
     ;;
 esac
 
+function bazel_cleanup {
+  "${TOP}/tools/bazel" shutdown
+}
+trap bazel_cleanup EXIT
+
+echo
+echo "Running Bazel smoke test..."
+"${TOP}/tools/bazel" info
+
+echo
+echo "Running Soong test..."
 soong_build_go multiproduct_kati android/soong/cmd/multiproduct_kati
 exec "$(getoutdir)/multiproduct_kati" "$@"
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 91eb886..38269cb 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -487,9 +487,21 @@
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		c.libraryDecorator.androidMkWriteExportedFlags(entries)
 
+		// Specifying stem is to pass check_elf_files when vendor modules link against vndk prebuilt.
+		// We can't use install path because VNDKs are not installed. Instead, Srcs is directly used.
+		_, file := filepath.Split(c.properties.Srcs[0])
+		stem, suffix, ext := android.SplitFileExt(file)
+		entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
+		entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
+		entries.SetString("LOCAL_MODULE_STEM", stem)
+
 		if c.tocFile.Valid() {
 			entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String())
 		}
+
+		// VNDK libraries available to vendor are not installed because
+		// they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go)
+		entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
 	})
 }
 
diff --git a/cc/cc.go b/cc/cc.go
index c93bdeb..3b01fb2 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3085,6 +3085,12 @@
 	}
 }
 
+func squashVendorRamdiskSrcs(m *Module) {
+	if lib, ok := m.compiler.(*libraryDecorator); ok {
+		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...)
+	}
+}
+
 func (c *Module) IsSdkVariant() bool {
 	return c.Properties.IsSdkVariant || c.AlwaysSdk()
 }
diff --git a/cc/compiler.go b/cc/compiler.go
index 21da2fc..e2a33d7 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -177,6 +177,15 @@
 			// build the recovery variant of the C/C++ module.
 			Exclude_generated_sources []string
 		}
+		Vendor_ramdisk struct {
+			// list of source files that should not be used to
+			// build the vendor ramdisk variant of the C/C++ module.
+			Exclude_srcs []string `android:"path"`
+
+			// List of additional cflags that should be used to build the vendor ramdisk
+			// variant of the C/C++ module.
+			Cflags []string
+		}
 	}
 
 	Proto struct {
@@ -290,6 +299,7 @@
 	CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
 	CheckBadCompilerFlags(ctx, "vendor.cflags", compiler.Properties.Target.Vendor.Cflags)
 	CheckBadCompilerFlags(ctx, "recovery.cflags", compiler.Properties.Target.Recovery.Cflags)
+	CheckBadCompilerFlags(ctx, "vendor_ramdisk.cflags", compiler.Properties.Target.Vendor_ramdisk.Cflags)
 
 	esc := proptools.NinjaAndShellEscapeList
 
@@ -471,6 +481,10 @@
 		flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Recovery.Cflags)...)
 	}
 
+	if ctx.inVendorRamdisk() {
+		flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Vendor_ramdisk.Cflags)...)
+	}
+
 	// We can enforce some rules more strictly in the code we own. strict
 	// indicates if this is code that we can be stricter with. If we have
 	// rules that we want to apply to *our* code (but maybe can't for
diff --git a/cc/image.go b/cc/image.go
index ba091e1..7b9425f 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -353,8 +353,11 @@
 
 func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
 	m := module.(*Module)
-	if variant == android.RamdiskVariation || variant == android.VendorRamdiskVariation {
+	if variant == android.RamdiskVariation {
 		m.MakeAsPlatform()
+	} else if variant == android.VendorRamdiskVariation {
+		m.MakeAsPlatform()
+		squashVendorRamdiskSrcs(m)
 	} else if variant == android.RecoveryVariation {
 		m.MakeAsPlatform()
 		squashRecoverySrcs(m)
diff --git a/cc/library.go b/cc/library.go
index 0e0f143..910fc31 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -833,6 +833,13 @@
 		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Ramdisk.Exclude_shared_libs)
 		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Ramdisk.Exclude_static_libs)
 	}
+	if ctx.inVendorRamdisk() {
+		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+		deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+		deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+	}
 
 	return deps
 }
diff --git a/cc/linker.go b/cc/linker.go
index 12c8b2c..7f13e28 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -158,6 +158,15 @@
 			// the ramdisk variant of the C/C++ module.
 			Exclude_static_libs []string
 		}
+		Vendor_ramdisk struct {
+			// list of shared libs that should not be used to build
+			// the recovery variant of the C/C++ module.
+			Exclude_shared_libs []string
+
+			// list of static libs that should not be used to build
+			// the vendor ramdisk variant of the C/C++ module.
+			Exclude_static_libs []string
+		}
 		Platform struct {
 			// list of shared libs that should be use to build the platform variant
 			// of a module that sets sdk_version.  This should rarely be necessary,
@@ -259,12 +268,20 @@
 	}
 
 	if ctx.inRamdisk() {
-		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
-		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs)
-		deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Recovery.Static_libs...)
-		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
-		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
-		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
+		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Ramdisk.Exclude_shared_libs)
+		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Ramdisk.Exclude_shared_libs)
+		deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Ramdisk.Static_libs...)
+		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Ramdisk.Exclude_static_libs)
+		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Ramdisk.Exclude_static_libs)
+		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Ramdisk.Exclude_static_libs)
+	}
+
+	if ctx.inVendorRamdisk() {
+		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor_ramdisk.Exclude_shared_libs)
+		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
 	}
 
 	if !ctx.useSdk() {
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 82a7732..dddd5ac 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -232,6 +232,14 @@
 		&prebuilt.properties,
 	)
 
+	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+		// empty BOARD_VNDK_VERSION implies that the device won't support
+		// system only OTA. In this case, VNDK snapshots aren't needed.
+		if ctx.DeviceConfig().VndkVersion() == "" {
+			ctx.Module().Disable()
+		}
+	})
+
 	return module
 }
 
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 47110c9..ab31958 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -48,7 +48,7 @@
 
 	pathCtx := android.PathContextForTesting(config)
 	dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
-	dexpreoptConfig.BootJars = android.CreateConfiguredJarList(pathCtx, []string{"platform:foo", "platform:bar", "platform:baz"})
+	dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList([]string{"platform:foo", "platform:bar", "platform:baz"})
 	dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
 
 	ctx := testContext()
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 0f8888a..c315124 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -81,13 +81,12 @@
 		targets := dexpreoptTargets(ctx)
 		deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
 
-		artModules := global.ArtApexJars.CopyOf()
+		artModules := global.ArtApexJars
 		// With EMMA_INSTRUMENT_FRAMEWORK=true the Core libraries depend on jacoco.
 		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
-			artModules.Append("com.android.art", "jacocoagent")
+			artModules = artModules.Append("com.android.art", "jacocoagent")
 		}
-		frameworkModules := global.BootJars.CopyOf()
-		frameworkModules.RemoveList(artModules)
+		frameworkModules := global.BootJars.RemoveList(artModules)
 
 		artSubdir := "apex/art_boot_images/javalib"
 		frameworkSubdir := "system/framework"
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 0c223d9..7acaae7 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -25,7 +25,7 @@
 
 func testConfigWithBootJars(bp string, bootJars []string) android.Config {
 	config := testConfig(nil, bp, nil)
-	config.TestProductVariables.BootJars = android.CreateConfiguredJarList(nil, bootJars)
+	config.TestProductVariables.BootJars = android.CreateTestConfiguredJarList(bootJars)
 	return config
 }