Merge "Prevent sdk variants from install"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 8cd52cb..89c2d19 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -199,6 +199,7 @@
 		"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
 		"frameworks/base/tools/aapt2":                        Bp2BuildDefaultTrue,
 		"frameworks/base/tools/streaming_proto":              Bp2BuildDefaultTrueRecursively,
+		"frameworks/hardware/interfaces/stats/aidl":          Bp2BuildDefaultTrue,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/arect":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/gui":                         Bp2BuildDefaultTrue,
@@ -257,30 +258,32 @@
 
 		"libnativehelper": Bp2BuildDefaultTrueRecursively,
 
-		"packages/apps/DevCamera":                          Bp2BuildDefaultTrue,
-		"packages/apps/HTMLViewer":                         Bp2BuildDefaultTrue,
-		"packages/apps/Protips":                            Bp2BuildDefaultTrue,
-		"packages/apps/SafetyRegulatoryInfo":               Bp2BuildDefaultTrue,
-		"packages/apps/WallpaperPicker":                    Bp2BuildDefaultTrue,
-		"packages/modules/NeuralNetworks/driver/cache":     Bp2BuildDefaultTrueRecursively,
-		"packages/modules/StatsD/lib/libstatssocket":       Bp2BuildDefaultTrueRecursively,
-		"packages/modules/adb":                             Bp2BuildDefaultTrue,
-		"packages/modules/adb/apex":                        Bp2BuildDefaultTrue,
-		"packages/modules/adb/crypto":                      Bp2BuildDefaultTrueRecursively,
-		"packages/modules/adb/libs":                        Bp2BuildDefaultTrueRecursively,
-		"packages/modules/adb/pairing_auth":                Bp2BuildDefaultTrueRecursively,
-		"packages/modules/adb/pairing_connection":          Bp2BuildDefaultTrueRecursively,
-		"packages/modules/adb/proto":                       Bp2BuildDefaultTrueRecursively,
-		"packages/modules/adb/tls":                         Bp2BuildDefaultTrueRecursively,
-		"packages/providers/MediaProvider/tools/dialogs":   Bp2BuildDefaultFalse, // TODO(b/242834374)
-		"packages/screensavers/Basic":                      Bp2BuildDefaultTrue,
-		"packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultFalse, // TODO(b/242834321)
+		"packages/apps/DevCamera":                            Bp2BuildDefaultTrue,
+		"packages/apps/HTMLViewer":                           Bp2BuildDefaultTrue,
+		"packages/apps/Protips":                              Bp2BuildDefaultTrue,
+		"packages/apps/SafetyRegulatoryInfo":                 Bp2BuildDefaultTrue,
+		"packages/apps/WallpaperPicker":                      Bp2BuildDefaultTrue,
+		"packages/modules/NeuralNetworks/driver/cache":       Bp2BuildDefaultTrueRecursively,
+		"packages/modules/StatsD/lib/libstatssocket":         Bp2BuildDefaultTrueRecursively,
+		"packages/modules/adb":                               Bp2BuildDefaultTrue,
+		"packages/modules/adb/apex":                          Bp2BuildDefaultTrue,
+		"packages/modules/adb/crypto":                        Bp2BuildDefaultTrueRecursively,
+		"packages/modules/adb/libs":                          Bp2BuildDefaultTrueRecursively,
+		"packages/modules/adb/pairing_auth":                  Bp2BuildDefaultTrueRecursively,
+		"packages/modules/adb/pairing_connection":            Bp2BuildDefaultTrueRecursively,
+		"packages/modules/adb/proto":                         Bp2BuildDefaultTrueRecursively,
+		"packages/modules/adb/tls":                           Bp2BuildDefaultTrueRecursively,
+		"packages/modules/NetworkStack/common/captiveportal": Bp2BuildDefaultTrue,
+		"packages/providers/MediaProvider/tools/dialogs":     Bp2BuildDefaultFalse, // TODO(b/242834374)
+		"packages/screensavers/Basic":                        Bp2BuildDefaultTrue,
+		"packages/services/Car/tests/SampleRearViewCamera":   Bp2BuildDefaultFalse, // TODO(b/242834321)
 
 		"platform_testing/tests/example": Bp2BuildDefaultTrueRecursively,
 
 		"prebuilts/clang/host/linux-x86":           Bp2BuildDefaultTrueRecursively,
 		"prebuilts/gradle-plugin":                  Bp2BuildDefaultTrueRecursively,
 		"prebuilts/runtime/mainline/platform/sdk":  Bp2BuildDefaultTrueRecursively,
+		"prebuilts/sdk/current/androidx":           Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/support":            Bp2BuildDefaultTrue,
 		"prebuilts/tools":                          Bp2BuildDefaultTrue,
diff --git a/android/androidmk.go b/android/androidmk.go
index 6346401..14b2e82 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -501,6 +501,7 @@
 // generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
 type fillInEntriesContext interface {
 	ModuleDir(module blueprint.Module) string
+	ModuleSubDir(module blueprint.Module) string
 	Config() Config
 	ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
 	ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
@@ -528,7 +529,7 @@
 		fmt.Fprintf(&a.header, distString)
 	}
 
-	fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)  # "+ctx.ModuleType(mod))
+	fmt.Fprintf(&a.header, "\ninclude $(CLEAR_VARS)  # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod))
 
 	// Collect make variable assignment entries.
 	a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 3a459f1..e7ff08f 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -201,6 +201,8 @@
 	// (for example, that it is MixedBuildBuildable).
 	IsModuleNameAllowed(moduleName string, withinApex bool) bool
 
+	IsModuleDclaAllowed(moduleName string) bool
+
 	// Returns the bazel output base (the root directory for all bazel intermediate outputs).
 	OutputBase() string
 
@@ -341,6 +343,10 @@
 	return true
 }
 
+func (m MockBazelContext) IsModuleDclaAllowed(_ string) bool {
+	return true
+}
+
 func (m MockBazelContext) OutputBase() string { return m.OutputBaseDir }
 
 func (m MockBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
@@ -483,6 +489,10 @@
 	return false
 }
 
+func (n noopBazelContext) IsModuleDclaAllowed(_ string) bool {
+	return false
+}
+
 func (m noopBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
 	return []*bazel.BuildStatement{}
 }
@@ -619,13 +629,17 @@
 	if context.bazelEnabledModules[moduleName] {
 		return true
 	}
-	if withinApex && context.bazelDclaEnabledModules[moduleName] {
+	if withinApex && context.IsModuleDclaAllowed(moduleName) {
 		return true
 	}
 
 	return context.modulesDefaultToBazel
 }
 
+func (context *mixedBuildBazelContext) IsModuleDclaAllowed(moduleName string) bool {
+	return context.bazelDclaEnabledModules[moduleName]
+}
+
 func pwdPrefix() string {
 	// Darwin doesn't have /proc
 	if runtime.GOOS != "darwin" {
diff --git a/apex/apex.go b/apex/apex.go
index 9a80aa8..d7d76d1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -111,6 +111,18 @@
 
 	Multilib apexMultilibProperties
 
+	// List of runtime resource overlays (RROs) that are embedded inside this APEX.
+	Rros []string
+
+	// List of bootclasspath fragments that are embedded inside this APEX bundle.
+	Bootclasspath_fragments []string
+
+	// List of systemserverclasspath fragments that are embedded inside this APEX bundle.
+	Systemserverclasspath_fragments []string
+
+	// List of java libraries that are embedded inside this APEX bundle.
+	Java_libs []string
+
 	// List of sh binaries that are embedded inside this APEX bundle.
 	Sh_binaries []string
 
@@ -141,9 +153,6 @@
 	// Default: true.
 	Installable *bool
 
-	// Whether this APEX ignores the apex_available list defined in its dependencies.
-	Override_apex_available *bool
-
 	// If set true, VNDK libs are considered as stable libs and are not included in this APEX.
 	// Should be only used in non-system apexes (e.g. vendor: true). Default is false.
 	Use_vndk_as_stable *bool
@@ -329,21 +338,9 @@
 	// 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
-
 	// List of BPF programs inside this APEX bundle.
 	Bpfs []string
 
-	// List of bootclasspath fragments that are embedded inside this APEX bundle.
-	Bootclasspath_fragments []string
-
-	// List of systemserverclasspath fragments that are embedded inside this APEX bundle.
-	Systemserverclasspath_fragments []string
-
-	// List of java libraries that are embedded inside this APEX bundle.
-	Java_libs []string
-
 	// Names of modules to be overridden. Listed modules can only be other binaries (in Make or
 	// Soong). This does not completely prevent installation of the overridden binaries, but if
 	// both binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will
@@ -850,6 +847,10 @@
 
 	// Common-arch dependencies come next
 	commonVariation := ctx.Config().AndroidCommonTarget.Variations()
+	ctx.AddFarVariationDependencies(commonVariation, rroTag, a.properties.Rros...)
+	ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...)
+	ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...)
+	ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
 	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
 	ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
 }
@@ -863,10 +864,6 @@
 	commonVariation := ctx.Config().AndroidCommonTarget.Variations()
 	ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...)
 	ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
-	ctx.AddFarVariationDependencies(commonVariation, rroTag, a.overridableProperties.Rros...)
-	ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.overridableProperties.Bootclasspath_fragments...)
-	ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.overridableProperties.Systemserverclasspath_fragments...)
-	ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.overridableProperties.Java_libs...)
 	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
@@ -1516,10 +1513,6 @@
 	return proptools.BoolDefault(a.properties.Platform_apis, false)
 }
 
-func (a *apexBundle) OverrideApexAvailable() bool {
-	return proptools.BoolDefault(a.properties.Override_apex_available, false)
-}
-
 // getCertString returns the name of the cert that should be used to sign this APEX. This is
 // basically from the "certificate" property, but could be overridden by the device config.
 func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
@@ -3047,11 +3040,6 @@
 		return
 	}
 
-	// Ignore availability when `override_apex_available` is true.
-	if a.OverrideApexAvailable() {
-		return
-	}
-
 	a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
 		// As soon as the dependency graph crosses the APEX boundary, don't go further.
 		if externalDep {
@@ -3121,9 +3109,9 @@
 
 // Collect information for opening IDE project files in java/jdeps.go.
 func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) {
-	dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Java_libs...)
-	dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Bootclasspath_fragments...)
-	dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Systemserverclasspath_fragments...)
+	dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...)
+	dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments...)
+	dpInfo.Deps = append(dpInfo.Deps, a.properties.Systemserverclasspath_fragments...)
 	dpInfo.Paths = append(dpInfo.Paths, a.modulePaths...)
 }
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index faf82b3..b7febe1 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6294,9 +6294,6 @@
 			apps: ["app"],
 			bpfs: ["bpf"],
 			prebuilts: ["myetc"],
-			bootclasspath_fragments: ["mybootclasspath_fragment"],
-			systemserverclasspath_fragments: ["mysystemserverclasspath_fragment"],
-			java_libs: ["myjava_library"],
 			overrides: ["oldapex"],
 			updatable: false,
 		}
@@ -6307,9 +6304,6 @@
 			apps: ["override_app"],
 			bpfs: ["overrideBpf"],
 			prebuilts: ["override_myetc"],
-			bootclasspath_fragments: ["override_bootclasspath_fragment"],
-			systemserverclasspath_fragments: ["override_systemserverclasspath_fragment"],
-			java_libs: ["override_java_library"],
 			overrides: ["unknownapex"],
 			logging_parent: "com.foo.bar",
 			package_name: "test.overridden.package",
@@ -6368,78 +6362,6 @@
 			name: "override_myetc",
 			src: "override_myprebuilt",
 		}
-
-		java_library {
-			name: "bcplib",
-			srcs: ["a.java"],
-			compile_dex: true,
-			apex_available: ["myapex"],
-			permitted_packages: ["bcp.lib"],
-		}
-
-		bootclasspath_fragment {
-			name: "mybootclasspath_fragment",
-			contents: ["bcplib"],
-			apex_available: ["myapex"],
-			hidden_api: {
-				split_packages: ["*"],
-			},
-		}
-
-		java_library {
-			name: "override_bcplib",
-			srcs: ["a.java"],
-			compile_dex: true,
-			apex_available: ["myapex"],
-			permitted_packages: ["override.bcp.lib"],
-		}
-
-		bootclasspath_fragment {
-			name: "override_bootclasspath_fragment",
-			contents: ["override_bcplib"],
-			apex_available: ["myapex"],
-			hidden_api: {
-				split_packages: ["*"],
-			},
-		}
-
-		java_library {
-			name: "systemserverlib",
-			srcs: ["a.java"],
-			apex_available: ["myapex"],
-		}
-
-		systemserverclasspath_fragment {
-			name: "mysystemserverclasspath_fragment",
-			standalone_contents: ["systemserverlib"],
-			apex_available: ["myapex"],
-		}
-
-		java_library {
-			name: "override_systemserverlib",
-			srcs: ["a.java"],
-			apex_available: ["myapex"],
-		}
-
-		systemserverclasspath_fragment {
-			name: "override_systemserverclasspath_fragment",
-			standalone_contents: ["override_systemserverlib"],
-			apex_available: ["myapex"],
-		}
-
-		java_library {
-			name: "myjava_library",
-			srcs: ["a.java"],
-			compile_dex: true,
-			apex_available: ["myapex"],
-		}
-
-		java_library {
-			name: "override_java_library",
-			srcs: ["a.java"],
-			compile_dex: true,
-			apex_available: ["myapex"],
-		}
 	`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
 
 	originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(android.OverridableModule)
@@ -6474,13 +6396,6 @@
 		t.Errorf("override_myapex should have logging parent (com.foo.bar), but was %q.", apexBundle.overridableProperties.Logging_parent)
 	}
 
-	android.AssertArrayString(t, "Bootclasspath_fragments does not match",
-		[]string{"override_bootclasspath_fragment"}, apexBundle.overridableProperties.Bootclasspath_fragments)
-	android.AssertArrayString(t, "Systemserverclasspath_fragments does not match",
-		[]string{"override_systemserverclasspath_fragment"}, apexBundle.overridableProperties.Systemserverclasspath_fragments)
-	android.AssertArrayString(t, "Java_libs does not match",
-		[]string{"override_java_library"}, apexBundle.overridableProperties.Java_libs)
-
 	optFlags := apexRule.Args["opt_flags"]
 	ensureContains(t, optFlags, "--override_apk_package_name test.overridden.package")
 	ensureContains(t, optFlags, "--pubkey testkey2.avbpubkey")
@@ -6495,18 +6410,12 @@
 	ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE := overrideBpf.o.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.override_myapex")
-	ensureContains(t, androidMk, "LOCAL_MODULE := override_bcplib.override_myapex")
-	ensureContains(t, androidMk, "LOCAL_MODULE := override_systemserverlib.override_myapex")
-	ensureContains(t, androidMk, "LOCAL_MODULE := override_java_library.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE_STEM := override_myapex.apex")
 	ensureContains(t, androidMk, "LOCAL_OVERRIDES_MODULES := unknownapex myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := app.myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := bpf.myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := override_app.myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex")
-	ensureNotContains(t, androidMk, "LOCAL_MODULE := override_bcplib.myapex")
-	ensureNotContains(t, androidMk, "LOCAL_MODULE := override_systemserverlib.myapex")
-	ensureNotContains(t, androidMk, "LOCAL_MODULE := override_java_library.pb.myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.apex")
 }
 
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 54be709..af14f64 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -4084,3 +4084,56 @@
 		},
 	})
 }
+
+func TestCcLibraryInApexWithStubSharedLibs(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library with in apex with stub shared_libs and export_shared_lib_headers",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library {
+	name: "barlib",
+	stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
+	bazel_module: { bp2build_available: false },
+}
+cc_library {
+	name: "bazlib",
+	stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
+	bazel_module: { bp2build_available: false },
+}
+cc_library {
+    name: "foo",
+	  shared_libs: ["barlib", "bazlib"],
+    export_shared_lib_headers: ["bazlib"],
+    apex_available: [
+        "apex_available:platform",
+    ],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"implementation_dynamic_deps": `select({
+        "//build/bazel/rules/apex:android-in_apex": [":barlib_stub_libs_current"],
+        "//conditions:default": [":barlib"],
+    })`,
+				"dynamic_deps": `select({
+        "//build/bazel/rules/apex:android-in_apex": [":bazlib_stub_libs_current"],
+        "//conditions:default": [":bazlib"],
+    })`,
+				"local_includes": `["."]`,
+				"tags":           `["apex_available=apex_available:platform"]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"implementation_dynamic_deps": `select({
+        "//build/bazel/rules/apex:android-in_apex": [":barlib_stub_libs_current"],
+        "//conditions:default": [":barlib"],
+    })`,
+				"dynamic_deps": `select({
+        "//build/bazel/rules/apex:android-in_apex": [":bazlib_stub_libs_current"],
+        "//conditions:default": [":bazlib"],
+    })`,
+				"local_includes": `["."]`,
+				"tags":           `["apex_available=apex_available:platform"]`,
+			}),
+		},
+	})
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 250241c..808f51c 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -1080,43 +1080,13 @@
 	la.resolveTargetApexProp(ctx, props)
 
 	if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) {
-		// If a dependency in la.implementationDynamicDeps has stubs, its stub variant should be
-		// used when the dependency is linked in a APEX. The dependencies in NoConfigAxis and
-		// OsConfigurationAxis/OsAndroid are grouped by having stubs or not, so Bazel select()
-		// statement can be used to choose source/stub variants of them.
-		depsWithStubs := []bazel.Label{}
-		for _, l := range sharedDeps.implementation.Includes {
-			dep, _ := ctx.ModuleFromName(l.OriginalModuleName)
-			if m, ok := dep.(*Module); ok && m.HasStubsVariants() {
-				depsWithStubs = append(depsWithStubs, l)
-			}
-		}
-		if len(depsWithStubs) > 0 {
-			implDynamicDeps := bazel.SubtractBazelLabelList(sharedDeps.implementation, bazel.MakeLabelList(depsWithStubs))
-			la.implementationDynamicDeps.SetSelectValue(axis, config, implDynamicDeps)
-
-			stubLibLabels := []bazel.Label{}
-			for _, l := range depsWithStubs {
-				l.Label = l.Label + stubsSuffix
-				stubLibLabels = append(stubLibLabels, l)
-			}
-			inApexSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex)
-			nonApexSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex)
-			defaultSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey)
-			if axis == bazel.NoConfigAxis {
-				(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
-				(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
-				(&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue))
-			} else if config == bazel.OsAndroid {
-				(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
-				(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
-			}
-		}
+		// If a dependency in la.implementationDynamicDeps or la.dynamicDeps has stubs, its
+		// stub variant should be used when the dependency is linked in a APEX. The
+		// dependencies in NoConfigAxis and OsConfigurationAxis/OsAndroid are grouped by
+		// having stubs or not, so Bazel select() statement can be used to choose
+		// source/stub variants of them.
+		setStubsForDynamicDeps(ctx, axis, config, sharedDeps.export, &la.dynamicDeps, 0)
+		setStubsForDynamicDeps(ctx, axis, config, sharedDeps.implementation, &la.implementationDynamicDeps, 1)
 	}
 
 	if !BoolDefault(props.Pack_relocations, packRelocationsDefault) {
@@ -1173,6 +1143,43 @@
 	}
 }
 
+func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis,
+	config string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int) {
+	depsWithStubs := []bazel.Label{}
+	for _, l := range dynamicLibs.Includes {
+		dep, _ := ctx.ModuleFromName(l.OriginalModuleName)
+		if m, ok := dep.(*Module); ok && m.HasStubsVariants() {
+			depsWithStubs = append(depsWithStubs, l)
+		}
+	}
+	if len(depsWithStubs) > 0 {
+		implDynamicDeps := bazel.SubtractBazelLabelList(dynamicLibs, bazel.MakeLabelList(depsWithStubs))
+		dynamicDeps.SetSelectValue(axis, config, implDynamicDeps)
+
+		stubLibLabels := []bazel.Label{}
+		for _, l := range depsWithStubs {
+			l.Label = l.Label + stubsSuffix
+			stubLibLabels = append(stubLibLabels, l)
+		}
+		inApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex)
+		nonApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex)
+		defaultSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey)
+		if axis == bazel.NoConfigAxis {
+			(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
+			(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+			(&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+			dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
+			dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
+			dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue))
+		} else if config == bazel.OsAndroid {
+			(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
+			(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+			dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
+			dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
+		}
+	}
+}
+
 func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
 	bp2BuildPropParseHelper(ctx, module, &StripProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
 		if stripProperties, ok := props.(*StripProperties); ok {
diff --git a/cc/cc.go b/cc/cc.go
index 5bb13ff..c07d836 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1920,6 +1920,9 @@
 func GetApexConfigKey(ctx android.BaseModuleContext) *android.ApexConfigKey {
 	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
 	if !apexInfo.IsForPlatform() {
+		if !ctx.Config().BazelContext.IsModuleDclaAllowed(ctx.Module().Name()) {
+			return nil
+		}
 		apexKey := android.ApexConfigKey{
 			WithinApex:     true,
 			ApexSdkVersion: findApexSdkVersion(ctx, apexInfo).String(),
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 801176e..8175a37 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -69,42 +69,222 @@
 	Dir          string
 }
 
-type PrivilegedLevel string
+type Vector string
 
 const (
-	// Environment with the most minimal permissions.
-	Constrained PrivilegedLevel = "Constrained"
-	// Typical execution environment running unprivileged code.
-	Unprivileged = "Unprivileged"
-	// May have access to elevated permissions.
-	Privileged = "Privileged"
-	// Trusted computing base.
-	Tcb = "TCB"
-	// Bootloader chain.
-	Bootloader = "Bootloader"
-	// Tusted execution environment.
-	Tee = "Tee"
-	// Secure enclave.
-	Se = "Se"
-	// Other.
-	Other = "Other"
+	unknown_access_vector Vector = "unknown_access_vector"
+	// The code being fuzzed is reachable from a remote source, or using data
+	// provided by a remote source.  For example: media codecs process media files
+	// from the internet, SMS processing handles remote message data.
+	// See
+	// https://source.android.com/docs/security/overview/updates-resources#local-vs-remote
+	// for an explanation of what's considered "remote."
+	remote = "remote"
+	// The code being fuzzed can only be reached locally, such as from an
+	// installed app.  As an example, if it's fuzzing a Binder interface, it's
+	// assumed that you'd need a local app to make arbitrary Binder calls.
+	// And the app that's calling the fuzzed code does not require any privileges;
+	// any 3rd party app could make these calls.
+	local_no_privileges_required = "local_no_privileges_required"
+	// The code being fuzzed can only be called locally, and the calling process
+	// requires additional permissions that prevent arbitrary 3rd party apps from
+	// calling the code.  For instance: this requires a privileged or signature
+	// permission to reach, or SELinux restrictions prevent the untrusted_app
+	// domain from calling it.
+	local_privileges_required = "local_privileges_required"
+	// The code is only callable on a PC host, not on a production Android device.
+	// For instance, this is fuzzing code used during the build process, or
+	// tooling that does not exist on a user's actual Android device.
+	host_access = "host_access"
+	// The code being fuzzed is only reachable if the user has enabled Developer
+	// Options, or has enabled a persistent Developer Options setting.
+	local_with_developer_options = "local_with_developer_options"
 )
 
+func (vector Vector) isValidVector() bool {
+	switch vector {
+	case "",
+		unknown_access_vector,
+		remote,
+		local_no_privileges_required,
+		local_privileges_required,
+		host_access,
+		local_with_developer_options:
+		return true
+	}
+	return false
+}
+
+type ServicePrivilege string
+
+const (
+	unknown_service_privilege ServicePrivilege = "unknown_service_privilege"
+	// The code being fuzzed runs on a Secure Element.  This has access to some
+	// of the most privileged data on the device, such as authentication keys.
+	// Not all devices have a Secure Element.
+	secure_element = "secure_element"
+	// The code being fuzzed runs in the TEE.  The TEE is designed to be resistant
+	// to a compromised kernel, and stores sensitive data.
+	trusted_execution = "trusted_execution"
+	// The code being fuzzed has privileges beyond what arbitrary 3rd party apps
+	// have.  For instance, it's running as the System UID, or it's in an SELinux
+	// domain that's able to perform calls that can't be made by 3rd party apps.
+	privileged = "privileged"
+	// The code being fuzzed is equivalent to a 3rd party app.  It runs in the
+	// untrusted_app SELinux domain, or it only has privileges that are equivalent
+	// to what a 3rd party app could have.
+	unprivileged = "unprivileged"
+	// The code being fuzzed is significantly constrained, and even if it's
+	// compromised, it has significant restrictions that prevent it from
+	// performing most actions.  This is significantly more restricted than
+	// UNPRIVILEGED.  An example is the isolatedProcess=true setting in a 3rd
+	// party app.  Or a process that's very restricted by SELinux, such as
+	// anything in the mediacodec SELinux domain.
+	constrained = "constrained"
+	// The code being fuzzed always has Negligible Security Impact.  Even
+	// arbitrary out of bounds writes and full code execution would not be
+	// considered a security vulnerability.  This typically only makes sense if
+	// FuzzedCodeUsage is set to FUTURE_VERSION or EXPERIMENTAL, and if
+	// AutomaticallyRouteTo is set to ALWAYS_NSI.
+	nsi = "nsi"
+	// The code being fuzzed only runs on a PC host, not on a production Android
+	// device.  For instance, the fuzzer is fuzzing code used during the build
+	// process, or tooling that does not exist on a user's actual Android device.
+	host_only = "host_only"
+)
+
+func (service_privilege ServicePrivilege) isValidServicePrivilege() bool {
+	switch service_privilege {
+	case "",
+		unknown_service_privilege,
+		secure_element,
+		trusted_execution,
+		privileged,
+		unprivileged,
+		constrained,
+		nsi,
+		host_only:
+		return true
+	}
+	return false
+}
+
+type UserData string
+
+const (
+	unknown_user_data UserData = "unknown_user_data"
+	// The process being fuzzed only handles data from a single user, or from a
+	// single process or app.  It's possible the process shuts down before
+	// handling data from another user/process/app, or it's possible the process
+	// only ever handles one user's/process's/app's data.  As an example, some
+	// print spooler processes are started for a single document and terminate
+	// when done, so each instance only handles data from a single user/app.
+	single_user = "single_user"
+	// The process handles data from multiple users, or from multiple other apps
+	// or processes.  Media processes, for instance, can handle media requests
+	// from multiple different apps without restarting.  Wi-Fi and network
+	// processes handle data from multiple users, and processes, and apps.
+	multi_user = "multi_user"
+)
+
+func (user_data UserData) isValidUserData() bool {
+	switch user_data {
+	case "",
+		unknown_user_data,
+		single_user,
+		multi_user:
+		return true
+	}
+	return false
+}
+
+type FuzzedCodeUsage string
+
+const (
+	undefined FuzzedCodeUsage = "undefined"
+	unknown                   = "unknown"
+	// The code being fuzzed exists in a shipped version of Android and runs on
+	// devices in production.
+	shipped = "shipped"
+	// The code being fuzzed is not yet in a shipping version of Android, but it
+	// will be at some point in the future.
+	future_version = "future_version"
+	// The code being fuzzed is not in a shipping version of Android, and there
+	// are no plans to ship it in the future.
+	experimental = "experimental"
+)
+
+func (fuzzed_code_usage FuzzedCodeUsage) isValidFuzzedCodeUsage() bool {
+	switch fuzzed_code_usage {
+	case "",
+		undefined,
+		unknown,
+		shipped,
+		future_version,
+		experimental:
+		return true
+	}
+	return false
+}
+
+type AutomaticallyRouteTo string
+
+const (
+	undefined_routing AutomaticallyRouteTo = "undefined_routing"
+	// Automatically route this to the Android Automotive security team for
+	// assessment.
+	android_automotive = "android_automotive"
+	// This should not be used in fuzzer configurations.  It is used internally
+	// by Severity Assigner to flag memory leak reports.
+	memory_leak = "memory_leak"
+	// Route this vulnerability to our Ittiam vendor team for assessment.
+	ittiam = "ittiam"
+	// Reports from this fuzzer are always NSI (see the NSI ServicePrivilegeEnum
+	// value for additional context).  It is not possible for this code to ever
+	// have a security vulnerability.
+	always_nsi = "always_nsi"
+	// Route this vulnerability to AIDL team for assessment.
+	aidl = "aidl"
+)
+
+func (automatically_route_to AutomaticallyRouteTo) isValidAutomaticallyRouteTo() bool {
+	switch automatically_route_to {
+	case "",
+		undefined_routing,
+		android_automotive,
+		memory_leak,
+		ittiam,
+		always_nsi,
+		aidl:
+		return true
+	}
+	return false
+}
+
 func IsValidConfig(fuzzModule FuzzPackagedModule, moduleName string) bool {
 	var config = fuzzModule.FuzzProperties.Fuzz_config
 	if config != nil {
-		var level = PrivilegedLevel(config.Privilege_level)
-		if level != "" {
-			switch level {
-			case Constrained, Unprivileged, Privileged, Tcb, Bootloader, Tee, Se, Other:
-				return true
-			}
-			panic(fmt.Errorf("Invalid privileged level in fuzz config in %s", moduleName))
+		if !config.Vector.isValidVector() {
+			panic(fmt.Errorf("Invalid vector in fuzz config in %s", moduleName))
 		}
-		return true
-	} else {
-		return false
+
+		if !config.Service_privilege.isValidServicePrivilege() {
+			panic(fmt.Errorf("Invalid service_privilege in fuzz config in %s", moduleName))
+		}
+
+		if !config.Users.isValidUserData() {
+			panic(fmt.Errorf("Invalid users (user_data) in fuzz config in %s", moduleName))
+		}
+
+		if !config.Fuzzed_code_usage.isValidFuzzedCodeUsage() {
+			panic(fmt.Errorf("Invalid fuzzed_code_usage in fuzz config in %s", moduleName))
+		}
+
+		if !config.Automatically_route_to.isValidAutomaticallyRouteTo() {
+			panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName))
+		}
 	}
+	return true
 }
 
 type FuzzConfig struct {
@@ -112,18 +292,23 @@
 	Cc []string `json:"cc,omitempty"`
 	// A brief description of what the fuzzed code does.
 	Description string `json:"description,omitempty"`
-	// Can this code be triggered remotely or only locally.
-	Remotely_accessible *bool `json:"remotely_accessible,omitempty"`
-	// Is the fuzzed code host only, i.e. test frameworks or support utilities.
-	Host_only *bool `json:"host_only,omitempty"`
+	// Whether the code being fuzzed is remotely accessible or requires privileges
+	// to access locally.
+	Vector Vector `json:"vector,omitempty"`
+	// How privileged the service being fuzzed is.
+	Service_privilege ServicePrivilege `json:"service_privilege,omitempty"`
+	// Whether the service being fuzzed handles data from multiple users or only
+	// a single one.
+	Users UserData `json:"users,omitempty"`
+	// Specifies the use state of the code being fuzzed. This state factors into
+	// how an issue is handled.
+	Fuzzed_code_usage FuzzedCodeUsage `json:"fuzzed_code_usage,omitempty"`
+	// Comment describing how we came to these settings for this fuzzer.
+	Config_comment string
+	// Which team to route this to, if it should be routed automatically.
+	Automatically_route_to AutomaticallyRouteTo `json:"automatically_route_to,omitempty"`
 	// Can third party/untrusted apps supply data to fuzzed code.
 	Untrusted_data *bool `json:"untrusted_data,omitempty"`
-	// Is the code being fuzzed in a privileged, constrained or any other
-	// context from:
-	// https://source.android.com/security/overview/updates-resources#context_types.
-	Privilege_level PrivilegedLevel `json:"privilege_level,omitempty"`
-	// Is the fuzzed code isolated or can it be called by multiple users/processes.
-	Isolated *bool `json:"users_isolation,omitempty"`
 	// When code was released or will be released.
 	Production_date string `json:"production_date,omitempty"`
 	// Prevents critical service functionality like phone calls, bluetooth, etc.
diff --git a/java/base.go b/java/base.go
index cce06a4..e7e3d8f 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1487,7 +1487,14 @@
 			}
 			// Dex compilation
 			var dexOutputFile android.OutputPath
-			dexOutputFile = j.dexer.compileDex(ctx, flags, j.MinSdkVersion(ctx), implementationAndResourcesJar, jarName)
+			params := &compileDexParams{
+				flags:         flags,
+				sdkVersion:    j.SdkVersion(ctx),
+				minSdkVersion: j.MinSdkVersion(ctx),
+				classesJar:    implementationAndResourcesJar,
+				jarName:       jarName,
+			}
+			dexOutputFile = j.dexer.compileDex(ctx, params)
 			if ctx.Failed() {
 				return
 			}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 101d3ca..585f818 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -1291,7 +1291,7 @@
 		}
 		return bootImageFiles
 	} else {
-		if profile == nil {
+		if profile == nil && imageConfig.isProfileGuided() {
 			ctx.ModuleErrorf("Unable to produce boot image files: neither boot image files nor profiles exists in the prebuilt apex")
 			return bootImageOutputs{}
 		}
diff --git a/java/dex.go b/java/dex.go
index a8dd375..7b6a99a 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -184,7 +184,7 @@
 		"r8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, []string{"implicits"})
 
 func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
-	minSdkVersion android.SdkSpec) (flags []string, deps android.Paths) {
+	dexParams *compileDexParams) (flags []string, deps android.Paths) {
 
 	flags = d.dexProperties.Dxflags
 	// Translate all the DX flags to D8 ones until all the build files have been migrated
@@ -213,11 +213,11 @@
 	// Note: Targets with a min SDK kind of core_platform (e.g., framework.jar) or unspecified (e.g.,
 	// services.jar), are not classified as stable, which is WAI.
 	// TODO(b/232073181): Expand to additional min SDK cases after validation.
-	if !minSdkVersion.Stable() {
+	if !dexParams.sdkVersion.Stable() {
 		flags = append(flags, "--android-platform-build")
 	}
 
-	effectiveVersion, err := minSdkVersion.EffectiveVersion(ctx)
+	effectiveVersion, err := dexParams.minSdkVersion.EffectiveVersion(ctx)
 	if err != nil {
 		ctx.PropertyErrorf("min_sdk_version", "%s", err)
 	}
@@ -340,20 +340,27 @@
 	return r8Flags, r8Deps
 }
 
-func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, minSdkVersion android.SdkSpec,
-	classesJar android.Path, jarName string) android.OutputPath {
+type compileDexParams struct {
+	flags         javaBuilderFlags
+	sdkVersion    android.SdkSpec
+	minSdkVersion android.SdkSpec
+	classesJar    android.Path
+	jarName       string
+}
+
+func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) android.OutputPath {
 
 	// Compile classes.jar into classes.dex and then javalib.jar
-	javalibJar := android.PathForModuleOut(ctx, "dex", jarName).OutputPath
+	javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
 	outDir := android.PathForModuleOut(ctx, "dex")
-	tmpJar := android.PathForModuleOut(ctx, "withres-withoutdex", jarName)
+	tmpJar := android.PathForModuleOut(ctx, "withres-withoutdex", dexParams.jarName)
 
 	zipFlags := "--ignore_missing_files"
 	if proptools.Bool(d.dexProperties.Uncompress_dex) {
 		zipFlags += " -L 0"
 	}
 
-	commonFlags, commonDeps := d.dexCommonFlags(ctx, minSdkVersion)
+	commonFlags, commonDeps := d.dexCommonFlags(ctx, dexParams)
 
 	// Exclude kotlinc generated files when "exclude_kotlinc_generated_files" is set to true.
 	mergeZipsFlags := ""
@@ -372,7 +379,7 @@
 			android.ModuleNameWithPossibleOverride(ctx), "unused.txt")
 		proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip")
 		d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
-		r8Flags, r8Deps := d.r8Flags(ctx, flags)
+		r8Flags, r8Deps := d.r8Flags(ctx, dexParams.flags)
 		r8Deps = append(r8Deps, commonDeps...)
 		rule := r8
 		args := map[string]string{
@@ -396,12 +403,12 @@
 			Description:     "r8",
 			Output:          javalibJar,
 			ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip},
-			Input:           classesJar,
+			Input:           dexParams.classesJar,
 			Implicits:       r8Deps,
 			Args:            args,
 		})
 	} else {
-		d8Flags, d8Deps := d8Flags(flags)
+		d8Flags, d8Deps := d8Flags(dexParams.flags)
 		d8Deps = append(d8Deps, commonDeps...)
 		rule := d8
 		if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
@@ -411,7 +418,7 @@
 			Rule:        rule,
 			Description: "d8",
 			Output:      javalibJar,
-			Input:       classesJar,
+			Input:       dexParams.classesJar,
 			Implicits:   d8Deps,
 			Args: map[string]string{
 				"d8Flags":        strings.Join(append(commonFlags, d8Flags...), " "),
@@ -423,7 +430,7 @@
 		})
 	}
 	if proptools.Bool(d.dexProperties.Uncompress_dex) {
-		alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName).OutputPath
+		alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath
 		TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
 		javalibJar = alignedJavalibJar
 	}
diff --git a/java/dex_test.go b/java/dex_test.go
index dc85f9e..97fc3d0 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -43,6 +43,7 @@
 			name: "core_platform_app",
 			srcs: ["foo.java"],
 			sdk_version: "core_platform",
+			min_sdk_version: "31",
 		}
 
 		java_library {
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 3effff6..40aad06 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -287,6 +287,9 @@
 
 	// Path of the preloaded classes file.
 	preloadedClassesFile string
+
+	// The "--compiler-filter" argument.
+	compilerFilter string
 }
 
 // Target-dependent description of a boot image.
@@ -443,6 +446,10 @@
 		append(imageLocationsOnDevice, dexpreopt.PathStringToLocation(image.imagePathOnDevice, image.target.Arch.ArchType))
 }
 
+func (image *bootImageConfig) isProfileGuided() bool {
+	return image.compilerFilter == "speed-profile"
+}
+
 func dexpreoptBootJarsFactory() android.SingletonModule {
 	m := &dexpreoptBootJars{}
 	android.InitAndroidModule(m)
@@ -721,11 +728,13 @@
 		cmd.FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress())
 	}
 
-	// We always expect a preloaded classes file to be available. However, if we cannot find it, it's
-	// OK to not pass the flag to dex2oat.
-	preloadedClassesPath := android.ExistentPathForSource(ctx, image.preloadedClassesFile)
-	if preloadedClassesPath.Valid() {
-		cmd.FlagWithInput("--preloaded-classes=", preloadedClassesPath.Path())
+	if len(image.preloadedClassesFile) > 0 {
+		// We always expect a preloaded classes file to be available. However, if we cannot find it, it's
+		// OK to not pass the flag to dex2oat.
+		preloadedClassesPath := android.ExistentPathForSource(ctx, image.preloadedClassesFile)
+		if preloadedClassesPath.Valid() {
+			cmd.FlagWithInput("--preloaded-classes=", preloadedClassesPath.Path())
+		}
 	}
 
 	cmd.
@@ -743,7 +752,8 @@
 		FlagWithArg("--android-root=", global.EmptyDirectory).
 		FlagWithArg("--no-inline-from=", "core-oj.jar").
 		Flag("--force-determinism").
-		Flag("--abort-on-hard-verifier-error")
+		Flag("--abort-on-hard-verifier-error").
+		FlagWithArg("--compiler-filter=", image.compilerFilter)
 
 	// Use the default variant/features for host builds.
 	// The map below contains only device CPU info (which might be x86 on some devices).
@@ -828,6 +838,10 @@
 Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
 
 func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
+	if !image.isProfileGuided() {
+		return nil
+	}
+
 	globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
 	global := dexpreopt.GetGlobalConfig(ctx)
 
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 4d0bd09..2975130 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -63,6 +63,7 @@
 			profileInstallPathInApex: "etc/boot-image.prof",
 			modules:                  artModules,
 			preloadedClassesFile:     "art/build/boot/preloaded-classes",
+			compilerFilter:           "speed-profile",
 		}
 
 		// Framework config for the boot image extension.
@@ -76,6 +77,7 @@
 			installDirOnDevice:   frameworkSubdir,
 			modules:              frameworkModules,
 			preloadedClassesFile: "frameworks/base/config/preloaded-classes",
+			compilerFilter:       "speed-profile",
 		}
 
 		return map[string]*bootImageConfig{
diff --git a/java/java.go b/java/java.go
index c2fcccf..27b2a6e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2067,7 +2067,15 @@
 			j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
 
 			var dexOutputFile android.OutputPath
-			dexOutputFile = j.dexer.compileDex(ctx, flags, j.MinSdkVersion(ctx), outputFile, jarName)
+			dexParams := &compileDexParams{
+				flags:         flags,
+				sdkVersion:    j.SdkVersion(ctx),
+				minSdkVersion: j.MinSdkVersion(ctx),
+				classesJar:    outputFile,
+				jarName:       jarName,
+			}
+
+			dexOutputFile = j.dexer.compileDex(ctx, dexParams)
 			if ctx.Failed() {
 				return
 			}
@@ -2807,6 +2815,9 @@
 		if sdkVersion.Kind == android.SdkPublic && sdkVersion.ApiLevel == android.FutureApiLevel {
 			// TODO(b/220869005) remove forced dependency on current public android.jar
 			deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import"))
+		} else if sdkVersion.Kind == android.SdkSystem && sdkVersion.ApiLevel == android.FutureApiLevel {
+			// TODO(b/215230098) remove forced dependency on current public android.jar
+			deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:system_current_android_sdk_java_import"))
 		}
 	} else if !deps.IsEmpty() {
 		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 878f896..8cec918 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -313,7 +313,7 @@
 
 func (b *bindgenDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
 	deps = b.BaseSourceProvider.SourceProviderDeps(ctx, deps)
-	if ctx.toolchain().Bionic() {
+	if ctx.toolchain().Bionic() && !ctx.RustModule().compiler.noStdlibs() {
 		deps = bionicDeps(ctx, deps, false)
 	} else if ctx.Os() == android.LinuxMusl {
 		deps = muslDeps(ctx, deps, false)
diff --git a/rust/compiler.go b/rust/compiler.go
index 31acd49..06ae12f 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -269,6 +269,11 @@
 func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags {
 	if ctx.RustModule().UseVndk() {
 		compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vndk")
+		if ctx.RustModule().InVendor() {
+			compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vendor")
+		} else if ctx.RustModule().InProduct() {
+			compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_product")
+		}
 	}
 
 	flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...)
diff --git a/rust/config/global.go b/rust/config/global.go
index ef428b8..0dface4 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.66.1"
+	RustDefaultVersion = "1.67.1"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2021"
 	Stdlibs            = []string{
diff --git a/rust/image_test.go b/rust/image_test.go
index 8185872..fb4d9c1 100644
--- a/rust/image_test.go
+++ b/rust/image_test.go
@@ -53,6 +53,7 @@
 				crate_name: "foo",
 				srcs: ["foo.rs"],
 				vendor_available: true,
+				product_available: true,
 			}
 		`)
 
@@ -61,6 +62,35 @@
 	if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vndk'") {
 		t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
 	}
+	if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vendor'") {
+		t.Errorf("missing \"--cfg 'android_vendor'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
+	}
+	if strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_product'") {
+		t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
+	}
+
+	product := ctx.ModuleForTests("libfoo", "android_product.29_arm64_armv8-a_static").Rule("rustc")
+	if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vndk'") {
+		t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
+	}
+	if strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vendor'") {
+		t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
+	}
+	if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_product'") {
+		t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
+	}
+
+	system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Rule("rustc")
+	if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vndk'") {
+		t.Errorf("unexpected \"--cfg 'android_vndk'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"])
+	}
+	if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vendor'") {
+		t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"])
+	}
+	if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_product'") {
+		t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo system variant, rustcFlags: %#v", product.Args["rustcFlags"])
+	}
+
 }
 
 // Test that cc modules can link against vendor_ramdisk_available rust_ffi_static libraries.