Merge "Retain concrete overrides of abstract methods by default" into main
diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go
index 48cfb76..79573c7 100644
--- a/aconfig/java_aconfig_library.go
+++ b/aconfig/java_aconfig_library.go
@@ -58,6 +58,8 @@
 
 	// Add aconfig-annotations-lib as a dependency for the optimization / code stripping annotations
 	module.AddSharedLibrary("aconfig-annotations-lib")
+	// TODO(b/303773055): Remove the annotation after access issue is resolved.
+	module.AddSharedLibrary("unsupportedappusage")
 }
 
 func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(module *java.GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 16e2328..5354611 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -350,6 +350,8 @@
 		"packages/modules/NetworkStack/common/captiveportal": Bp2BuildDefaultTrue,
 		"packages/modules/NeuralNetworks/apex":               Bp2BuildDefaultTrue,
 		"packages/modules/NeuralNetworks/apex/testing":       Bp2BuildDefaultTrue,
+		"packages/modules/SdkExtensions/gen_sdk":             Bp2BuildDefaultTrue,
+		"packages/modules/common/proto":                      Bp2BuildDefaultTrue,
 		"packages/providers/MediaProvider/tools/dialogs":     Bp2BuildDefaultFalse, // TODO(b/242834374)
 		"packages/screensavers/Basic":                        Bp2BuildDefaultTrue,
 		"packages/services/Car/tests/SampleRearViewCamera":   Bp2BuildDefaultFalse, // TODO(b/242834321)
@@ -1088,7 +1090,7 @@
 		"versioner", // TODO(b/228313961):  depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
 
 		// requires host tools for apexer
-		"apexer_test", "apexer_test_host_tools", "host_apex_verifier",
+		"apexer_test", "apexer_test_host_tools", "host_apex_verifier", "host-apex-verifier",
 
 		// java bugs
 		"libbase_ndk",           // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
diff --git a/android/bazel.go b/android/bazel.go
index 0c65945..202fc48 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -549,7 +549,8 @@
 	// the same name are both allowlisted. This cannot be applied to all the *_import
 	// module types. For example, android_library_import has to use original module
 	// name here otherwise the *-nodeps targets cannot be handled correctly.
-	if strings.HasPrefix(p.moduleType, "java_import") {
+	// TODO(b/304385140): remove this special casing
+	if p.moduleType == "java_import" || p.moduleType == "java_import_host" {
 		moduleName = module.Name()
 	}
 
@@ -633,9 +634,6 @@
 
 func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("bp2build_conversion", bp2buildConversionMutator).Parallel()
-}
-
-func registerBp2buildDepsMutator(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("bp2build_deps", bp2buildDepsMutator).Parallel()
 }
 
diff --git a/android/config.go b/android/config.go
index 04b43ac..2930c86 100644
--- a/android/config.go
+++ b/android/config.go
@@ -306,9 +306,6 @@
 	// in tests when a path doesn't exist.
 	TestAllowNonExistentPaths bool
 
-	// If true, register the "bp2build_deps" mutator in the mutator pipeline.
-	Bp2buildDepsMutator bool
-
 	// The list of files that when changed, must invalidate soong_build to
 	// regenerate build.ninja.
 	ninjaFileDepsSet sync.Map
diff --git a/android/mutator.go b/android/mutator.go
index 3d59655..067d6c3 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -35,9 +35,6 @@
 // RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
 func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
 	bp2buildMutators := append(preArchMutators, registerBp2buildConversionMutator)
-	if ctx.config.Bp2buildDepsMutator {
-		bp2buildMutators = append(bp2buildMutators, registerBp2buildDepsMutator)
-	}
 	registerMutatorsForBazelConversion(ctx, bp2buildMutators)
 }
 
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 8e51d98..0a4d749 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1058,50 +1058,6 @@
 				}),
 			},
 		},
-		{
-			Description:                "depends_on_other_unconverted_module_error",
-			ModuleTypeUnderTest:        "filegroup",
-			ModuleTypeUnderTestFactory: android.FileGroupFactory,
-			UnconvertedDepsMode:        errorModulesUnconvertedDeps,
-			Blueprint: `filegroup {
-    name: "foobar",
-    srcs: [
-        ":foo",
-        "c",
-    ],
-    bazel_module: { bp2build_available: true },
-}`,
-			ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on unconverted modules: foo`),
-			Filesystem: map[string]string{
-				"other/Android.bp": `filegroup {
-    name: "foo",
-    srcs: ["a", "b"],
-}`,
-			},
-		},
-		{
-			Description:                "depends_on_other_missing_module_error",
-			ModuleTypeUnderTest:        "filegroup",
-			ModuleTypeUnderTestFactory: android.FileGroupFactory,
-			UnconvertedDepsMode:        errorModulesUnconvertedDeps,
-			Blueprint: `filegroup {
-    name: "foobar",
-    srcs: [
-        "c",
-        "//other:foo",
-        "//other:goo",
-    ],
-    bazel_module: { bp2build_available: true },
-}`,
-			ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on missing modules: //other:goo`),
-			Filesystem: map[string]string{"other/Android.bp": `filegroup {
-    name: "foo",
-    srcs: ["a"],
-    bazel_module: { bp2build_available: true },
-}
-`,
-			},
-		},
 	}
 
 	for _, testCase := range testCases {
@@ -2119,7 +2075,6 @@
 		Blueprint:            bp,
 		ExpectedBazelTargets: expectedBazelTargets,
 		Description:          "Skipping conversion of a target with missing transitive dep",
-		DepsMutator:          true,
 	})
 }
 
@@ -2157,7 +2112,6 @@
 		Blueprint:            bp,
 		ExpectedBazelTargets: expectedBazelTargets,
 		Description:          "Skipping conversion of a target with missing direct dep",
-		DepsMutator:          true,
 	})
 }
 
@@ -2180,7 +2134,6 @@
 		Blueprint:            bp,
 		ExpectedBazelTargets: []string{},
 		Description:          "Skipping conversion of a target with unconverted direct dep",
-		DepsMutator:          true,
 	})
 }
 
@@ -2219,7 +2172,6 @@
 		Blueprint:            bp,
 		ExpectedBazelTargets: expectedBazelTargets,
 		Description:          "Skipping conversion of a target with unconverted transitive dep",
-		DepsMutator:          true,
 	})
 }
 
@@ -2259,7 +2211,6 @@
 		Blueprint:               bp,
 		ExpectedBazelTargets:    expectedBazelTargets,
 		Description:             "Convert target with already-existing build dep",
-		DepsMutator:             true,
 	})
 }
 
@@ -2301,6 +2252,5 @@
 		Blueprint:               bp,
 		ExpectedBazelTargets:    expectedBazelTargets,
 		Description:             "Convert target with dep on libc",
-		DepsMutator:             true,
 	})
 }
diff --git a/bp2build/sh_test_conversion_test.go b/bp2build/sh_test_conversion_test.go
index e99d566..48fd077 100644
--- a/bp2build/sh_test_conversion_test.go
+++ b/bp2build/sh_test_conversion_test.go
@@ -22,11 +22,18 @@
 )
 
 func TestShTestSimple(t *testing.T) {
-	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
-		Description:                "sh_test test",
-		ModuleTypeUnderTest:        "sh_test",
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	}, Bp2buildTestCase{
+		Description:         "sh_test test",
+		ModuleTypeUnderTest: "sh_test",
+		StubbedBuildDefinitions: []string{"android.hardware.bluetooth@1.1-service.sim",
+			"android.hardware.bluetooth@1.1-impl-sim", "libc++", "libcrypto"},
 		ModuleTypeUnderTestFactory: sh.ShTestFactory,
-		Blueprint: `sh_test{
+		Blueprint: simpleModule("filegroup", "android.hardware.bluetooth@1.1-service.sim") +
+			simpleModule("filegroup", "android.hardware.bluetooth@1.1-impl-sim") +
+			simpleModule("filegroup", "libc++") +
+			simpleModule("filegroup", "libcrypto") + `sh_test{
     name: "sts-rootcanal-sidebins",
     src: "empty.sh",
     test_suites: [
@@ -47,28 +54,37 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
-				"srcs": `["empty.sh"]`,
+				"srcs":    `["empty.sh"]`,
+				"runs_on": `["device"]`,
 				"data": `[
         "android.hardware.bluetooth@1.1-service.sim.rc",
-        "android.hardware.bluetooth@1.1-service.sim",
-        "android.hardware.bluetooth@1.1-impl-sim",
-        "libc++",
-        "libcrypto",
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+        ":libc++",
+        ":libcrypto",
     ]`,
-				"test_config":          `"art-gtests-target-install-apex.xml"`,
-				"test_config_template": `":art-run-test-target-template"`,
-				"auto_gen_config":      "False",
-				"tags":                 `["no-remote"]`,
+				"data_bins": `[
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+    ]`,
+				"tags": `["no-remote"]`,
 			})},
 	})
 }
 
 func TestShTestHostSimple(t *testing.T) {
-	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
-		Description:                "sh_test_host test",
-		ModuleTypeUnderTest:        "sh_test_host",
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	}, Bp2buildTestCase{
+		Description:         "sh_test_host test",
+		ModuleTypeUnderTest: "sh_test_host",
+		StubbedBuildDefinitions: []string{"android.hardware.bluetooth@1.1-service.sim",
+			"android.hardware.bluetooth@1.1-impl-sim", "libc++", "libcrypto"},
 		ModuleTypeUnderTestFactory: sh.ShTestHostFactory,
-		Blueprint: `sh_test_host{
+		Blueprint: simpleModule("filegroup", "android.hardware.bluetooth@1.1-service.sim") +
+			simpleModule("filegroup", "android.hardware.bluetooth@1.1-impl-sim") +
+			simpleModule("filegroup", "libc++") +
+			simpleModule("filegroup", "libcrypto") + `sh_test_host{
     name: "sts-rootcanal-sidebins",
     src: "empty.sh",
     test_suites: [
@@ -89,18 +105,20 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
-				"srcs": `["empty.sh"]`,
+				"srcs":    `["empty.sh"]`,
+				"runs_on": `["host_without_device"]`,
 				"data": `[
         "android.hardware.bluetooth@1.1-service.sim.rc",
-        "android.hardware.bluetooth@1.1-service.sim",
-        "android.hardware.bluetooth@1.1-impl-sim",
-        "libc++",
-        "libcrypto",
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+        ":libc++",
+        ":libcrypto",
     ]`,
-				"tags":                 `["no-remote"]`,
-				"test_config":          `"art-gtests-target-install-apex.xml"`,
-				"test_config_template": `":art-run-test-target-template"`,
-				"auto_gen_config":      "False",
+				"data_bins": `[
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+    ]`,
+				"tags": `["no-remote"]`,
 				"target_compatible_with": `select({
         "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
         "//conditions:default": [],
@@ -109,12 +127,131 @@
 	})
 }
 
-func TestShTestSimpleUnset(t *testing.T) {
-	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
-		Description:                "sh_test test",
-		ModuleTypeUnderTest:        "sh_test",
+func TestShTestAutogen(t *testing.T) {
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	}, Bp2buildTestCase{
+		Description:         "sh_test test",
+		ModuleTypeUnderTest: "sh_test",
+		StubbedBuildDefinitions: []string{"android.hardware.bluetooth@1.1-service.sim",
+			"android.hardware.bluetooth@1.1-impl-sim", "libc++", "libcrypto", "art-run-test-target-template"},
 		ModuleTypeUnderTestFactory: sh.ShTestFactory,
-		Blueprint: `sh_test{
+		Blueprint: simpleModule("filegroup", "android.hardware.bluetooth@1.1-service.sim") +
+			simpleModule("filegroup", "android.hardware.bluetooth@1.1-impl-sim") +
+			simpleModule("filegroup", "libc++") +
+			simpleModule("filegroup", "libcrypto") +
+			simpleModule("filegroup", "art-run-test-target-template") + `sh_test{
+    name: "sts-rootcanal-sidebins",
+    src: "empty.sh",
+    test_suites: [
+        "sts",
+        "sts-lite",
+    ],
+    data_bins: [
+        "android.hardware.bluetooth@1.1-service.sim",
+        "android.hardware.bluetooth@1.1-impl-sim"
+    ],
+    data: ["android.hardware.bluetooth@1.1-service.sim.rc"],
+    data_libs: ["libc++","libcrypto"],
+		test_config: "art-gtests-target-install-apex.xml",
+		test_config_template: ":art-run-test-target-template",
+		auto_gen_config: true,
+    test_options:{tags: ["no-remote"],
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
+				"srcs":                      `["empty.sh"]`,
+				"runs_on":                   `["device"]`,
+				"auto_generate_test_config": "True",
+				"target_compatible_with":    `["//build/bazel/platforms/os:android"]`,
+				"template_test_config":      `":art-run-test-target-template"`,
+				"data": `[
+        "android.hardware.bluetooth@1.1-service.sim.rc",
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+        ":libc++",
+        ":libcrypto",
+    ]`,
+				"data_bins": `[
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+    ]`,
+				"tags": `["no-remote"]`,
+			})},
+	})
+}
+
+func TestShTestHostAutogen(t *testing.T) {
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	}, Bp2buildTestCase{
+		Description:         "sh_test_host test",
+		ModuleTypeUnderTest: "sh_test_host",
+		StubbedBuildDefinitions: []string{"android.hardware.bluetooth@1.1-service.sim",
+			"android.hardware.bluetooth@1.1-impl-sim", "libc++", "libcrypto", "art-run-test-target-template"},
+		ModuleTypeUnderTestFactory: sh.ShTestHostFactory,
+		Blueprint: simpleModule("filegroup", "android.hardware.bluetooth@1.1-service.sim") +
+			simpleModule("filegroup", "android.hardware.bluetooth@1.1-impl-sim") +
+			simpleModule("filegroup", "libc++") +
+			simpleModule("filegroup", "libcrypto") +
+			simpleModule("filegroup", "art-run-test-target-template") + `sh_test_host{
+    name: "sts-rootcanal-sidebins",
+    src: "empty.sh",
+    test_suites: [
+        "sts",
+        "sts-lite",
+    ],
+    data_bins: [
+        "android.hardware.bluetooth@1.1-service.sim",
+        "android.hardware.bluetooth@1.1-impl-sim"
+    ],
+    data: ["android.hardware.bluetooth@1.1-service.sim.rc"],
+    data_libs: ["libc++","libcrypto"],
+		test_config: "art-gtests-target-install-apex.xml",
+		test_config_template: ":art-run-test-target-template",
+		auto_gen_config: true,
+    test_options:{tags: ["no-remote"],
+	},
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
+				"srcs":                      `["empty.sh"]`,
+				"runs_on":                   `["host_without_device"]`,
+				"auto_generate_test_config": "True",
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+				"template_test_config": `":art-run-test-target-template"`,
+				"data": `[
+        "android.hardware.bluetooth@1.1-service.sim.rc",
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+        ":libc++",
+        ":libcrypto",
+    ]`,
+				"data_bins": `[
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+    ]`,
+				"tags": `["no-remote"]`,
+			})},
+	})
+}
+func TestShTestSimpleUnset(t *testing.T) {
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	}, Bp2buildTestCase{
+		Description:         "sh_test test",
+		ModuleTypeUnderTest: "sh_test",
+		StubbedBuildDefinitions: []string{"android.hardware.bluetooth@1.1-service.sim",
+			"android.hardware.bluetooth@1.1-impl-sim", "libc++", "libcrypto"},
+		ModuleTypeUnderTestFactory: sh.ShTestFactory,
+		Blueprint: simpleModule("filegroup", "android.hardware.bluetooth@1.1-service.sim") +
+			simpleModule("filegroup", "android.hardware.bluetooth@1.1-impl-sim") +
+			simpleModule("filegroup", "libc++") +
+			simpleModule("filegroup", "libcrypto") + `sh_test{
     name: "sts-rootcanal-sidebins",
     src: "empty.sh",
     test_suites: [
@@ -132,13 +269,18 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
-				"srcs": `["empty.sh"]`,
+				"srcs":    `["empty.sh"]`,
+				"runs_on": `["device"]`,
 				"data": `[
         "android.hardware.bluetooth@1.1-service.sim.rc",
-        "android.hardware.bluetooth@1.1-service.sim",
-        "android.hardware.bluetooth@1.1-impl-sim",
-        "libc++",
-        "libcrypto",
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+        ":libc++",
+        ":libcrypto",
+    ]`,
+				"data_bins": `[
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
     ]`,
 				"tags": `["no-remote"]`,
 			})},
@@ -146,11 +288,18 @@
 }
 
 func TestShTestHostSimpleUnset(t *testing.T) {
-	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	}, Bp2buildTestCase{
 		Description:                "sh_test_host test",
 		ModuleTypeUnderTest:        "sh_test_host",
 		ModuleTypeUnderTestFactory: sh.ShTestHostFactory,
-		Blueprint: `sh_test_host{
+		StubbedBuildDefinitions: []string{"android.hardware.bluetooth@1.1-service.sim",
+			"android.hardware.bluetooth@1.1-impl-sim", "libc++", "libcrypto"},
+		Blueprint: simpleModule("filegroup", "android.hardware.bluetooth@1.1-service.sim") +
+			simpleModule("filegroup", "android.hardware.bluetooth@1.1-impl-sim") +
+			simpleModule("filegroup", "libc++") +
+			simpleModule("filegroup", "libcrypto") + `sh_test_host{
     name: "sts-rootcanal-sidebins",
     src: "empty.sh",
     test_suites: [
@@ -168,13 +317,18 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
-				"srcs": `["empty.sh"]`,
+				"srcs":    `["empty.sh"]`,
+				"runs_on": `["host_without_device"]`,
 				"data": `[
         "android.hardware.bluetooth@1.1-service.sim.rc",
-        "android.hardware.bluetooth@1.1-service.sim",
-        "android.hardware.bluetooth@1.1-impl-sim",
-        "libc++",
-        "libcrypto",
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
+        ":libc++",
+        ":libcrypto",
+    ]`,
+				"data_bins": `[
+        ":android.hardware.bluetooth@1.1-service.sim",
+        ":android.hardware.bluetooth@1.1-impl-sim",
     ]`,
 				"tags": `["no-remote"]`,
 				"target_compatible_with": `select({
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 6907487..763cccc 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -124,12 +124,6 @@
 	// be merged with the generated BUILD file. This allows custom BUILD targets
 	// to be used in tests, or use BUILD files to draw package boundaries.
 	KeepBuildFileForDirs []string
-
-	// If true, the bp2build_deps mutator is used for this test. This is an
-	// experimental mutator that will disable modules which have transitive
-	// dependencies with no bazel definition.
-	// TODO: b/285631638 - Enable this feature by default.
-	DepsMutator bool
 }
 
 func RunBp2BuildTestCaseExtraContext(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), modifyContext func(ctx *android.TestContext), tc Bp2buildTestCase) {
@@ -140,11 +134,6 @@
 	if modifyContext != nil {
 		preparers = append(preparers, android.FixtureModifyContext(modifyContext))
 	}
-	if tc.DepsMutator {
-		preparers = append(preparers, android.FixtureModifyConfig(func(cfg android.Config) {
-			cfg.Bp2buildDepsMutator = true
-		}))
-	}
 	preparers = append(preparers, SetBp2BuildTestRunner)
 	bp2buildSetup := android.GroupFixturePreparers(
 		preparers...,
diff --git a/cc/afdo.go b/cc/afdo.go
index 23d196d..5c587c0 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -84,6 +84,7 @@
 		// 3. Make the profile searchable by the build system. So it's used the next time the binary
 		//	  is built.
 		flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
+		flags.Local.CFlags = append([]string{"-mllvm", "-enable-fs-discriminator=true"}, flags.Local.CFlags...)
 	}
 	if path := afdo.Properties.FdoProfilePath; path != nil {
 		// The flags are prepended to allow overriding.
diff --git a/cc/config/global.go b/cc/config/global.go
index 62b008b..f79d16a 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -248,6 +248,7 @@
 		"-Werror=fortify-source",
 
 		"-Werror=address-of-temporary",
+		"-Werror=incompatible-function-pointer-types",
 		"-Werror=null-dereference",
 		"-Werror=return-type",
 
@@ -324,10 +325,6 @@
 		"-fcommon",
 		// http://b/191699019
 		"-Wno-format-insufficient-args",
-		// http://b/296321145
-		// Indicates potential memory or stack corruption, so should be changed
-		// to a hard error. Currently triggered by some vendor code.
-		"-Wno-incompatible-function-pointer-types",
 		// http://b/296321508
 		// Introduced in response to a critical security vulnerability and
 		// should be a hard error - it requires only whitespace changes to fix.
diff --git a/java/java.go b/java/java.go
index cac49a2..35fd7c2 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1087,6 +1087,10 @@
 	return true
 }
 
+func (j *TestHost) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+	return ctx.DeviceConfig().NativeCoverageEnabled()
+}
+
 func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) {
 	if len(j.testHostProperties.Data_device_bins_first) > 0 {
 		deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
@@ -1689,6 +1693,12 @@
 
 	// Version of previously released API file for compatibility check.
 	Previous_api *string `android:"path"`
+
+	// java_system_modules module providing the jar to be added to the
+	// bootclasspath when compiling the stubs.
+	// The jar will also be passed to metalava as a classpath to
+	// generate compilable stubs.
+	System_modules *string
 }
 
 func ApiLibraryFactory() android.Module {
@@ -1708,7 +1718,8 @@
 }
 
 func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
-	srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand {
+	srcs android.Paths, homeDir android.WritablePath,
+	classpath android.Paths) *android.RuleBuilderCommand {
 	rule.Command().Text("rm -rf").Flag(homeDir.String())
 	rule.Command().Text("mkdir -p").Flag(homeDir.String())
 
@@ -1747,12 +1758,17 @@
 		FlagWithArg("--hide ", "InvalidNullabilityOverride").
 		FlagWithArg("--hide ", "ChangedDefault")
 
-	// The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
-	// classes on the classpath when an API file contains missing classes. However, as this command
-	// does not specify `--classpath` this is not needed for that. However, this is also used as a
-	// signal to the special metalava code for generating stubs from text files that it needs to add
-	// some additional items into the API (e.g. default constructors).
-	cmd.FlagWithArg("--api-class-resolution ", "api")
+	if len(classpath) == 0 {
+		// The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
+		// classes on the classpath when an API file contains missing classes. However, as this command
+		// does not specify `--classpath` this is not needed for that. However, this is also used as a
+		// signal to the special metalava code for generating stubs from text files that it needs to add
+		// some additional items into the API (e.g. default constructors).
+		cmd.FlagWithArg("--api-class-resolution ", "api")
+	} else {
+		cmd.FlagWithArg("--api-class-resolution ", "api:classpath")
+		cmd.FlagWithInputList("--classpath ", classpath, ":")
+	}
 
 	return cmd
 }
@@ -1815,6 +1831,9 @@
 	if al.properties.Full_api_surface_stub != nil {
 		ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub))
 	}
+	if al.properties.System_modules != nil {
+		ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules))
+	}
 }
 
 // Map where key is the api scope name and value is the int value
@@ -1854,6 +1873,7 @@
 	var classPaths android.Paths
 	var staticLibs android.Paths
 	var depApiSrcsStubsJar android.Path
+	var systemModulesPaths android.Paths
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		tag := ctx.OtherModuleDependencyTag(dep)
 		switch tag {
@@ -1872,6 +1892,9 @@
 		case depApiSrcsTag:
 			provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
 			depApiSrcsStubsJar = provider.HeaderJars[0]
+		case systemModulesTag:
+			module := dep.(SystemModulesProvider)
+			systemModulesPaths = append(systemModulesPaths, module.HeaderJars()...)
 		}
 	})
 
@@ -1885,7 +1908,7 @@
 		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
 	}
 
-	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
+	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths)
 
 	al.stubsFlags(ctx, cmd, stubsDir)
 
@@ -1917,6 +1940,7 @@
 		flags.javaVersion = getStubsJavaVersion()
 		flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
 		flags.classpath = classpath(classPaths)
+		flags.bootClasspath = classpath(systemModulesPaths)
 
 		annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
 
diff --git a/java/java_test.go b/java/java_test.go
index d51604a..6b8b735 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2447,3 +2447,39 @@
 		"default/java/api/module-lib-current.txt default/java/api/system-server-current.txt"
 	android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag)
 }
+
+func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForJavaTest,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		FixtureWithLastReleaseApis("foo"),
+		android.FixtureModifyConfig(func(config android.Config) {
+			config.SetApiLibraries([]string{"foo"})
+		}),
+		android.FixtureMergeMockFs(
+			map[string][]byte{
+				"A.java": nil,
+			},
+		),
+	).RunTestWithBp(t, `
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+		}
+		java_system_modules {
+			name: "baz",
+			libs: ["bar"],
+		}
+		java_sdk_library {
+			name: "foo",
+			srcs: ["A.java"],
+			system_modules: "baz",
+		}
+	`)
+	m := result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common")
+	manifest := m.Output("metalava.sbox.textproto")
+	sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+	manifestCommand := sboxProto.Commands[0].GetCommand()
+	classPathFlag := "--classpath __SBOX_SANDBOX_DIR__/out/.intermediates/bar/android_common/turbine-combined/bar.jar"
+	android.AssertStringDoesContain(t, "command expected to contain classpath flag", manifestCommand, classPathFlag)
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e410a41..f72c608 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1837,6 +1837,7 @@
 		Libs                  []string
 		Static_libs           []string
 		Full_api_surface_stub *string
+		System_modules        *string
 	}{}
 
 	props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
@@ -1875,6 +1876,8 @@
 		props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
 	}
 
+	props.System_modules = module.deviceProperties.System_modules
+
 	mctx.CreateModule(ApiLibraryFactory, &props)
 }
 
diff --git a/java/testing.go b/java/testing.go
index 98bea7f..4461351 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -73,10 +73,15 @@
 		// Needed for various deps defined in GatherRequiredDepsForTest()
 		defaultJavaDir + "/a.java":                        nil,
 		defaultJavaDir + "/api/current.txt":               nil,
+		defaultJavaDir + "/api/removed.txt":               nil,
 		defaultJavaDir + "/api/system-current.txt":        nil,
+		defaultJavaDir + "/api/system-removed.txt":        nil,
 		defaultJavaDir + "/api/test-current.txt":          nil,
+		defaultJavaDir + "/api/test-removed.txt":          nil,
 		defaultJavaDir + "/api/module-lib-current.txt":    nil,
+		defaultJavaDir + "/api/module-lib-removed.txt":    nil,
 		defaultJavaDir + "/api/system-server-current.txt": nil,
+		defaultJavaDir + "/api/system-server-removed.txt": nil,
 
 		// Needed for R8 rules on apps
 		"build/make/core/proguard.flags":             nil,
@@ -410,6 +415,7 @@
 		"stub-annotations",
 
 		"aconfig-annotations-lib",
+		"unsupportedappusage",
 	}
 
 	for _, extra := range extraModules {
@@ -424,80 +430,96 @@
 		`, extra)
 	}
 
-	type apiContributionStruct struct {
-		name       string
-		apiSurface string
-		apiFile    string
+	type droidstubsStruct struct {
+		name        string
+		apiSurface  string
+		apiFile     string
+		removedFile string
 	}
 
-	var publicApiContribution = apiContributionStruct{
-		name:       "api-stubs-docs-non-updatable.api.contribution",
-		apiSurface: "public",
-		apiFile:    "api/current.txt",
+	var publicDroidstubs = droidstubsStruct{
+		name:        "api-stubs-docs-non-updatable",
+		apiSurface:  "public",
+		apiFile:     "api/current.txt",
+		removedFile: "api/removed.txt",
 	}
-	var systemApiContribution = apiContributionStruct{
-		name:       "system-api-stubs-docs-non-updatable.api.contribution",
-		apiSurface: "system",
-		apiFile:    "api/system-current.txt",
+	var systemDroidstubs = droidstubsStruct{
+		name:        "system-api-stubs-docs-non-updatable",
+		apiSurface:  "system",
+		apiFile:     "api/system-current.txt",
+		removedFile: "api/system-removed.txt",
 	}
-	var testApiContribution = apiContributionStruct{
-		name:       "test-api-stubs-docs-non-updatable.api.contribution",
-		apiSurface: "test",
-		apiFile:    "api/test-current.txt",
+	var testDroidstubs = droidstubsStruct{
+		name:        "test-api-stubs-docs-non-updatable",
+		apiSurface:  "test",
+		apiFile:     "api/test-current.txt",
+		removedFile: "api/test-removed.txt",
 	}
-	var moduleLibApiContribution = apiContributionStruct{
-		name:       "module-lib-api-stubs-docs-non-updatable.api.contribution",
-		apiSurface: "module-lib",
-		apiFile:    "api/module-lib-current.txt",
+	var moduleLibDroidstubs = droidstubsStruct{
+		name:        "module-lib-api-stubs-docs-non-updatable",
+		apiSurface:  "module-lib",
+		apiFile:     "api/module-lib-current.txt",
+		removedFile: "api/module-lib-removed.txt",
 	}
-	var systemServerApiContribution = apiContributionStruct{
+	var systemServerDroidstubs = droidstubsStruct{
 		// This module does not exist but is named this way for consistency
-		name:       "system-server-api-stubs-docs-non-updatable.api.contribution",
-		apiSurface: "system-server",
-		apiFile:    "api/system-server-current.txt",
+		name:        "system-server-api-stubs-docs-non-updatable",
+		apiSurface:  "system-server",
+		apiFile:     "api/system-server-current.txt",
+		removedFile: "api/system-server-removed.txt",
 	}
-	var apiContributionStructs = []apiContributionStruct{
-		publicApiContribution,
-		systemApiContribution,
-		testApiContribution,
-		moduleLibApiContribution,
-		systemServerApiContribution,
+	var droidstubsStructs = []droidstubsStruct{
+		publicDroidstubs,
+		systemDroidstubs,
+		testDroidstubs,
+		moduleLibDroidstubs,
+		systemServerDroidstubs,
 	}
 
-	extraApiLibraryModules := map[string]apiContributionStruct{
-		"android_stubs_current.from-text":                  publicApiContribution,
-		"android_system_stubs_current.from-text":           systemApiContribution,
-		"android_test_stubs_current.from-text":             testApiContribution,
-		"android_module_lib_stubs_current.from-text":       moduleLibApiContribution,
-		"android_module_lib_stubs_current_full.from-text":  moduleLibApiContribution,
-		"android_system_server_stubs_current.from-text":    systemServerApiContribution,
-		"core.current.stubs.from-text":                     publicApiContribution,
-		"legacy.core.platform.api.stubs.from-text":         publicApiContribution,
-		"stable.core.platform.api.stubs.from-text":         publicApiContribution,
-		"core-lambda-stubs.from-text":                      publicApiContribution,
-		"android-non-updatable.stubs.from-text":            publicApiContribution,
-		"android-non-updatable.stubs.system.from-text":     systemApiContribution,
-		"android-non-updatable.stubs.test.from-text":       testApiContribution,
-		"android-non-updatable.stubs.module_lib.from-text": moduleLibApiContribution,
+	extraApiLibraryModules := map[string]droidstubsStruct{
+		"android_stubs_current.from-text":                  publicDroidstubs,
+		"android_system_stubs_current.from-text":           systemDroidstubs,
+		"android_test_stubs_current.from-text":             testDroidstubs,
+		"android_module_lib_stubs_current.from-text":       moduleLibDroidstubs,
+		"android_module_lib_stubs_current_full.from-text":  moduleLibDroidstubs,
+		"android_system_server_stubs_current.from-text":    systemServerDroidstubs,
+		"core.current.stubs.from-text":                     publicDroidstubs,
+		"legacy.core.platform.api.stubs.from-text":         publicDroidstubs,
+		"stable.core.platform.api.stubs.from-text":         publicDroidstubs,
+		"core-lambda-stubs.from-text":                      publicDroidstubs,
+		"android-non-updatable.stubs.from-text":            publicDroidstubs,
+		"android-non-updatable.stubs.system.from-text":     systemDroidstubs,
+		"android-non-updatable.stubs.test.from-text":       testDroidstubs,
+		"android-non-updatable.stubs.module_lib.from-text": moduleLibDroidstubs,
 	}
 
-	for _, apiContribution := range apiContributionStructs {
+	for _, droidstubs := range droidstubsStructs {
 		bp += fmt.Sprintf(`
-			java_api_contribution {
+			droidstubs {
 				name: "%s",
 				api_surface: "%s",
-				api_file: "%s",
+				check_api: {
+					current: {
+						api_file: "%s",
+						removed_api_file: "%s",
+					}
+				}
 			}
-		`, apiContribution.name, apiContribution.apiSurface, apiContribution.apiFile)
+		`,
+			droidstubs.name,
+			droidstubs.apiSurface,
+			droidstubs.apiFile,
+			droidstubs.removedFile,
+		)
 	}
 
-	for libName, apiContribution := range extraApiLibraryModules {
+	for libName, droidstubs := range extraApiLibraryModules {
 		bp += fmt.Sprintf(`
             java_api_library {
                 name: "%s",
                 api_contributions: ["%s"],
             }
-        `, libName, apiContribution.name)
+        `, libName, droidstubs.name+".api.contribution")
 	}
 
 	bp += `
@@ -552,7 +574,7 @@
 	return bp
 }
 
-func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string) []string {
 	t.Helper()
 	module := ctx.ModuleForTests(name, variant).Module()
 	deps := []string{}
@@ -561,11 +583,29 @@
 	})
 	sort.Strings(deps)
 
+	return deps
+}
+
+// CheckModuleDependencies checks if the expected dependencies of the module are
+// identical to the actual dependencies.
+func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+	deps := getModuleDependencies(t, ctx, name, variant)
+
 	if actual := deps; !reflect.DeepEqual(expected, actual) {
 		t.Errorf("expected %#q, found %#q", expected, actual)
 	}
 }
 
+// CheckModuleHasDependency returns true if the module depends on the expected dependency.
+func CheckModuleHasDependency(t *testing.T, ctx *android.TestContext, name, variant string, expected string) bool {
+	for _, dep := range getModuleDependencies(t, ctx, name, variant) {
+		if dep == expected {
+			return true
+		}
+	}
+	return false
+}
+
 // CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by
 // the platform-bootclasspath module.
 func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index a80a587..ffe532f 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -124,18 +124,20 @@
 		ctx.PropertyErrorf("c_std", "c_std and cpp_std cannot both be defined at the same time.")
 	}
 
-	if String(b.ClangProperties.Cpp_std) != "" {
+	if b.ClangProperties.Cpp_std != nil {
+		isCpp = true
 		if String(b.ClangProperties.Cpp_std) == "experimental" {
 			stdVersion = cc_config.ExperimentalCppStdVersion
-		} else if String(b.ClangProperties.Cpp_std) == "default" {
+		} else if String(b.ClangProperties.Cpp_std) == "default" || String(b.ClangProperties.Cpp_std) == "" {
 			stdVersion = cc_config.CppStdVersion
 		} else {
 			stdVersion = String(b.ClangProperties.Cpp_std)
 		}
 	} else if b.ClangProperties.C_std != nil {
+		isCpp = false
 		if String(b.ClangProperties.C_std) == "experimental" {
 			stdVersion = cc_config.ExperimentalCStdVersion
-		} else if String(b.ClangProperties.C_std) == "default" {
+		} else if String(b.ClangProperties.C_std) == "default" || String(b.ClangProperties.C_std) == "" {
 			stdVersion = cc_config.CStdVersion
 		} else {
 			stdVersion = String(b.ClangProperties.C_std)
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index 12cdb3c..0ba0ff8 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -115,7 +115,7 @@
 	ctx := testRust(t, `
 		rust_bindgen {
 			name: "libbindgen_cstd",
-			wrapper_src: "src/any.h",
+			wrapper_src: "src/any.hpp",
 			crate_name: "bindgen",
 			stem: "libbindgen",
 			source_stem: "bindings",
@@ -141,6 +141,16 @@
 	if !strings.Contains(libbindgen_cppstd.Args["cflags"], "-std=foo") {
 		t.Errorf("cpp_std value not passed in to rust_bindgen as a clang flag")
 	}
+
+	// Make sure specifying cpp_std emits the '-x c++' flag
+	if !strings.Contains(libbindgen_cppstd.Args["cflags"], "-x c++") {
+		t.Errorf("Setting cpp_std should cause the '-x c++' flag to be emitted")
+	}
+
+	// Make sure specifying c_std omits the '-x c++' flag
+	if strings.Contains(libbindgen_cstd.Args["cflags"], "-x c++") {
+		t.Errorf("Setting c_std should not cause the '-x c++' flag to be emitted")
+	}
 }
 
 func TestBindgenDisallowedFlags(t *testing.T) {
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 79a885f..2e869f4 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -575,12 +575,12 @@
 }
 
 type bazelShTestAttributes struct {
-	Srcs                 bazel.LabelListAttribute
-	Data                 bazel.LabelListAttribute
-	Tags                 bazel.StringListAttribute
-	Test_config          *string
-	Test_config_template *string
-	Auto_gen_config      *bool
+	Srcs      bazel.LabelListAttribute
+	Data      bazel.LabelListAttribute
+	Data_bins bazel.LabelListAttribute
+	Tags      bazel.StringListAttribute
+	Runs_on   bazel.StringListAttribute
+	tradefed.TestConfigAttributes
 }
 
 func (m *ShBinary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
@@ -615,28 +615,42 @@
 	srcs := bazel.MakeLabelListAttribute(
 		android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
 
-	combinedData := append(m.testProperties.Data, m.testProperties.Data_bins...)
-	combinedData = append(combinedData, m.testProperties.Data_libs...)
+	dataBins := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.testProperties.Data_bins))
 
-	data := bazel.MakeLabelListAttribute(
-		android.BazelLabelForModuleSrc(ctx, combinedData))
+	var combinedData bazel.LabelList
+	combinedData.Append(android.BazelLabelForModuleSrc(ctx, m.testProperties.Data))
+	combinedData.Append(android.BazelLabelForModuleDeps(ctx, m.testProperties.Data_bins))
+	combinedData.Append(android.BazelLabelForModuleDeps(ctx, m.testProperties.Data_libs))
+	data := bazel.MakeLabelListAttribute(combinedData)
 
 	tags := bazel.MakeStringListAttribute(
 		m.testProperties.Test_options.Tags)
 
-	test_config := m.testProperties.Test_config
+	testConfigAttributes := tradefed.GetTestConfigAttributes(
+		ctx,
+		m.testProperties.Test_config,
+		[]string{},
+		m.testProperties.Auto_gen_config,
+		m.testProperties.Test_suites,
+		m.testProperties.Test_config_template,
+		nil,
+		nil,
+	)
 
-	test_config_template := m.testProperties.Test_config_template
+	unitTest := m.testProperties.Test_options.Unit_test
 
-	auto_gen_config := m.testProperties.Auto_gen_config
+	runs_on := bazel.MakeStringListAttribute(android.RunsOn(
+		m.ModuleBase.HostSupported(),
+		m.ModuleBase.DeviceSupported(),
+		(unitTest != nil && *unitTest)))
 
 	attrs := &bazelShTestAttributes{
 		Srcs:                 srcs,
 		Data:                 data,
+		Data_bins:            dataBins,
 		Tags:                 tags,
-		Test_config:          test_config,
-		Test_config_template: test_config_template,
-		Auto_gen_config:      auto_gen_config,
+		Runs_on:              runs_on,
+		TestConfigAttributes: testConfigAttributes,
 	}
 
 	props := bazel.BazelTargetModuleProperties{
diff --git a/tests/b_args_test.sh b/tests/b_args_test.sh
new file mode 100755
index 0000000..0dfbabf
--- /dev/null
+++ b/tests/b_args_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -eu
+
+# This file tests the creation of bazel commands for b usage
+set -o pipefail
+source "$(dirname "$0")/../../bazel/lib.sh"
+
+BES_UUID="blank"
+OUT_DIR="arbitrary_out"
+b_args=$(formulate_b_args "build --config=nonsense foo:bar")
+
+if [[ $b_args != "build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=metrics_data --config=nonsense foo:bar" ]]; then
+   echo "b args are malformed"
+   echo "Expected : build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build  --invocation_id=$BES_UUID --config=metrics_data --config=nonsense foo:bar"
+   echo "Actual: $b_args"
+   exit 1
+fi
+
+b_args=$(formulate_b_args "build --config=nonsense --disable_bes --package_path \"my package\" foo:bar")
+
+if [[ $b_args != "build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar" ]]; then
+   echo "b args are malformed"
+   echo "Expected : build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build  --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar"
+   echo "Actual: $b_args"
+   exit 1
+fi
+
+# Test with startup option
+b_args=$(formulate_b_args "--batch build --config=nonsense --disable_bes --package_path \"my package\" foo:bar")
+if [[ $b_args != "--batch build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar" ]]; then
+   echo "b args are malformed"
+   echo "Expected : --batch build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build  --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar"
+   echo "Actual: $b_args"
+   exit 1
+fi
+
+OUT_DIR="mock_out"
+TEST_PROFILE_OUT=$(get_profile_out_dir)
+if [[ $TEST_PROFILE_OUT != "mock_out" ]]; then
+   echo "Profile Out is malformed."
+   echo "Expected: mock_out"
+   echo "Actual: $TEST_PROFILE_OUT"
+   exit 1
+fi
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 8045591..231e18b 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -4,6 +4,7 @@
 
 TOP="$(readlink -f "$(dirname "$0")"/../../..)"
 "$TOP/build/soong/tests/androidmk_test.sh"
+"$TOP/build/soong/tests/b_args_test.sh"
 "$TOP/build/soong/tests/bootstrap_test.sh"
 "$TOP/build/soong/tests/mixed_mode_test.sh"
 "$TOP/build/soong/tests/bp2build_bazel_test.sh"