Merge "Do not modules in files called "Blueprints"."
diff --git a/android/bazel.go b/android/bazel.go
index bebb61b..692fbcd 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -120,6 +120,10 @@
 	// allows modules to opt-out.
 	Bp2BuildDefaultTrueRecursively BazelConversionConfigEntry = iota + 1
 
+	// all modules in this package (not recursively) default to bp2build_available: true.
+	// allows modules to opt-out.
+	Bp2BuildDefaultTrue
+
 	// all modules in this package (not recursively) default to bp2build_available: false.
 	// allows modules to opt-in.
 	Bp2BuildDefaultFalse
@@ -141,6 +145,7 @@
 		"build/bazel/bazel_skylib":/* recursive = */ true,
 		"build/bazel/rules":/* recursive = */ true,
 		"build/bazel/rules_cc":/* recursive = */ true,
+		"build/bazel/scripts":/* recursive = */ true,
 		"build/bazel/tests":/* recursive = */ true,
 		"build/bazel/platforms":/* recursive = */ true,
 		"build/bazel/product_variables":/* recursive = */ true,
@@ -164,7 +169,9 @@
 		"build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
 		"development/sdk":                   Bp2BuildDefaultTrueRecursively,
 		"external/gwp_asan":                 Bp2BuildDefaultTrueRecursively,
+		"external/brotli":                   Bp2BuildDefaultTrue,
 		"system/core/libcutils":             Bp2BuildDefaultTrueRecursively,
+		"system/core/libprocessgroup":       Bp2BuildDefaultTrue,
 		"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
 		"system/libbase":                  Bp2BuildDefaultTrueRecursively,
 		"system/logging/liblog":           Bp2BuildDefaultTrueRecursively,
@@ -173,6 +180,7 @@
 		"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
 		"external/fmtlib":                 Bp2BuildDefaultTrueRecursively,
 		"external/jemalloc_new":           Bp2BuildDefaultTrueRecursively,
+		"external/libcxx":                 Bp2BuildDefaultTrueRecursively,
 		"external/libcxxabi":              Bp2BuildDefaultTrueRecursively,
 		"external/scudo":                  Bp2BuildDefaultTrueRecursively,
 		"prebuilts/clang/host/linux-x86":  Bp2BuildDefaultTrueRecursively,
@@ -217,6 +225,12 @@
 
 		"gwp_asan_crash_handler", // cc_library, ld.lld: error: undefined symbol: memset
 
+		//system/core/libprocessgroup/...
+		"libprocessgroup", // depends on //system/core/libprocessgroup/cgrouprc:libcgrouprc
+
+		//external/brotli/...
+		"brotli-fuzzer-corpus", // "declared output 'external/brotli/c/fuzz/73231c6592f195ffd41100b8706d1138ff6893b9' was not created by genrule"
+
 		// Tests. Handle later.
 		"libbionic_tests_headers_posix", // http://b/186024507, cc_library_static, sched.h, time.h not found
 		"libjemalloc5_integrationtest",
@@ -237,8 +251,12 @@
 	// Per-module denylist to opt modules out of mixed builds. Such modules will
 	// still be generated via bp2build.
 	mixedBuildsDisabledList = []string{
-		"libc++abi",      // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
-		"libc++demangle", // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
+		"libbrotli",           // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
+		"libc++fs",            // http://b/198403271, Missing symbols/members in the global namespace when referenced from headers in //external/libcxx/includes
+		"libc++_experimental", // http://b/198403271, Missing symbols/members in the global namespace when referenced from headers in //external/libcxx/includes
+		"libc++_static",       // http://b/198403271, Missing symbols/members in the global namespace when referenced from headers in //external/libcxx/includes
+		"libc++abi",           // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
+		"libc++demangle",      // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
 	}
 
 	// Used for quicker lookups
@@ -340,11 +358,10 @@
 func bp2buildDefaultTrueRecursively(packagePath string, config Bp2BuildConfig) bool {
 	ret := false
 
-	// Return exact matches in the config.
-	if config[packagePath] == Bp2BuildDefaultTrueRecursively {
+	// Check if the package path has an exact match in the config.
+	if config[packagePath] == Bp2BuildDefaultTrue || config[packagePath] == Bp2BuildDefaultTrueRecursively {
 		return true
-	}
-	if config[packagePath] == Bp2BuildDefaultFalse {
+	} else if config[packagePath] == Bp2BuildDefaultFalse {
 		return false
 	}
 
diff --git a/android/config.go b/android/config.go
index c7d9bc1..e0fc266 100644
--- a/android/config.go
+++ b/android/config.go
@@ -72,13 +72,29 @@
 }
 
 func (c Config) OutDir() string {
-	return c.soongOutDir
+	return c.outDir
+}
+
+func (c Config) RunGoTests() bool {
+	return c.runGoTests
+}
+
+func (c Config) UseValidationsForGoTests() bool {
+	return c.useValidationsForGoTests
 }
 
 func (c Config) DebugCompilation() bool {
 	return false // Never compile Go code in the main build for debugging
 }
 
+func (c Config) Subninjas() []string {
+	return []string{}
+}
+
+func (c Config) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderInvocation {
+	return []bootstrap.PrimaryBuilderInvocation{}
+}
+
 // A DeviceConfig object represents the configuration for a particular device
 // being built. For now there will only be one of these, but in the future there
 // may be multiple devices being built.
@@ -122,9 +138,13 @@
 
 	deviceConfig *deviceConfig
 
-	soongOutDir    string // the path of the build output directory
+	outDir         string // The output directory (usually out/)
+	soongOutDir    string
 	moduleListFile string // the path to the file which lists blueprint files to parse.
 
+	runGoTests               bool
+	useValidationsForGoTests bool
+
 	env       map[string]string
 	envLock   sync.Mutex
 	envDeps   map[string]string
@@ -283,9 +303,10 @@
 
 // NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that
 // use the android package.
-func NullConfig(soongOutDir string) Config {
+func NullConfig(outDir, soongOutDir string) Config {
 	return Config{
 		config: &config{
+			outDir:      outDir,
 			soongOutDir: soongOutDir,
 			fs:          pathtools.OsFs,
 		},
@@ -319,6 +340,9 @@
 			ShippingApiLevel:                  stringPtr("30"),
 		},
 
+		outDir: buildDir,
+		// soongOutDir is inconsistent with production (it should be buildDir + "/soong")
+		// but a lot of tests assume this :(
 		soongOutDir:  buildDir,
 		captureBuild: true,
 		env:          envCopy,
@@ -396,8 +420,8 @@
 // bootstrap run. Only per-run data is reset. Data which needs to persist across
 // multiple runs in the same program execution is carried over (such as Bazel
 // context or environment deps).
-func ConfigForAdditionalRun(c Config) (Config, error) {
-	newConfig, err := NewConfig(c.soongOutDir, c.moduleListFile, c.env)
+func ConfigForAdditionalRun(cmdlineArgs bootstrap.Args, c Config) (Config, error) {
+	newConfig, err := NewConfig(cmdlineArgs, c.soongOutDir, c.env)
 	if err != nil {
 		return Config{}, err
 	}
@@ -408,17 +432,20 @@
 
 // NewConfig creates a new Config object. The srcDir argument specifies the path
 // to the root source directory. It also loads the config file, if found.
-func NewConfig(soongOutDir string, moduleListFile string, availableEnv map[string]string) (Config, error) {
+func NewConfig(cmdlineArgs bootstrap.Args, soongOutDir string, availableEnv map[string]string) (Config, error) {
 	// Make a config with default options.
 	config := &config{
 		ProductVariablesFileName: filepath.Join(soongOutDir, productVariablesFileName),
 
 		env: availableEnv,
 
-		soongOutDir:       soongOutDir,
-		multilibConflicts: make(map[ArchType]bool),
+		outDir:                   cmdlineArgs.OutDir,
+		soongOutDir:              soongOutDir,
+		runGoTests:               cmdlineArgs.RunGoTests,
+		useValidationsForGoTests: cmdlineArgs.UseValidations,
+		multilibConflicts:        make(map[ArchType]bool),
 
-		moduleListFile: moduleListFile,
+		moduleListFile: cmdlineArgs.ModuleListFile,
 		fs:             pathtools.NewOsFs(absSrcDir),
 	}
 
diff --git a/android/override_module.go b/android/override_module.go
index e72cb78..51e74d4 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -295,7 +295,7 @@
 }
 
 func overridableModuleDepsMutator(ctx BottomUpMutatorContext) {
-	if b, ok := ctx.Module().(OverridableModule); ok {
+	if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled() {
 		b.OverridablePropertiesDepsMutator(ctx)
 	}
 }
diff --git a/apex/apex.go b/apex/apex.go
index 6bafcae..fbf6a6f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -111,9 +111,6 @@
 	// List of java libraries that are embedded inside this APEX bundle.
 	Java_libs []string
 
-	// List of prebuilt files that are embedded inside this APEX bundle.
-	Prebuilts []string
-
 	// List of platform_compat_config files that are embedded inside this APEX bundle.
 	Compat_configs []string
 
@@ -291,6 +288,9 @@
 	// List of APKs that are embedded inside this APEX.
 	Apps []string
 
+	// List of prebuilt files that are embedded inside this APEX bundle.
+	Prebuilts []string
+
 	// List of runtime resource overlays (RROs) that are embedded inside this APEX.
 	Rros []string
 
@@ -684,7 +684,6 @@
 	// each target os/architectures, appropriate dependencies are selected by their
 	// target.<os>.multilib.<type> groups and are added as (direct) dependencies.
 	targets := ctx.MultiTargets()
-	config := ctx.DeviceConfig()
 	imageVariation := a.getImageVariation(ctx)
 
 	a.combineProperties(ctx)
@@ -758,23 +757,6 @@
 		}
 	}
 
-	if prebuilts := a.properties.Prebuilts; len(prebuilts) > 0 {
-		// For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
-		// regardless of the TARGET_PREFER_* setting. See b/144532908
-		archForPrebuiltEtc := config.Arches()[0]
-		for _, arch := range config.Arches() {
-			// Prefer 64-bit arch if there is any
-			if arch.ArchType.Multilib == "lib64" {
-				archForPrebuiltEtc = arch
-				break
-			}
-		}
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "os", Variation: ctx.Os().String()},
-			{Mutator: "arch", Variation: archForPrebuiltEtc.String()},
-		}, prebuiltTag, prebuilts...)
-	}
-
 	// Common-arch dependencies come next
 	commonVariation := ctx.Config().AndroidCommonTarget.Variations()
 	ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...)
@@ -814,6 +796,25 @@
 	ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...)
 	ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
 	ctx.AddFarVariationDependencies(commonVariation, rroTag, a.overridableProperties.Rros...)
+	if prebuilts := a.overridableProperties.Prebuilts; len(prebuilts) > 0 {
+		// For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
+		// regardless of the TARGET_PREFER_* setting. See b/144532908
+		arches := ctx.DeviceConfig().Arches()
+		if len(arches) != 0 {
+			archForPrebuiltEtc := arches[0]
+			for _, arch := range arches {
+				// Prefer 64-bit arch if there is any
+				if arch.ArchType.Multilib == "lib64" {
+					archForPrebuiltEtc = arch
+					break
+				}
+			}
+			ctx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "os", Variation: ctx.Os().String()},
+				{Mutator: "arch", Variation: archForPrebuiltEtc.String()},
+			}, prebuiltTag, prebuilts...)
+		}
+	}
 
 	// Dependencies for signing
 	if String(a.overridableProperties.Key) == "" {
@@ -3282,7 +3283,7 @@
 	nativeSharedLibsLabelList := android.BazelLabelForModuleDeps(ctx, nativeSharedLibs)
 	nativeSharedLibsLabelListAttribute := bazel.MakeLabelListAttribute(nativeSharedLibsLabelList)
 
-	prebuilts := module.properties.Prebuilts
+	prebuilts := module.overridableProperties.Prebuilts
 	prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, prebuilts)
 	prebuiltsLabelListAttribute := bazel.MakeLabelListAttribute(prebuiltsLabelList)
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index daaa5cb..5c7c90b 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6080,6 +6080,7 @@
 			key: "myapex.key",
 			apps: ["app"],
 			bpfs: ["bpf"],
+			prebuilts: ["myetc"],
 			overrides: ["oldapex"],
 			updatable: false,
 		}
@@ -6089,6 +6090,7 @@
 			base: "myapex",
 			apps: ["override_app"],
 			bpfs: ["override_bpf"],
+			prebuilts: ["override_myetc"],
 			overrides: ["unknownapex"],
 			logging_parent: "com.foo.bar",
 			package_name: "test.overridden.package",
@@ -6137,6 +6139,16 @@
 			name: "override_bpf",
 			srcs: ["override_bpf.c"],
 		}
+
+		prebuilt_etc {
+			name: "myetc",
+			src: "myprebuilt",
+		}
+
+		prebuilt_etc {
+			name: "override_myetc",
+			src: "override_myprebuilt",
+		}
 	`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
 
 	originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(android.OverridableModule)
@@ -6158,6 +6170,9 @@
 	ensureNotContains(t, copyCmds, "image.apex/etc/bpf/bpf.o")
 	ensureContains(t, copyCmds, "image.apex/etc/bpf/override_bpf.o")
 
+	ensureNotContains(t, copyCmds, "image.apex/etc/myetc")
+	ensureContains(t, copyCmds, "image.apex/etc/override_myetc")
+
 	apexBundle := module.Module().(*apexBundle)
 	name := apexBundle.Name()
 	if name != "override_myapex" {
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 51cdddf..704b03a 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -45,11 +45,17 @@
 	abidw = pctx.AndroidStaticRule("abidw",
 		blueprint.RuleParams{
 			Command: "$abidw --type-id-style hash --no-corpus-path " +
-				"--no-show-locs --no-comp-dir-path -w $symbolList $in | " +
-				"$abitidy --all -o $out",
-			CommandDeps: []string{"$abitidy", "$abidw"},
+				"--no-show-locs --no-comp-dir-path -w $symbolList " +
+				"$in --out-file $out",
+			CommandDeps: []string{"$abidw"},
 		}, "symbolList")
 
+	abitidy = pctx.AndroidStaticRule("abitidy",
+		blueprint.RuleParams{
+			Command:     "$abitidy --all -i $in -o $out",
+			CommandDeps: []string{"$abitidy"},
+		})
+
 	abidiff = pctx.AndroidStaticRule("abidiff",
 		blueprint.RuleParams{
 			// Need to create *some* output for ninja. We don't want to use tee
@@ -313,19 +319,28 @@
 
 func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) {
 	implementationLibrary := this.findImplementationLibrary(ctx)
-	this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
+	abiRawPath := getNdkAbiDumpInstallBase(ctx).Join(ctx,
 		this.apiLevel.String(), ctx.Arch().ArchType.String(),
-		this.libraryName(ctx), "abi.xml")
+		this.libraryName(ctx), "abi.raw.xml")
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        abidw,
 		Description: fmt.Sprintf("abidw %s", implementationLibrary),
-		Output:      this.abiDumpPath,
 		Input:       implementationLibrary,
+		Output:      abiRawPath,
 		Implicit:    symbolList,
 		Args: map[string]string{
 			"symbolList": symbolList.String(),
 		},
 	})
+	this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
+		this.apiLevel.String(), ctx.Arch().ArchType.String(),
+		this.libraryName(ctx), "abi.xml")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        abitidy,
+		Description: fmt.Sprintf("abitidy %s", implementationLibrary),
+		Input:       abiRawPath,
+		Output:      this.abiDumpPath,
+	})
 }
 
 func findNextApiLevel(ctx ModuleContext, apiLevel android.ApiLevel) *android.ApiLevel {
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 16a4e1a..3e724ee 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -35,7 +35,7 @@
 
 var (
 	topDir           string
-	outDir           string
+	soongOutDir      string
 	availableEnvFile string
 	usedEnvFile      string
 
@@ -55,13 +55,12 @@
 func init() {
 	// Flags that make sense in every mode
 	flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree")
-	flag.StringVar(&outDir, "out", "", "Soong output directory (usually $TOP/out/soong)")
+	flag.StringVar(&soongOutDir, "soong_out", "", "Soong output directory (usually $TOP/out/soong)")
 	flag.StringVar(&availableEnvFile, "available_env", "", "File containing available environment variables")
 	flag.StringVar(&usedEnvFile, "used_env", "", "File containing used environment variables")
 	flag.StringVar(&globFile, "globFile", "build-globs.ninja", "the Ninja file of globs to output")
 	flag.StringVar(&globListDir, "globListDir", "", "the directory containing the glob list files")
-	flag.StringVar(&cmdlineArgs.SoongOutDir, "b", ".", "the build output directory")
-	flag.StringVar(&cmdlineArgs.OutDir, "n", "", "the ninja builddir directory")
+	flag.StringVar(&cmdlineArgs.OutDir, "out", "", "the ninja builddir directory")
 	flag.StringVar(&cmdlineArgs.ModuleListFile, "l", "", "file that lists filepaths to parse")
 
 	// Debug flags
@@ -113,8 +112,8 @@
 	return ctx
 }
 
-func newConfig(outDir string, availableEnv map[string]string) android.Config {
-	configuration, err := android.NewConfig(outDir, cmdlineArgs.ModuleListFile, availableEnv)
+func newConfig(cmdlineArgs bootstrap.Args, outDir string, availableEnv map[string]string) android.Config {
+	configuration, err := android.NewConfig(cmdlineArgs, outDir, availableEnv)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "%s", err)
 		os.Exit(1)
@@ -140,13 +139,13 @@
 		os.Exit(1)
 	}
 	// Second pass: Full analysis, using the bazel command results. Output ninja file.
-	secondConfig, err := android.ConfigForAdditionalRun(configuration)
+	secondArgs = cmdlineArgs
+	secondConfig, err := android.ConfigForAdditionalRun(secondArgs, configuration)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "%s", err)
 		os.Exit(1)
 	}
 	secondCtx := newContext(secondConfig, true)
-	secondArgs = cmdlineArgs
 	ninjaDeps := bootstrap.RunBlueprint(secondArgs, secondCtx.Context, secondConfig)
 	ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
 
@@ -298,7 +297,7 @@
 
 	availableEnv := parseAvailableEnv()
 
-	configuration := newConfig(outDir, availableEnv)
+	configuration := newConfig(cmdlineArgs, soongOutDir, availableEnv)
 	extraNinjaDeps := []string{
 		configuration.ProductVariablesFileName,
 		usedEnvFile,
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index 7dbe74c..ba05d94 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -87,7 +87,9 @@
 		usage("--module configuration file is required")
 	}
 
-	ctx := &builderContext{android.NullConfig(*outDir)}
+	// NOTE: duplicating --out_dir here is incorrect (one should be the another
+	// plus "/soong" but doing so apparently breaks dexpreopt
+	ctx := &builderContext{android.NullConfig(*outDir, *outDir)}
 
 	globalSoongConfigData, err := ioutil.ReadFile(*globalSoongConfigPath)
 	if err != nil {
diff --git a/java/app_import.go b/java/app_import.go
index b5a6084..3e5f972 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -204,9 +204,9 @@
 		return false
 	}
 
-	// Uncompress dex in APKs of privileged apps
-	if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
-		return true
+	// Uncompress dex in APKs of priv-apps if and only if DONT_UNCOMPRESS_PRIV_APPS_DEXS is false.
+	if a.Privileged() {
+		return ctx.Config().UncompressPrivAppDex()
 	}
 
 	return shouldUncompressDex(ctx, &a.dexpreopter)
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 024a3df..efa52c1 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -15,6 +15,7 @@
 package java
 
 import (
+	"fmt"
 	"reflect"
 	"regexp"
 	"strings"
@@ -656,3 +657,74 @@
 		}
 	}
 }
+
+func TestAndroidTestImport_UncompressDex(t *testing.T) {
+	testCases := []struct {
+		name string
+		bp   string
+	}{
+		{
+			name: "normal",
+			bp: `
+				android_app_import {
+					name: "foo",
+					presigned: true,
+					apk: "prebuilts/apk/app.apk",
+				}
+			`,
+		},
+		{
+			name: "privileged",
+			bp: `
+				android_app_import {
+					name: "foo",
+					presigned: true,
+					privileged: true,
+					apk: "prebuilts/apk/app.apk",
+				}
+			`,
+		},
+	}
+
+	test := func(t *testing.T, bp string, unbundled bool, dontUncompressPrivAppDexs bool) {
+		t.Helper()
+
+		result := android.GroupFixturePreparers(
+			prepareForJavaTest,
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				if unbundled {
+					variables.Unbundled_build = proptools.BoolPtr(true)
+				}
+				variables.UncompressPrivAppDex = proptools.BoolPtr(!dontUncompressPrivAppDexs)
+			}),
+		).RunTestWithBp(t, bp)
+
+		foo := result.ModuleForTests("foo", "android_common")
+		actual := foo.MaybeRule("uncompress-dex").Rule != nil
+
+		expect := !unbundled
+		if strings.Contains(bp, "privileged: true") {
+			if dontUncompressPrivAppDexs {
+				expect = false
+			} else {
+				// TODO(b/194504107): shouldn't priv-apps be always uncompressed unless
+				// DONT_UNCOMPRESS_PRIV_APPS_DEXS is true (regardless of unbundling)?
+				// expect = true
+			}
+		}
+
+		android.AssertBoolEquals(t, "uncompress dex", expect, actual)
+	}
+
+	for _, unbundled := range []bool{false, true} {
+		for _, dontUncompressPrivAppDexs := range []bool{false, true} {
+			for _, tt := range testCases {
+				name := fmt.Sprintf("%s,unbundled:%t,dontUncompressPrivAppDexs:%t",
+					tt.name, unbundled, dontUncompressPrivAppDexs)
+				t.Run(name, func(t *testing.T) {
+					test(t, tt.bp, unbundled, dontUncompressPrivAppDexs)
+				})
+			}
+		}
+	}
+}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index a627dae..d4f6f2f 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -71,10 +71,14 @@
 // A tiny struct used to tell Blueprint that it's in bootstrap mode. It would
 // probably be nicer to use a flag in bootstrap.Args instead.
 type BlueprintConfig struct {
-	toolDir          string
-	soongOutDir      string
-	outDir           string
-	debugCompilation bool
+	toolDir                   string
+	soongOutDir               string
+	outDir                    string
+	runGoTests                bool
+	useValidations            bool
+	debugCompilation          bool
+	subninjas                 []string
+	primaryBuilderInvocations []bootstrap.PrimaryBuilderInvocation
 }
 
 func (c BlueprintConfig) HostToolDir() string {
@@ -89,10 +93,26 @@
 	return c.outDir
 }
 
+func (c BlueprintConfig) RunGoTests() bool {
+	return c.runGoTests
+}
+
+func (c BlueprintConfig) UseValidationsForGoTests() bool {
+	return c.useValidations
+}
+
 func (c BlueprintConfig) DebugCompilation() bool {
 	return c.debugCompilation
 }
 
+func (c BlueprintConfig) Subninjas() []string {
+	return c.subninjas
+}
+
+func (c BlueprintConfig) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderInvocation {
+	return c.primaryBuilderInvocations
+}
+
 func environmentArgs(config Config, suffix string) []string {
 	return []string{
 		"--available_env", shared.JoinPath(config.SoongOutDir(), availableEnvFile),
@@ -211,10 +231,14 @@
 	blueprintCtx := blueprint.NewContext()
 	blueprintCtx.SetIgnoreUnknownModuleTypes(true)
 	blueprintConfig := BlueprintConfig{
-		soongOutDir:      config.SoongOutDir(),
-		toolDir:          config.HostToolDir(),
-		outDir:           config.OutDir(),
-		debugCompilation: os.Getenv("SOONG_DELVE") != "",
+		soongOutDir:               config.SoongOutDir(),
+		toolDir:                   config.HostToolDir(),
+		outDir:                    config.OutDir(),
+		runGoTests:                !config.skipSoongTests,
+		useValidations:            true,
+		debugCompilation:          os.Getenv("SOONG_DELVE") != "",
+		subninjas:                 args.Subninjas,
+		primaryBuilderInvocations: args.PrimaryBuilderInvocations,
 	}
 
 	args.EmptyNinjaFile = false