Merge "Allowlist //build/soong/cc/{ndkstubgen,symbolfile}."
diff --git a/android/module.go b/android/module.go
index 767f9f4..b500f01 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1300,6 +1300,8 @@
 
 func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
 
+// AddProperties "registers" the provided props
+// each value in props MUST be a pointer to a struct
 func (m *ModuleBase) AddProperties(props ...interface{}) {
 	m.registerProps = append(m.registerProps, props...)
 }
diff --git a/android/mutator.go b/android/mutator.go
index 461cb17..0a93517 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -529,28 +529,6 @@
 	mod.base().addBp2buildInfo(info)
 }
 
-func (t *topDownMutatorContext) appendPrependHelper(props []interface{},
-	extendFn func([]interface{}, interface{}, proptools.ExtendPropertyFilterFunc) error) {
-	for _, p := range props {
-		err := extendFn(t.Module().base().customizableProperties, p, nil)
-		if err != nil {
-			if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
-				t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
-			} else {
-				panic(err)
-			}
-		}
-	}
-}
-
-func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
-	t.appendPrependHelper(props, proptools.AppendMatchingProperties)
-}
-
-func (t *topDownMutatorContext) PrependProperties(props ...interface{}) {
-	t.appendPrependHelper(props, proptools.PrependMatchingProperties)
-}
-
 // android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
 // has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
 // ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
diff --git a/apex/apex.go b/apex/apex.go
index 75cff7d..25b1568 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -130,6 +130,13 @@
 	// symlinking to the system libs. Default is true.
 	Updatable *bool
 
+	// Marks that this APEX is designed to be updatable in the future, although it's not
+	// updatable yet. This is used to mimic some of the build behaviors that are applied only to
+	// updatable APEXes. Currently, this disables the size optimization, so that the size of
+	// APEX will not increase when the APEX is actually marked as truly updatable. Default is
+	// false.
+	Future_updatable *bool
+
 	// Whether this APEX can use platform APIs or not. Can be set to true only when `updatable:
 	// false`. Default is false.
 	Platform_apis *bool
@@ -1306,6 +1313,10 @@
 	return proptools.BoolDefault(a.properties.Updatable, true)
 }
 
+func (a *apexBundle) FutureUpdatable() bool {
+	return proptools.BoolDefault(a.properties.Future_updatable, false)
+}
+
 func (a *apexBundle) UsePlatformApis() bool {
 	return proptools.BoolDefault(a.properties.Platform_apis, false)
 }
@@ -2105,10 +2116,11 @@
 	}
 
 	forced := ctx.Config().ForceApexSymlinkOptimization()
+	updatable := a.Updatable() || a.FutureUpdatable()
 
 	// We don't need the optimization for updatable APEXes, as it might give false signal
 	// to the system health when the APEXes are still bundled (b/149805758).
-	if !forced && a.Updatable() && a.properties.ApexType == imageApex {
+	if !forced && updatable && a.properties.ApexType == imageApex {
 		a.linkToSystemLib = false
 	}
 
@@ -2377,6 +2389,12 @@
 		if a.UsePlatformApis() {
 			ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs")
 		}
+		if a.SocSpecific() || a.DeviceSpecific() {
+			ctx.PropertyErrorf("updatable", "vendor APEXes are not updatable")
+		}
+		if a.FutureUpdatable() {
+			ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`")
+		}
 		a.checkJavaStableSdkVersion(ctx)
 		a.checkClasspathFragments(ctx)
 	}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e2ca234..b805cd9 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7075,6 +7075,23 @@
 	`)
 }
 
+func TestUpdatable_cannot_be_vendor_apex(t *testing.T) {
+	testApexError(t, `"myapex" .*: updatable: vendor APEXes are not updatable`, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			updatable: true,
+			soc_specific: true,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+	`)
+}
+
 func TestUpdatable_should_not_set_generate_classpaths_proto(t *testing.T) {
 	testApexError(t, `"mysystemserverclasspathfragment" .* it must not set generate_classpaths_proto to false`, `
 		apex {
diff --git a/cc/builder.go b/cc/builder.go
index 72c2fa5..fea65d5 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -549,6 +549,10 @@
 		return "$" + kind + n
 	}
 
+	// clang-tidy checks source files and does not need to link with libraries.
+	// tidyPathDeps should contain pathDeps but not libraries.
+	tidyPathDeps := skipNdkLibraryDeps(ctx, pathDeps)
+
 	for i, srcFile := range srcFiles {
 		objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
 
@@ -672,7 +676,7 @@
 				Output:      tidyFile,
 				Input:       srcFile,
 				Implicits:   cFlagsDeps,
-				OrderOnly:   pathDeps,
+				OrderOnly:   tidyPathDeps,
 				Args: map[string]string{
 					"ccCmd":     ccCmd,
 					"cFlags":    shareFlags("cFlags", escapeSingleQuotes(moduleToolingFlags)),
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index fd458d9..ee11db1 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -82,12 +82,33 @@
 	return android.PathForOutput(ctx, "ndk_base.timestamp")
 }
 
+// The headers timestamp file depends only on the NDK headers.
+// This is used mainly for .tidy files that do not need any stub libraries.
+func getNdkHeadersTimestampFile(ctx android.PathContext) android.WritablePath {
+	return android.PathForOutput(ctx, "ndk_headers.timestamp")
+}
+
 // The full timestamp file depends on the base timestamp *and* the static
 // libraries.
 func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath {
 	return android.PathForOutput(ctx, "ndk.timestamp")
 }
 
+// Replace ndk_base.timestamp and ndk.timestamp with ndk_headers.timestamp.
+func skipNdkLibraryDeps(ctx android.ModuleContext, paths android.Paths) android.Paths {
+	var newPaths android.Paths
+	baseTimestamp := getNdkBaseTimestampFile(ctx)
+	fullTimestamp := getNdkFullTimestampFile(ctx)
+	headersTimestamp := getNdkHeadersTimestampFile(ctx)
+	for _, path := range paths {
+		if path == baseTimestamp || path == fullTimestamp {
+			path = headersTimestamp
+		}
+		newPaths = append(newPaths, path)
+	}
+	return newPaths
+}
+
 func NdkSingleton() android.Singleton {
 	return &ndkSingleton{}
 }
@@ -96,6 +117,7 @@
 
 func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 	var staticLibInstallPaths android.Paths
+	var headerPaths android.Paths
 	var installPaths android.Paths
 	var licensePaths android.Paths
 	ctx.VisitAllModules(func(module android.Module) {
@@ -104,16 +126,19 @@
 		}
 
 		if m, ok := module.(*headerModule); ok {
+			headerPaths = append(headerPaths, m.installPaths...)
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
 
 		if m, ok := module.(*versionedHeaderModule); ok {
+			headerPaths = append(headerPaths, m.installPaths...)
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
 
 		if m, ok := module.(*preprocessedHeadersModule); ok {
+			headerPaths = append(headerPaths, m.installPaths...)
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
@@ -153,6 +178,12 @@
 		Validation: getNdkAbiDiffTimestampFile(ctx),
 	})
 
+	ctx.Build(pctx, android.BuildParams{
+		Rule:      android.Touch,
+		Output:    getNdkHeadersTimestampFile(ctx),
+		Implicits: headerPaths,
+	})
+
 	fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
 
 	// There's a phony "ndk" rule defined in core/main.mk that depends on this.
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index dfc4eae..c81d4bc 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -386,7 +386,7 @@
 // - won't be overwritten by corresponding bp2build generated files
 //
 // And return their paths so they can be left out of the Bazel workspace dir (i.e. ignored)
-func getPathsToIgnoredBuildFiles(topDir string, generatedRoot string, srcDirBazelFiles []string) []string {
+func getPathsToIgnoredBuildFiles(topDir string, generatedRoot string, srcDirBazelFiles []string, verbose bool) []string {
 	paths := make([]string, 0)
 
 	for _, srcDirBazelFileRelativePath := range srcDirBazelFiles {
@@ -416,7 +416,9 @@
 			// BUILD file clash resolution happens later in the symlink forest creation
 			continue
 		}
-		fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", srcDirBazelFileRelativePath)
+		if verbose {
+			fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", srcDirBazelFileRelativePath)
+		}
 		paths = append(paths, srcDirBazelFileRelativePath)
 	}
 
@@ -523,7 +525,7 @@
 		os.Exit(1)
 	}
 
-	pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(topDir, generatedRoot, existingBazelRelatedFiles)
+	pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(topDir, generatedRoot, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
 	excludes = append(excludes, pathsToIgnoredBuildFiles...)
 
 	excludes = append(excludes, getTemporaryExcludes()...)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 38065f1..3a1f5fc 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -42,6 +43,20 @@
 	},
 	"args", "libs")
 
+// targetSdkVersion for manifest_fixer
+// When TARGET_BUILD_APPS is not empty, this method returns the unreleased(future) API level
+// This enables release builds (that run with TARGET_BUILD_APPS=[val...]) to target APIs that have not yet been finalized as part of an SDK
+func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext android.SdkContext) string {
+	if ctx.Config().UnbundledBuildApps() {
+		return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt())
+	}
+	targetSdkVersion, err := sdkContext.TargetSdkVersion(ctx).EffectiveVersionString(ctx)
+	if err != nil {
+		ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
+	}
+	return targetSdkVersion
+}
+
 // Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
 func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext android.SdkContext,
 	classLoaderContexts dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
@@ -89,10 +104,7 @@
 		args = append(args, "--logging-parent", loggingParent)
 	}
 	var deps android.Paths
-	targetSdkVersion, err := sdkContext.TargetSdkVersion(ctx).EffectiveVersionString(ctx)
-	if err != nil {
-		ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
-	}
+	targetSdkVersion := targetSdkVersionForManifestFixer(ctx, sdkContext)
 	if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
 		targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
 		deps = append(deps, ApiFingerprintPath(ctx))
diff --git a/mk2rbc/Android.bp b/mk2rbc/Android.bp
index b18bfc7..4fa3eb6 100644
--- a/mk2rbc/Android.bp
+++ b/mk2rbc/Android.bp
@@ -38,7 +38,6 @@
         "soong_variables.go",
         "types.go",
         "variable.go",
-        "version_defaults.go",
     ],
     deps: ["androidmk-parser"],
 }
diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go
index bb5a680..d9b4e86 100644
--- a/mk2rbc/cmd/mk2rbc.go
+++ b/mk2rbc/cmd/mk2rbc.go
@@ -80,7 +80,6 @@
 var tracedVariables []string
 var errorLogger = errorSink{data: make(map[string]datum)}
 var makefileFinder = &LinuxMakefileFinder{}
-var versionDefaultsMk = filepath.Join("build", "make", "core", "version_defaults.mk")
 
 func main() {
 	flag.Usage = func() {
@@ -168,18 +167,14 @@
 		if len(files) != 1 {
 			quit(fmt.Errorf("a launcher can be generated only for a single product"))
 		}
-		versionDefaults, err := generateVersionDefaults()
-		if err != nil {
-			quit(err)
+		if *inputVariables == "" {
+			quit(fmt.Errorf("the product launcher requires an input variables file"))
 		}
-		versionDefaultsPath := outputFilePath(versionDefaultsMk)
-		err = writeGenerated(versionDefaultsPath, versionDefaults)
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "%s: %s", files[0], err)
-			ok = false
+		if !convertOne(*inputVariables) {
+			quit(fmt.Errorf("the product launcher input variables file failed to convert"))
 		}
 
-		err = writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(files[0]), versionDefaultsPath,
+		err := writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(files[0]), outputFilePath(*inputVariables),
 			mk2rbc.MakePath2ModuleName(files[0])))
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "%s: %s", files[0], err)
@@ -213,15 +208,6 @@
 	}
 }
 
-func generateVersionDefaults() (string, error) {
-	versionSettings, err := mk2rbc.ParseVersionDefaults(filepath.Join(*rootDir, versionDefaultsMk))
-	if err != nil {
-		return "", err
-	}
-	return mk2rbc.VersionDefaults(versionSettings), nil
-
-}
-
 func quit(s interface{}) {
 	fmt.Fprintln(os.Stderr, s)
 	os.Exit(2)
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 4b9779c..15e5963 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -1695,12 +1695,12 @@
 	return starScript, nil
 }
 
-func Launcher(mainModuleUri, versionDefaultsUri, mainModuleName string) string {
+func Launcher(mainModuleUri, inputVariablesUri, mainModuleName string) string {
 	var buf bytes.Buffer
 	fmt.Fprintf(&buf, "load(%q, %q)\n", baseUri, baseName)
-	fmt.Fprintf(&buf, "load(%q, \"version_defaults\")\n", versionDefaultsUri)
+	fmt.Fprintf(&buf, "load(%q, input_variables_init = \"init\")\n", inputVariablesUri)
 	fmt.Fprintf(&buf, "load(%q, \"init\")\n", mainModuleUri)
-	fmt.Fprintf(&buf, "%s(%s(%q, init, version_defaults))\n", cfnPrintVars, cfnMain, mainModuleName)
+	fmt.Fprintf(&buf, "%s(%s(%q, init, input_variables_init))\n", cfnPrintVars, cfnMain, mainModuleName)
 	return buf.String()
 }
 
diff --git a/mk2rbc/version_defaults.go b/mk2rbc/version_defaults.go
deleted file mode 100644
index 64645d7..0000000
--- a/mk2rbc/version_defaults.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// 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 mk2rbc
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"sort"
-	"strconv"
-	"strings"
-
-	mkparser "android/soong/androidmk/parser"
-)
-
-const codenamePrefix = "PLATFORM_VERSION_CODENAME."
-
-// ParseVersionDefaults extracts version settings from the given file
-// and returns the map.
-func ParseVersionDefaults(path string) (map[string]string, error) {
-	contents, err := ioutil.ReadFile(path)
-	if err != nil {
-		return nil, err
-	}
-	parser := mkparser.NewParser(path, bytes.NewBuffer(contents))
-	nodes, errs := parser.Parse()
-	if len(errs) > 0 {
-		for _, e := range errs {
-			fmt.Fprintln(os.Stderr, "ERROR:", e)
-		}
-		return nil, fmt.Errorf("cannot parse %s", path)
-	}
-
-	result := map[string]string{
-		"DEFAULT_PLATFORM_VERSION":            "",
-		"MAX_PLATFORM_VERSION":                "",
-		"MIN_PLATFORM_VERSION":                "A",
-		"PLATFORM_BASE_SDK_EXTENSION_VERSION": "",
-		"PLATFORM_SDK_EXTENSION_VERSION":      "",
-		"PLATFORM_SDK_VERSION":                "",
-		"PLATFORM_SECURITY_PATCH":             "",
-		"PLATFORM_VERSION_LAST_STABLE":        "",
-	}
-	for _, node := range nodes {
-		asgn, ok := node.(*mkparser.Assignment)
-		if !(ok && asgn.Name.Const()) {
-			continue
-		}
-		s := asgn.Name.Strings[0]
-		_, ok = result[s]
-		if !ok {
-			ok = strings.HasPrefix(s, codenamePrefix)
-		}
-		if !ok {
-			continue
-		}
-		v := asgn.Value
-		if !v.Const() {
-			return nil, fmt.Errorf("the value of %s should be constant", s)
-		}
-		result[s] = strings.TrimSpace(v.Strings[0])
-	}
-	return result, nil
-}
-
-func genericValue(s string) interface{} {
-	if ival, err := strconv.ParseInt(s, 0, 0); err == nil {
-		return ival
-	}
-	return s
-}
-
-// VersionDefaults generates the contents of the version_defaults.rbc file
-func VersionDefaults(values map[string]string) string {
-	var sink bytes.Buffer
-	var lines []string
-	var codenames []string
-	for name, value := range values {
-		if strings.HasPrefix(name, codenamePrefix) {
-			codenames = append(codenames,
-				fmt.Sprintf("%q: %q", strings.TrimPrefix(name, codenamePrefix), value))
-		} else {
-			// Print numbers as such
-			lines = append(lines, fmt.Sprintf("    %s = %#v,\n",
-				strings.ToLower(name), genericValue(value)))
-		}
-	}
-
-	sort.Strings(lines)
-	sort.Strings(codenames)
-
-	sink.WriteString("version_defaults = struct(\n")
-	for _, l := range lines {
-		sink.WriteString(l)
-	}
-	sink.WriteString("    codenames = { ")
-	sink.WriteString(strings.Join(codenames, ", "))
-	sink.WriteString(" }\n)\n")
-	return sink.String()
-}
diff --git a/mk2rbc/version_defaults_test.go b/mk2rbc/version_defaults_test.go
deleted file mode 100644
index c78fa32..0000000
--- a/mk2rbc/version_defaults_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package mk2rbc
-
-import (
-	"path/filepath"
-	"reflect"
-	"strings"
-	"testing"
-)
-
-func TestParseVersionDefaults(t *testing.T) {
-	testDir := getTestDirectory()
-	abspath := func(relPath string) string { return filepath.Join(testDir, relPath) }
-	actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	expectedProducts := map[string]string{
-		"DEFAULT_PLATFORM_VERSION":            "TP1A",
-		"MAX_PLATFORM_VERSION":                "TP1A",
-		"MIN_PLATFORM_VERSION":                "TP1A",
-		"PLATFORM_BASE_SDK_EXTENSION_VERSION": "0",
-		"PLATFORM_SDK_EXTENSION_VERSION":      "1",
-		"PLATFORM_SDK_VERSION":                "31",
-		"PLATFORM_SECURITY_PATCH":             "2021-10-05",
-		"PLATFORM_VERSION_LAST_STABLE":        "12",
-		"PLATFORM_VERSION_CODENAME.SP2A":      "Sv2",
-		"PLATFORM_VERSION_CODENAME.TP1A":      "Tiramisu",
-	}
-	if !reflect.DeepEqual(actualProducts, expectedProducts) {
-		t.Errorf("\nExpected: %v\n  Actual: %v", expectedProducts, actualProducts)
-	}
-}
-
-func TestVersionDefaults(t *testing.T) {
-	testDir := getTestDirectory()
-	abspath := func(relPath string) string { return filepath.Join(testDir, relPath) }
-	actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	expectedString := `version_defaults = struct(
-    default_platform_version = "TP1A",
-    max_platform_version = "TP1A",
-    min_platform_version = "TP1A",
-    platform_base_sdk_extension_version = 0,
-    platform_sdk_extension_version = 1,
-    platform_sdk_version = 31,
-    platform_security_patch = "2021-10-05",
-    platform_version_last_stable = 12,
-    codenames = { "SP2A": "Sv2", "TP1A": "Tiramisu" }
-)
-`
-	actualString := VersionDefaults(actualProducts)
-	if !reflect.DeepEqual(actualString, expectedString) {
-		t.Errorf("\nExpected: %v\nActual:\n%v",
-			strings.ReplaceAll(expectedString, "\n", "␤\n"),
-			strings.ReplaceAll(actualString, "\n", "␤\n"))
-	}
-
-}
diff --git a/rust/config/global.go b/rust/config/global.go
index acc7a79..78c8dae 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.56.1p1"
+	RustDefaultVersion = "1.57.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2018"
 	Stdlibs            = []string{
diff --git a/scripts/rbc-run b/scripts/rbc-run
index 235da75..7243421 100755
--- a/scripts/rbc-run
+++ b/scripts/rbc-run
@@ -2,7 +2,7 @@
 # Convert and run one configuration
 # Args: a product/board makefile optionally followed by additional arguments
 #       that will be passed to rbcrun.
-[[ $# -gt 0 && -f "$1" ]] || { echo "Usage: ${0##*/} product.mk [Additional rbcrun arguments]" >&2; exit 1; }
+[[ $# -gt 1 && -f "$1" && -f "$2" ]] || { echo "Usage: ${0##*/} product.mk input_variables.mk [Additional rbcrun arguments]" >&2; exit 1; }
 set -eu
 
 declare -r output_root="${OUT_DIR:-out}"
@@ -10,7 +10,8 @@
 declare -r converter="${output_root}/soong/mk2rbc"
 declare -r launcher="${output_root}/rbc/launcher.rbc"
 declare -r makefile="$1"
-shift
-"${converter}" -mode=write -r --outdir "${output_root}/rbc" --launcher="${launcher}" "${makefile}"
+declare -r input_variables="$2"
+shift 2
+"${converter}" -mode=write -r --outdir "${output_root}/rbc" --input_variables "${input_variables}" --launcher="${launcher}" "${makefile}"
 "${runner}" RBC_OUT="make,global" RBC_DEBUG="${RBC_DEBUG:-}" $@ "${launcher}"