Merge "Turn on sandboxing for external/perfetto" into main
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 998ae47..11cd041 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -395,6 +395,7 @@
 		"system/apex/tools":                                      Bp2BuildDefaultTrueRecursively,
 		"system/core/debuggerd":                                  Bp2BuildDefaultTrueRecursively,
 		"system/core/diagnose_usb":                               Bp2BuildDefaultTrueRecursively,
+		"system/core/fs_mgr":                                     Bp2BuildDefaultTrueRecursively,
 		"system/core/healthd":                                    Bp2BuildDefaultTrue,
 		"system/core/healthd/testdata":                           Bp2BuildDefaultTrue,
 		"system/core/libasyncio":                                 Bp2BuildDefaultTrue,
@@ -699,8 +700,6 @@
 		// fastboot
 		"fastboot",
 		"libfastboot",
-		"liblp",
-		"libstorage_literals_headers",
 
 		"PluginCoreLib",
 		"dagger2",
@@ -756,14 +755,6 @@
 		//system/chre
 		"chre_api",
 
-		//system/core/fs_mgr/libdm
-		"libdm",
-
-		//system/core/fs_mgr/libfiemap
-		"libfiemap_headers",
-		"libfiemap_passthrough_srcs",
-		"libfiemap_srcs",
-
 		//system/gsid
 		"libgsi",
 		"libgsi_headers",
@@ -780,18 +771,9 @@
 		//system/extras/libfscrypt
 		"libfscrypt",
 
-		//system/core/fs_mgr
-		"libfstab",
-
 		//bootable/recovery/fuse_sideload
 		"libfusesideload",
 
-		//system/core/fs_mgr/libfs_avb
-		"libfs_avb",
-
-		//system/core/fs_mgr
-		"libfs_mgr",
-
 		"libcodec2_aidl",
 		"libcodec2_hidl@1.0",
 		"libcodec2_hidl@1.1",
@@ -899,7 +881,6 @@
 		"binderRpcWireProtocolTest",
 		"binderUnitTest",
 		"cpu_features-bit_utils_test",
-		"liblp_test",
 		"android.hardware.audio.common.test.utility_tests",
 		"HalAudioStreamWorkerTest",
 		"libjavacore-unit-tests",
diff --git a/android/bazel.go b/android/bazel.go
index 202fc48..1602b9b 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -81,6 +81,11 @@
 	// If non-nil, indicates that the module could not be converted successfully
 	// with bp2build. This will describe the reason the module could not be converted.
 	UnconvertedReason *UnconvertedReason
+
+	// The Partition this module will be installed on.
+	// TODO(b/306200980) Investigate how to handle modules that are installed in multiple
+	// partitions.
+	Partition string `blueprint:"mutated"`
 }
 
 // The reason a module could not be converted to a BUILD target via bp2build.
@@ -674,6 +679,9 @@
 
 	bModule.ConvertWithBp2build(ctx)
 
+	installCtx := &baseModuleContextToModuleInstallPathContext{ctx}
+	ctx.Module().base().setPartitionForBp2build(modulePartition(installCtx, true))
+
 	if len(ctx.Module().base().Bp2buildTargets()) == 0 && ctx.Module().base().GetUnconvertedReason() == nil {
 		panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName()))
 	}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 51ce3c9..0c65415 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -245,6 +245,55 @@
 
 var _ BazelContext = noopBazelContext{}
 
+func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
+	panic("unimplemented")
+}
+
+func (n noopBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
+	panic("unimplemented")
+}
+
+func (n noopBazelContext) GetOutputFiles(_ string, _ configKey) ([]string, error) {
+	panic("unimplemented")
+}
+
+func (n noopBazelContext) GetCcInfo(_ string, _ configKey) (cquery.CcInfo, error) {
+	panic("unimplemented")
+}
+
+func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexInfo, error) {
+	panic("unimplemented")
+}
+
+func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (n noopBazelContext) GetPrebuiltFileInfo(_ string, _ configKey) (cquery.PrebuiltFileInfo, error) {
+	panic("implement me")
+}
+
+func (n noopBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
+	panic("unimplemented")
+}
+
+func (m noopBazelContext) OutputBase() string {
+	return ""
+}
+
+func (n noopBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
+	return false
+}
+
+func (m noopBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
+	return []*bazel.BuildStatement{}
+}
+
+func (m noopBazelContext) AqueryDepsets() []bazel.AqueryDepset {
+	return []bazel.AqueryDepset{}
+}
+
 // A bazel context to use for tests.
 type MockBazelContext struct {
 	OutputBaseDir string
@@ -427,55 +476,6 @@
 	return cquery.PrebuiltFileInfo{}, fmt.Errorf("no bazel response for %s", key)
 }
 
-func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
-	panic("unimplemented")
-}
-
-func (n noopBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
-	panic("unimplemented")
-}
-
-func (n noopBazelContext) GetOutputFiles(_ string, _ configKey) ([]string, error) {
-	panic("unimplemented")
-}
-
-func (n noopBazelContext) GetCcInfo(_ string, _ configKey) (cquery.CcInfo, error) {
-	panic("unimplemented")
-}
-
-func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexInfo, error) {
-	panic("unimplemented")
-}
-
-func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (n noopBazelContext) GetPrebuiltFileInfo(_ string, _ configKey) (cquery.PrebuiltFileInfo, error) {
-	panic("implement me")
-}
-
-func (n noopBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
-	panic("unimplemented")
-}
-
-func (m noopBazelContext) OutputBase() string {
-	return ""
-}
-
-func (n noopBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
-	return false
-}
-
-func (m noopBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
-	return []*bazel.BuildStatement{}
-}
-
-func (m noopBazelContext) AqueryDepsets() []bazel.AqueryDepset {
-	return []bazel.AqueryDepset{}
-}
-
 func AddToStringSet(set map[string]bool, items []string) {
 	for _, item := range items {
 		set[item] = true
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index d272ec2..f25803c 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -103,7 +103,7 @@
 // or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
 // module within the given ctx.
 func BazelLabelForModuleDeps(ctx Bp2buildMutatorContext, modules []string) bazel.LabelList {
-	return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel, /*markAsDeps=*/true)
+	return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel, true)
 }
 
 // BazelLabelForModuleWholeDepsExcludes expects two lists: modules (containing modules to include in
@@ -154,11 +154,11 @@
 // the excluded dependencies.
 func BazelLabelForModuleDepsExcludesWithFn(ctx Bp2buildMutatorContext, modules, excludes []string,
 	moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
-	moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn, /*markAsDeps=*/true)
+	moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn, true)
 	if len(excludes) == 0 {
 		return moduleLabels
 	}
-	excludeLabels := BazelLabelForModuleDepsWithFn(ctx, excludes, moduleToLabelFn, /*markAsDeps=*/false)
+	excludeLabels := BazelLabelForModuleDepsWithFn(ctx, excludes, moduleToLabelFn, false)
 	return bazel.LabelList{
 		Includes: moduleLabels.Includes,
 		Excludes: excludeLabels.Includes,
diff --git a/android/config.go b/android/config.go
index 66c0e6d..dfc61a5 100644
--- a/android/config.go
+++ b/android/config.go
@@ -900,6 +900,10 @@
 	return c.katiEnabled
 }
 
+func (c *config) ProductVariables() ProductVariables {
+	return c.productVariables
+}
+
 func (c *config) BuildId() string {
 	return String(c.productVariables.BuildId)
 }
@@ -2059,8 +2063,15 @@
 		version)
 }
 
+func (c *config) JavaCoverageEnabled() bool {
+	return c.IsEnvTrue("EMMA_INSTRUMENT") || c.IsEnvTrue("EMMA_INSTRUMENT_STATIC") || c.IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
+}
+
 func (c *config) BuildFromTextStub() bool {
-	return c.buildFromTextStub
+	// TODO: b/302320354 - Remove the coverage build specific logic once the
+	// robust solution for handling native properties in from-text stub build
+	// is implemented.
+	return c.buildFromTextStub && !c.JavaCoverageEnabled()
 }
 
 func (c *config) SetBuildFromTextStub(b bool) {
diff --git a/android/module.go b/android/module.go
index b73f449..250161f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -572,6 +572,7 @@
 	Bp2buildTargets() []bp2buildInfo
 	GetUnconvertedBp2buildDeps() []string
 	GetMissingBp2buildDeps() []string
+	GetPartitionForBp2build() string
 
 	BuildParamsForTests() []BuildParams
 	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
@@ -1651,6 +1652,10 @@
 	m.commonProperties.BazelConversionStatus.Bp2buildInfo = append(m.commonProperties.BazelConversionStatus.Bp2buildInfo, info)
 }
 
+func (m *ModuleBase) setPartitionForBp2build(partition string) {
+	m.commonProperties.BazelConversionStatus.Partition = partition
+}
+
 func (m *ModuleBase) setBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
 	m.commonProperties.BazelConversionStatus.UnconvertedReason = &UnconvertedReason{
 		ReasonType: int(reasonType),
@@ -1667,6 +1672,11 @@
 	return m.commonProperties.BazelConversionStatus.Bp2buildInfo
 }
 
+// Bp2buildTargets returns the Bazel targets bp2build generated for this module.
+func (m *ModuleBase) GetPartitionForBp2build() string {
+	return m.commonProperties.BazelConversionStatus.Partition
+}
+
 // AddUnconvertedBp2buildDep stores module name of a dependency that was not converted to Bazel.
 func (b *baseModuleContext) AddUnconvertedBp2buildDep(dep string) {
 	unconvertedDeps := &b.Module().base().commonProperties.BazelConversionStatus.UnconvertedDeps
diff --git a/android/paths.go b/android/paths.go
index 7658299..8dd1966 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -116,6 +116,48 @@
 
 var _ ModuleInstallPathContext = ModuleContext(nil)
 
+type baseModuleContextToModuleInstallPathContext struct {
+	BaseModuleContext
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInData() bool {
+	return ctx.Module().InstallInData()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInTestcases() bool {
+	return ctx.Module().InstallInTestcases()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInSanitizerDir() bool {
+	return ctx.Module().InstallInSanitizerDir()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInRamdisk() bool {
+	return ctx.Module().InstallInRamdisk()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInVendorRamdisk() bool {
+	return ctx.Module().InstallInVendorRamdisk()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInDebugRamdisk() bool {
+	return ctx.Module().InstallInDebugRamdisk()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInRecovery() bool {
+	return ctx.Module().InstallInRecovery()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInRoot() bool {
+	return ctx.Module().InstallInRoot()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallForceOS() (*OsType, *ArchType) {
+	return ctx.Module().InstallForceOS()
+}
+
+var _ ModuleInstallPathContext = (*baseModuleContextToModuleInstallPathContext)(nil)
+
 // errorfContext is the interface containing the Errorf method matching the
 // Errorf method in blueprint.SingletonContext.
 type errorfContext interface {
@@ -1683,7 +1725,7 @@
 // module appended with paths...
 func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
 	os, arch := osAndArch(ctx)
-	partition := modulePartition(ctx, os)
+	partition := modulePartition(ctx, os.Class == Device)
 	return pathForInstall(ctx, os, arch, partition, pathComponents...)
 }
 
@@ -1785,12 +1827,12 @@
 	return "/" + rel
 }
 
-func modulePartition(ctx ModuleInstallPathContext, os OsType) string {
+func modulePartition(ctx ModuleInstallPathContext, device bool) string {
 	var partition string
 	if ctx.InstallInTestcases() {
 		// "testcases" install directory can be used for host or device modules.
 		partition = "testcases"
-	} else if os.Class == Device {
+	} else if device {
 		if ctx.InstallInData() {
 			partition = "data"
 		} else if ctx.InstallInRamdisk() {
diff --git a/android/variable.go b/android/variable.go
index ab6dfef..9896f20 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -494,38 +494,40 @@
 	Release_expose_flagged_api *bool `json:",omitempty"`
 }
 
+type PartitionQualifiedVariablesType struct {
+	BuildingImage               bool   `json:",omitempty"`
+	BoardErofsCompressor        string `json:",omitempty"`
+	BoardErofsCompressHints     string `json:",omitempty"`
+	BoardErofsPclusterSize      string `json:",omitempty"`
+	BoardExtfsInodeCount        string `json:",omitempty"`
+	BoardExtfsRsvPct            string `json:",omitempty"`
+	BoardF2fsSloadCompressFlags string `json:",omitempty"`
+	BoardFileSystemCompress     string `json:",omitempty"`
+	BoardFileSystemType         string `json:",omitempty"`
+	BoardJournalSize            string `json:",omitempty"`
+	BoardPartitionReservedSize  string `json:",omitempty"`
+	BoardPartitionSize          string `json:",omitempty"`
+	BoardSquashfsBlockSize      string `json:",omitempty"`
+	BoardSquashfsCompressor     string `json:",omitempty"`
+	BoardSquashfsCompressorOpt  string `json:",omitempty"`
+	BoardSquashfsDisable4kAlign string `json:",omitempty"`
+	ProductBaseFsPath           string `json:",omitempty"`
+	ProductHeadroom             string `json:",omitempty"`
+	ProductVerityPartition      string `json:",omitempty"`
+
+	BoardAvbAddHashtreeFooterArgs string `json:",omitempty"`
+	BoardAvbKeyPath               string `json:",omitempty"`
+	BoardAvbAlgorithm             string `json:",omitempty"`
+	BoardAvbRollbackIndex         string `json:",omitempty"`
+	BoardAvbRollbackIndexLocation string `json:",omitempty"`
+}
+
 type PartitionVariables struct {
 	ProductDirectory            string `json:",omitempty"`
-	PartitionQualifiedVariables map[string]struct {
-		BuildingImage               bool   `json:",omitempty"`
-		BoardErofsCompressor        string `json:",omitempty"`
-		BoardErofsCompressHints     string `json:",omitempty"`
-		BoardErofsPclusterSize      string `json:",omitempty"`
-		BoardExtfsInodeCount        string `json:",omitempty"`
-		BoardExtfsRsvPct            string `json:",omitempty"`
-		BoardF2fsSloadCompressFlags string `json:",omitempty"`
-		BoardFileSystemCompress     string `json:",omitempty"`
-		BoardFileSystemType         string `json:",omitempty"`
-		BoardJournalSize            string `json:",omitempty"`
-		BoardPartitionReservedSize  string `json:",omitempty"`
-		BoardPartitionSize          string `json:",omitempty"`
-		BoardSquashfsBlockSize      string `json:",omitempty"`
-		BoardSquashfsCompressor     string `json:",omitempty"`
-		BoardSquashfsCompressorOpt  string `json:",omitempty"`
-		BoardSquashfsDisable4kAlign string `json:",omitempty"`
-		ProductBaseFsPath           string `json:",omitempty"`
-		ProductHeadroom             string `json:",omitempty"`
-		ProductVerityPartition      string `json:",omitempty"`
-
-		BoardAvbAddHashtreeFooterArgs string `json:",omitempty"`
-		BoardAvbKeyPath               string `json:",omitempty"`
-		BoardAvbAlgorithm             string `json:",omitempty"`
-		BoardAvbRollbackIndex         string `json:",omitempty"`
-		BoardAvbRollbackIndexLocation string `json:",omitempty"`
-	}
-	TargetUserimagesUseExt2 bool `json:",omitempty"`
-	TargetUserimagesUseExt3 bool `json:",omitempty"`
-	TargetUserimagesUseExt4 bool `json:",omitempty"`
+	PartitionQualifiedVariables map[string]PartitionQualifiedVariablesType
+	TargetUserimagesUseExt2     bool `json:",omitempty"`
+	TargetUserimagesUseExt3     bool `json:",omitempty"`
+	TargetUserimagesUseExt4     bool `json:",omitempty"`
 
 	TargetUserimagesSparseExtDisabled      bool `json:",omitempty"`
 	TargetUserimagesSparseErofsDisabled    bool `json:",omitempty"`
@@ -546,6 +548,8 @@
 	CopyImagesForTargetFilesZip          bool   `json:",omitempty"`
 
 	BoardAvbEnable bool `json:",omitempty"`
+
+	ProductPackages []string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index a93fb38..14e32ed 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -89,6 +89,7 @@
         "python_library_conversion_test.go",
         "python_test_conversion_test.go",
         "rust_binary_conversion_test.go",
+        "rust_ffi_conversion_test.go",
         "rust_library_conversion_test.go",
         "rust_proc_macro_conversion_test.go",
         "rust_protobuf_conversion_test.go",
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index 6c9d903..1496ca7 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -82,7 +82,7 @@
 		os.Exit(1)
 	}
 	var bp2buildFiles []BazelFile
-	productConfig, err := createProductConfigFiles(ctx, res.metrics)
+	productConfig, err := createProductConfigFiles(ctx, res.moduleNameToPartition, res.metrics.convertedModulePathMap)
 	ctx.Context().EventHandler.Do("CreateBazelFile", func() {
 		allTargets := make(map[string]BazelTargets)
 		for k, v := range res.buildFileToTargets {
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 2adcccc..7f26bef 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -3,7 +3,6 @@
 import (
 	"encoding/json"
 	"fmt"
-	"os"
 	"path/filepath"
 	"reflect"
 	"sort"
@@ -53,7 +52,8 @@
 
 func createProductConfigFiles(
 	ctx *CodegenContext,
-	metrics CodegenMetrics) (createProductConfigFilesResult, error) {
+	moduleNameToPartition map[string]string,
+	convertedModulePathMap map[string]string) (createProductConfigFilesResult, error) {
 	cfg := &ctx.config
 	targetProduct := "unknown"
 	if cfg.HasDeviceProduct() {
@@ -68,16 +68,11 @@
 
 	var res createProductConfigFilesResult
 
-	productVariablesFileName := cfg.ProductVariablesFileName
-	if !strings.HasPrefix(productVariablesFileName, "/") {
-		productVariablesFileName = filepath.Join(ctx.topDir, productVariablesFileName)
-	}
-	productVariablesBytes, err := os.ReadFile(productVariablesFileName)
-	if err != nil {
-		return res, err
-	}
-	productVariables := android.ProductVariables{}
-	err = json.Unmarshal(productVariablesBytes, &productVariables)
+	productVariables := ctx.Config().ProductVariables()
+	// TODO(b/306243251): For some reason, using the real value of native_coverage makes some select
+	// statements ambiguous
+	productVariables.Native_coverage = nil
+	productVariablesBytes, err := json.Marshal(productVariables)
 	if err != nil {
 		return res, err
 	}
@@ -142,12 +137,12 @@
 			},
 		},
 	})
-	createTargets(productLabelsToVariables, res.bp2buildTargets)
+	createTargets(ctx, productLabelsToVariables, moduleNameToPartition, convertedModulePathMap, res.bp2buildTargets)
 
 	platformMappingContent, err := platformMappingContent(
 		productLabelsToVariables,
 		ctx.Config().Bp2buildSoongConfigDefinitions,
-		metrics.convertedModulePathMap)
+		convertedModulePathMap)
 	if err != nil {
 		return res, err
 	}
@@ -481,12 +476,17 @@
 	return result, nil
 }
 
-func createTargets(productLabelsToVariables map[bazelLabel]*android.ProductVariables, res map[string]BazelTargets) {
+func createTargets(
+	ctx *CodegenContext,
+	productLabelsToVariables map[bazelLabel]*android.ProductVariables,
+	moduleNameToPartition map[string]string,
+	convertedModulePathMap map[string]string,
+	res map[string]BazelTargets) {
 	createGeneratedAndroidCertificateDirectories(productLabelsToVariables, res)
 	createAvbKeyFilegroups(productLabelsToVariables, res)
 	createReleaseAconfigValueSetsFilegroup(productLabelsToVariables, res)
 	for label, variables := range productLabelsToVariables {
-		createSystemPartition(label, &variables.PartitionVarsForBazelMigrationOnlyDoNotUse, res)
+		createSystemPartition(ctx, label, &variables.PartitionVarsForBazelMigrationOnlyDoNotUse, moduleNameToPartition, convertedModulePathMap, res)
 	}
 }
 
@@ -581,7 +581,13 @@
 	}
 }
 
-func createSystemPartition(platformLabel bazelLabel, variables *android.PartitionVariables, targets map[string]BazelTargets) {
+func createSystemPartition(
+	ctx *CodegenContext,
+	platformLabel bazelLabel,
+	variables *android.PartitionVariables,
+	moduleNameToPartition map[string]string,
+	convertedModulePathMap map[string]string,
+	targets map[string]BazelTargets) {
 	if !variables.PartitionQualifiedVariables["system"].BuildingImage {
 		return
 	}
@@ -611,6 +617,26 @@
 		}
 	}
 
+	var deps []string
+	for _, mod := range variables.ProductPackages {
+		if path, ok := convertedModulePathMap[mod]; ok && ctx.Config().BazelContext.IsModuleNameAllowed(mod, false) {
+			if partition, ok := moduleNameToPartition[mod]; ok && partition == "system" {
+				if path == "//." {
+					path = "//"
+				}
+				deps = append(deps, fmt.Sprintf("        \"%s:%s\",\n", path, mod))
+			}
+		}
+	}
+	if len(deps) > 0 {
+		sort.Strings(deps)
+		extraProperties.WriteString("    deps = [\n")
+		for _, dep := range deps {
+			extraProperties.WriteString(dep)
+		}
+		extraProperties.WriteString("    ],\n")
+	}
+
 	targets[platformLabel.pkg] = append(targets[platformLabel.pkg], BazelTarget{
 		name:        "system_image",
 		packageName: platformLabel.pkg,
diff --git a/bp2build/bp2build_product_config_test.go b/bp2build/bp2build_product_config_test.go
index 02d83b4..02a2b51 100644
--- a/bp2build/bp2build_product_config_test.go
+++ b/bp2build/bp2build_product_config_test.go
@@ -2,6 +2,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/cc"
 	"android/soong/starlark_import"
 	"encoding/json"
 	"reflect"
@@ -87,3 +88,67 @@
 		}
 	}
 }
+
+func TestSystemPartitionDeps(t *testing.T) {
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
+	}, Bp2buildTestCase{
+		ExtraFixturePreparer: android.GroupFixturePreparers(
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				deviceProduct := "aosp_arm64"
+				variables.DeviceProduct = &deviceProduct
+				partitionVars := &variables.PartitionVarsForBazelMigrationOnlyDoNotUse
+				partitionVars.ProductDirectory = "build/make/target/product/"
+				partitionVars.ProductPackages = []string{"foo"}
+				var systemVars android.PartitionQualifiedVariablesType
+				systemVars.BuildingImage = true
+				partitionVars.PartitionQualifiedVariables = map[string]android.PartitionQualifiedVariablesType{
+					"system": systemVars,
+				}
+			}),
+			android.FixtureModifyConfig(func(config android.Config) {
+				// MockBazelContext will pretend everything is mixed-builds allowlisted.
+				// The default is noopBazelContext, which does the opposite.
+				config.BazelContext = android.MockBazelContext{}
+			}),
+		),
+		Blueprint: `
+cc_library {
+  name: "foo",
+}`,
+		ExpectedBazelTargets: []string{`android_product(
+    name = "aosp_arm64",
+    soong_variables = _soong_variables,
+)`, `partition(
+    name = "system_image",
+    base_staging_dir = "//build/bazel/bazel_sandwich:system_staging_dir",
+    base_staging_dir_file_list = "//build/bazel/bazel_sandwich:system_staging_dir_file_list",
+    root_dir = "//build/bazel/bazel_sandwich:root_staging_dir",
+    selinux_file_contexts = "//build/bazel/bazel_sandwich:selinux_file_contexts",
+    image_properties = """
+building_system_image=true
+erofs_sparse_flag=-s
+extfs_sparse_flag=-s
+f2fs_sparse_flag=-S
+skip_fsck=true
+squashfs_sparse_flag=-s
+system_disable_sparse=true
+
+""",
+    deps = [
+        "//:foo",
+    ],
+
+    type = "system",
+)`, `partition_diff_test(
+    name = "system_image_test",
+    partition1 = "//build/bazel/bazel_sandwich:make_system_image",
+    partition2 = ":system_image",
+)`, `run_test_in_build(
+    name = "run_system_image_test",
+    test = ":system_image_test",
+)`},
+		Dir:                      "build/make/target/product/aosp_arm64",
+		RunBp2buildProductConfig: true,
+	})
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index ed6e2dd..d2187ff 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -279,8 +279,9 @@
 }
 
 type conversionResults struct {
-	buildFileToTargets map[string]BazelTargets
-	metrics            CodegenMetrics
+	buildFileToTargets    map[string]BazelTargets
+	moduleNameToPartition map[string]string
+	metrics               CodegenMetrics
 }
 
 func (r conversionResults) BuildDirToTargets() map[string]BazelTargets {
@@ -707,6 +708,7 @@
 	metrics := CreateCodegenMetrics()
 
 	dirs := make(map[string]bool)
+	moduleNameToPartition := make(map[string]string)
 
 	var errs []error
 
@@ -754,6 +756,9 @@
 					metrics.IncrementRuleClassCount(t.ruleClass)
 				}
 
+				// record the partition
+				moduleNameToPartition[android.RemoveOptionalPrebuiltPrefix(aModule.Name())] = aModule.GetPartitionForBp2build()
+
 				// Log the module.
 				metrics.AddConvertedModule(aModule, moduleType, dir)
 
@@ -876,8 +881,9 @@
 	}
 
 	return conversionResults{
-		buildFileToTargets: buildFileToTargets,
-		metrics:            metrics,
+		buildFileToTargets:    buildFileToTargets,
+		moduleNameToPartition: moduleNameToPartition,
+		metrics:               metrics,
 	}, errs
 }
 
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
index ad69ed5..bba2f50 100644
--- a/bp2build/java_import_conversion_test.go
+++ b/bp2build/java_import_conversion_test.go
@@ -52,15 +52,13 @@
 }
 `,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("filegroup", "example_import-jars", AttrNameToString{
-				"srcs": `["import.jar"]`,
-			}),
 			MakeBazelTarget("java_import", "example_import", AttrNameToString{
-				"jars": `[":example_import-jars"]`,
+				"jars": `["import.jar"]`,
 			}),
-			MakeBazelTarget("java_import", "example_import-neverlink", AttrNameToString{
-				"jars":      `[":example_import-jars"]`,
-				"neverlink": `True`,
+			MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+				"exports":     `[":example_import"]`,
+				"neverlink":   `True`,
+				"sdk_version": `"none"`,
 			}),
 		}})
 }
@@ -88,19 +86,17 @@
 }
 `,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("filegroup", "example_import-jars", AttrNameToString{
-				"srcs": `select({
+			MakeBazelTarget("java_import", "example_import", AttrNameToString{
+				"jars": `select({
         "//build/bazel_common_rules/platforms/os:android": ["android.jar"],
         "//build/bazel_common_rules/platforms/os:linux_glibc": ["linux.jar"],
         "//conditions:default": [],
     })`,
 			}),
-			MakeBazelTarget("java_import", "example_import", AttrNameToString{
-				"jars": `[":example_import-jars"]`,
-			}),
-			MakeBazelTarget("java_import", "example_import-neverlink", AttrNameToString{
-				"jars":      `[":example_import-jars"]`,
-				"neverlink": `True`,
+			MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+				"exports":     `[":example_import"]`,
+				"neverlink":   `True`,
+				"sdk_version": `"none"`,
 			}),
 		}})
 }
@@ -121,15 +117,13 @@
 }
 `,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("filegroup", "example_import-jars", AttrNameToString{
-				"srcs": `["import.jar"]`,
-			}),
 			MakeBazelTarget("java_import", "example_import", AttrNameToString{
-				"jars": `[":example_import-jars"]`,
+				"jars": `["import.jar"]`,
 			}),
-			MakeBazelTarget("java_import", "example_import-neverlink", AttrNameToString{
-				"jars":      `[":example_import-jars"]`,
-				"neverlink": `True`,
+			MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+				"exports":     `[":example_import"]`,
+				"neverlink":   `True`,
+				"sdk_version": `"none"`,
 			}),
 		}})
 }
@@ -148,15 +142,13 @@
 }
 `,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("filegroup", "test_lib-jars", AttrNameToString{
-				"srcs": `["test.jar"]`,
-			}),
 			MakeBazelTarget("java_import", "test_lib", AttrNameToString{
-				"jars": `[":test_lib-jars"]`,
+				"jars": `["test.jar"]`,
 			}),
-			MakeBazelTarget("java_import", "test_lib-neverlink", AttrNameToString{
-				"jars":      `[":test_lib-jars"]`,
-				"neverlink": `True`,
+			MakeBazelTarget("java_library", "test_lib-neverlink", AttrNameToString{
+				"exports":     `[":test_lib"]`,
+				"neverlink":   `True`,
+				"sdk_version": `"none"`,
 			}),
 		},
 	}, func(ctx android.RegistrationContext) {
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index c88af1b..5099b49 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -1109,3 +1109,23 @@
 		ctx.RegisterModuleType("java_import", java.ImportFactory)
 	})
 }
+
+func TestJavaLibrarySharding(t *testing.T) {
+	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		Description: "java library with sharded compilation",
+		Blueprint: `java_library {
+			name: "lib1",
+			srcs: ["a.java"],
+			javac_shard_size: 3,
+			sdk_version: "current",
+		}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("java_library", "lib1", AttrNameToString{
+				"srcs":             `["a.java"]`,
+				"sdk_version":      `"current"`,
+				"javac_shard_size": "3",
+			}),
+			MakeNeverlinkDuplicateTarget("java_library", "lib1"),
+		},
+	})
+}
diff --git a/bp2build/rust_ffi_conversion_test.go b/bp2build/rust_ffi_conversion_test.go
new file mode 100644
index 0000000..97fe297
--- /dev/null
+++ b/bp2build/rust_ffi_conversion_test.go
@@ -0,0 +1,78 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/rust"
+	"testing"
+)
+
+func runRustFfiTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, registerRustFfiModuleTypes, tc)
+}
+
+func registerRustFfiModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("rust_ffi_static", rust.RustFFIStaticFactory)
+	ctx.RegisterModuleType("rust_library", rust.RustLibraryFactory)
+}
+
+func TestRustFfiStatic(t *testing.T) {
+	runRustFfiTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_ffi_static {
+	name: "libfoo",
+	crate_name: "foo",
+	host_supported: true,
+	srcs: ["src/lib.rs"],
+	edition: "2015",
+	include_dirs: [
+		"include",
+	],
+	rustlibs: ["libbar"],
+	bazel_module: { bp2build_available: true },
+}
+`,
+			"external/rust/crates/bar/Android.bp": `
+rust_library {
+	name: "libbar",
+	crate_name: "bar",
+	host_supported: true,
+	srcs: ["src/lib.rs"],
+	bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("rust_ffi_static", "libfoo", AttrNameToString{
+				"crate_name": `"foo"`,
+				"deps":       `["//external/rust/crates/bar:libbar"]`,
+				"srcs": `[
+        "src/helper.rs",
+        "src/lib.rs",
+    ]`,
+				"edition":         `"2015"`,
+				"export_includes": `["include"]`,
+			}),
+		},
+	},
+	)
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index b2804f9..c978164 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -28,6 +28,7 @@
 	"testing"
 
 	"android/soong/ui/metrics/bp2build_metrics_proto"
+
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
@@ -124,26 +125,28 @@
 	// 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
-}
 
-func RunBp2BuildTestCaseExtraContext(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), modifyContext func(ctx *android.TestContext), tc Bp2buildTestCase) {
-	t.Helper()
-	preparers := []android.FixturePreparer{
-		android.FixtureRegisterWithContext(registerModuleTypes),
-	}
-	if modifyContext != nil {
-		preparers = append(preparers, android.FixtureModifyContext(modifyContext))
-	}
-	preparers = append(preparers, SetBp2BuildTestRunner)
-	bp2buildSetup := android.GroupFixturePreparers(
-		preparers...,
-	)
-	runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
+	// An extra FixturePreparer to use when running the test. If you need multiple extra
+	// FixturePreparers, use android.GroupFixturePreparers()
+	ExtraFixturePreparer android.FixturePreparer
+
+	// If bp2build_product_config.go should run as part of the test.
+	RunBp2buildProductConfig bool
 }
 
 func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
 	t.Helper()
-	RunBp2BuildTestCaseExtraContext(t, registerModuleTypes, nil, tc)
+	preparers := []android.FixturePreparer{
+		android.FixtureRegisterWithContext(registerModuleTypes),
+	}
+	if tc.ExtraFixturePreparer != nil {
+		preparers = append(preparers, tc.ExtraFixturePreparer)
+	}
+	preparers = append(preparers, android.FixtureSetTestRunner(&bazelTestRunner{generateProductConfigTargets: tc.RunBp2buildProductConfig}))
+	bp2buildSetup := android.GroupFixturePreparers(
+		preparers...,
+	)
+	runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
 }
 
 func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePreparer, tc Bp2buildTestCase) {
@@ -247,11 +250,10 @@
 	result.CompareAllBazelTargets(t, tc, expectedTargets, true)
 }
 
-// SetBp2BuildTestRunner customizes the test fixture mechanism to run tests in Bp2Build mode.
-var SetBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{})
-
 // bazelTestRunner customizes the test fixture mechanism to run tests of the bp2build build mode.
-type bazelTestRunner struct{}
+type bazelTestRunner struct {
+	generateProductConfigTargets bool
+}
 
 func (b *bazelTestRunner) FinalPreparer(result *android.TestResult) android.CustomTestResult {
 	ctx := result.TestContext
@@ -274,6 +276,16 @@
 	if bazelResult.CollateErrs(errs) {
 		return
 	}
+	if b.generateProductConfigTargets {
+		productConfig, err := createProductConfigFiles(codegenCtx, res.moduleNameToPartition, res.metrics.convertedModulePathMap)
+		if err != nil {
+			bazelResult.CollateErrs([]error{err})
+			return
+		}
+		for k, v := range productConfig.bp2buildTargets {
+			res.buildFileToTargets[k] = append(res.buildFileToTargets[k], v...)
+		}
+	}
 
 	// Store additional data for access by tests.
 	bazelResult.conversionResults = res
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 57333b8..7ae8d89 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -1904,7 +1904,7 @@
 }
 
 func bazelLabelForWholeDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
-	return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps, /*markAsDeps=*/true)
+	return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps, true)
 }
 
 func bazelLabelForWholeDepsExcludes(ctx android.Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList {
@@ -1916,11 +1916,11 @@
 }
 
 func bazelLabelForStaticDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
-	return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule, /*markAsDeps=*/true)
+	return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule, true)
 }
 
 func bazelLabelForSharedDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
-	return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule, /*markAsDeps=*/true)
+	return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule, true)
 }
 
 func bazelLabelForHeaderDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
diff --git a/cc/config/global.go b/cc/config/global.go
index 0354b25..62b008b 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -170,9 +170,6 @@
 
 		// Emit additional debug info for AutoFDO
 		"-fdebug-info-for-profiling",
-
-		// Enable Hot Cold splitting optimization.
-		"-mllvm -hot-cold-split=true",
 	}
 
 	commonGlobalLldflags = []string{
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 227fe8b..df9f21a 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -357,10 +357,10 @@
 // their architecture & target/host specific zip file.
 type ccRustFuzzPackager struct {
 	fuzz.FuzzPackager
-	fuzzPackagingArchModules         			string
-	fuzzTargetSharedDepsInstallPairs 			string
-	allFuzzTargetsName               			string
-	onlyIncludePresubmits						bool
+	fuzzPackagingArchModules         string
+	fuzzTargetSharedDepsInstallPairs string
+	allFuzzTargetsName               string
+	onlyIncludePresubmits            bool
 }
 
 func fuzzPackagingFactory() android.Singleton {
@@ -369,7 +369,7 @@
 		fuzzPackagingArchModules:         "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
 		fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
 		allFuzzTargetsName:               "ALL_FUZZ_TARGETS",
-		onlyIncludePresubmits:			  false,
+		onlyIncludePresubmits:            false,
 	}
 	return fuzzPackager
 }
@@ -380,7 +380,7 @@
 		fuzzPackagingArchModules:         "SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES",
 		fuzzTargetSharedDepsInstallPairs: "PRESUBMIT_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
 		allFuzzTargetsName:               "ALL_PRESUBMIT_FUZZ_TARGETS",
-		onlyIncludePresubmits:			  true,
+		onlyIncludePresubmits:            true,
 	}
 	return fuzzPackager
 }
@@ -451,7 +451,7 @@
 			if fpm.FuzzProperties.Fuzz_config == nil {
 				return
 			}
-			if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false){
+			if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false) {
 				return
 			}
 		}
diff --git a/cc/orderfile.go b/cc/orderfile.go
index b64c1c7..9192e81 100644
--- a/cc/orderfile.go
+++ b/cc/orderfile.go
@@ -58,17 +58,17 @@
 
 type OrderfileProperties struct {
 	Orderfile struct {
-		Instrumentation    *bool
-		Order_file_path    *string `android:"arch_variant"`
-		Load_order_file    *bool `android:"arch_variant"`
+		Instrumentation *bool
+		Order_file_path *string `android:"arch_variant"`
+		Load_order_file *bool   `android:"arch_variant"`
 		// Additional compiler flags to use when building this module
 		// for orderfile profiling.
 		Cflags []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 
-	ShouldProfileModule 	  bool `blueprint:"mutated"`
-	OrderfileLoad             bool `blueprint:"mutated"`
-	OrderfileInstrLink        bool `blueprint:"mutated"`
+	ShouldProfileModule bool `blueprint:"mutated"`
+	OrderfileLoad       bool `blueprint:"mutated"`
+	OrderfileInstrLink  bool `blueprint:"mutated"`
 }
 
 type orderfile struct {
@@ -128,7 +128,6 @@
 	return flags
 }
 
-
 func (props *OrderfileProperties) loadOrderfileFlags(ctx ModuleContext, file string) []string {
 	flags := []string{fmt.Sprintf(orderfileUseFormat, file)}
 	flags = append(flags, orderfileOtherFlags...)
@@ -217,7 +216,7 @@
 
 			if dep, ok := dep.(*Module); ok {
 				if m.orderfile.Properties.OrderfileInstrLink {
-					dep.orderfile.Properties.OrderfileInstrLink = true;
+					dep.orderfile.Properties.OrderfileInstrLink = true
 				}
 			}
 
diff --git a/cc/orderfile_test.go b/cc/orderfile_test.go
index f68457d..3486f96 100644
--- a/cc/orderfile_test.go
+++ b/cc/orderfile_test.go
@@ -15,8 +15,8 @@
 package cc
 
 import (
-	"testing"
 	"strings"
+	"testing"
 
 	"android/soong/android"
 )
@@ -193,8 +193,8 @@
 	}
 
 	// Check cFlags of orderfile variant static libraries
-	libFooOfVariant  := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
-	libBarOfVariant  := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
+	libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
+	libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
 
 	cFlags = libFooOfVariant.Rule("cc").Args["cFlags"]
 	if !strings.Contains(cFlags, expectedCFlag) {
@@ -216,8 +216,8 @@
 	}
 
 	// Check cFlags of the non-orderfile variant static libraries
-	libFoo  := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
-	libBar  := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
 
 	cFlags = libFoo.Rule("cc").Args["cFlags"]
 	if strings.Contains(cFlags, expectedCFlag) {
@@ -281,8 +281,8 @@
 		t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags)
 	}
 
-	libFoo  := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
-	libBar  := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
 
 	// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
 	if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
@@ -351,8 +351,8 @@
 	}
 
 	// Check cFlags of the static and shared libraries
-	libFoo  := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
-	libBar  := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
+	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
 
 	cFlags = libFoo.Rule("cc").Args["cFlags"]
 	if strings.Contains(cFlags, expectedCFlag) {
@@ -431,8 +431,8 @@
 	}
 
 	// Check cFlags of the static libraries
-	libFoo  := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
-	libBar  := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
 
 	cFlags = libFoo.Rule("cc").Args["cFlags"]
 	if strings.Contains(cFlags, expectedCFlag) {
@@ -467,4 +467,4 @@
 			t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index ca28442..685571d 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -799,7 +799,7 @@
 	var dir = module.installDirBase
 	// prebuilt_file only supports "etc" or "usr/share" or "." as module installDirBase
 	if !(dir == "etc" || dir == "usr/share" || dir == ".") {
-		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
+		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "dir")
 		return
 	}
 
diff --git a/java/aar.go b/java/aar.go
index 368f241..479b5e0 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -849,6 +849,17 @@
 	}
 }
 
+func (a *AndroidLibrary) IDEInfo(dpInfo *android.IdeInfo) {
+	a.Library.IDEInfo(dpInfo)
+	a.aapt.IDEInfo(dpInfo)
+}
+
+func (a *aapt) IDEInfo(dpInfo *android.IdeInfo) {
+	if a.useResourceProcessorBusyBox() {
+		dpInfo.Jars = append(dpInfo.Jars, a.rJar.String())
+	}
+}
+
 // android_library builds and links sources into a `.jar` file for the device along with Android resources.
 //
 // An android_library has a single variant that produces a `.jar` file containing `.class` files that were
diff --git a/java/app.go b/java/app.go
index ce94aba..0cb72e2 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1073,6 +1073,11 @@
 
 var _ cc.Coverage = (*AndroidApp)(nil)
 
+func (a *AndroidApp) IDEInfo(dpInfo *android.IdeInfo) {
+	a.Library.IDEInfo(dpInfo)
+	a.aapt.IDEInfo(dpInfo)
+}
+
 // android_app compiles sources and Android resources into an Android application package `.apk` file.
 func AndroidAppFactory() android.Module {
 	module := &AndroidApp{}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index dcc2dec..d15dbc9 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -782,7 +782,7 @@
 	dexLocations := make([]string, 0, len(contents))
 	for _, module := range contents {
 		dexPaths = append(dexPaths, modules[module.Name()])
-		dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name() + ".jar"))
+		dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name()+".jar"))
 	}
 
 	// Build a profile for the modules in this fragment.
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 003f2de..c0f73af 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -628,7 +628,7 @@
 }
 
 type apexJarModulePair struct {
-	apex string
+	apex      string
 	jarModule android.Module
 }
 
@@ -640,7 +640,7 @@
 			name := android.RemoveOptionalPrebuiltPrefix(module.Name())
 			if name == imageConfig.modules.Jar(i) {
 				modules = append(modules, apexJarModulePair{
-					apex: imageConfig.modules.Apex(i),
+					apex:      imageConfig.modules.Apex(i),
 					jarModule: module,
 				})
 				found = true
@@ -1178,7 +1178,7 @@
 		Rule:        android.Phony,
 		Output:      phony,
 		Inputs:      allPhonies,
-		Description: "dump-oat-"+name,
+		Description: "dump-oat-" + name,
 	})
 }
 
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 0f4bd9b..29551ef 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -278,7 +278,7 @@
 	prefix := "dexpreopt_"
 	targets := ctx.Config().Targets[android.Android]
 	if len(targets) > 0 {
-		return prefix+targets[0].Arch.ArchType.String()
+		return prefix + targets[0].Arch.ArchType.String()
 	}
-	return prefix+"unknown_target"
+	return prefix + "unknown_target"
 }
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 176c251..41d4b72 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -77,7 +77,7 @@
 
 func PrepareApexBootJarModule(apexName string, moduleName string) android.FixturePreparer {
 	moduleSourceDir := fmt.Sprintf("packages/modules/%s", apexName)
-	fragmentName := apexName+"-bootclasspath-fragment"
+	fragmentName := apexName + "-bootclasspath-fragment"
 	imageNameProp := ""
 	if apexName == "com.android.art" {
 		fragmentName = "art-bootclasspath-fragment"
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 8039d05..a7e8eb6 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -19,6 +19,7 @@
 	"path/filepath"
 	"regexp"
 	"sort"
+	"strconv"
 	"strings"
 
 	"github.com/google/blueprint/proptools"
@@ -497,6 +498,7 @@
 	if metalavaUseRbe(ctx) {
 		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
 		execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+		compare, _ := strconv.ParseBool(ctx.Config().GetenvWithDefault("RBE_METALAVA_COMPARE", "false"))
 		labels := map[string]string{"type": "tool", "name": "metalava"}
 		// TODO: metalava pool rejects these jobs
 		pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
@@ -505,6 +507,9 @@
 			ExecStrategy:    execStrategy,
 			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
 			Platform:        map[string]string{remoteexec.PoolKey: pool},
+			Compare:         compare,
+			NumLocalRuns:    1,
+			NumRemoteRuns:   1,
 		})
 	}
 
diff --git a/java/java.go b/java/java.go
index 1b9941c..bc24050 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2916,6 +2916,7 @@
 	Sdk_version             bazel.StringAttribute
 	Java_version            bazel.StringAttribute
 	Errorprone_force_enable bazel.BoolAttribute
+	Javac_shard_size        *int64
 }
 
 type javaDependencyLabels struct {
@@ -2970,10 +2971,6 @@
 		// TODO(b/297356582): handle core_platform in bp2build
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version core_platform")
 		return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
-	} else if proptools.String(m.deviceProperties.Sdk_version) == "none" {
-		// TODO(b/297356703): handle system_modules
-		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version none")
-		return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
 	}
 
 	archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
@@ -3105,6 +3102,7 @@
 		Java_version:            bazel.StringAttribute{Value: m.properties.Java_version},
 		Sdk_version:             bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
 		Errorprone_force_enable: errorproneForceEnable,
+		Javac_shard_size:        m.properties.Javac_shard_size,
 	}
 
 	for axis, configToProps := range archVariantProps {
@@ -3407,14 +3405,9 @@
 	return libName
 }
 
-type importAttributes struct {
-	Jars      bazel.LabelListAttribute
-	Exports   bazel.LabelListAttribute
-	Neverlink *bool
-}
-
-type filegroupAttrs struct {
-	Srcs bazel.LabelListAttribute
+type bazelJavaImportAttributes struct {
+	Jars    bazel.LabelListAttribute
+	Exports bazel.LabelListAttribute
 }
 
 // java_import bp2Build converter.
@@ -3430,36 +3423,28 @@
 		}
 	}
 
-	name := android.RemoveOptionalPrebuiltPrefix(i.Name())
-	filegroupTargetName := name + "-jars"
-
-	ctx.CreateBazelTargetModule(
-		bazel.BazelTargetModuleProperties{
-			Rule_class:        "filegroup",
-			Bzl_load_location: "//build/bazel/rules:filegroup.bzl",
-		},
-		android.CommonAttributes{Name: filegroupTargetName},
-		&filegroupAttrs{
-			Srcs: jars,
-		},
-	)
-
-	attrs := &importAttributes{
-		Jars: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + filegroupTargetName}),
+	attrs := &bazelJavaImportAttributes{
+		Jars: jars,
 	}
 	props := bazel.BazelTargetModuleProperties{
 		Rule_class:        "java_import",
 		Bzl_load_location: "//build/bazel/rules/java:import.bzl",
 	}
 
+	name := android.RemoveOptionalPrebuiltPrefix(i.Name())
+
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
 
-	neverlinkAttrs := &importAttributes{
-		Jars:      attrs.Jars,
-		Neverlink: proptools.BoolPtr(true),
+	neverlink := true
+	neverlinkAttrs := &javaLibraryAttributes{
+		Neverlink: bazel.BoolAttribute{Value: &neverlink},
+		Exports:   bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+		javaCommonAttributes: &javaCommonAttributes{
+			Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
+		},
 	}
 	ctx.CreateBazelTargetModule(
-		props,
+		javaLibraryBazelTargetModuleProperties(),
 		android.CommonAttributes{Name: name + "-neverlink"},
 		neverlinkAttrs)
 }
diff --git a/java/java_test.go b/java/java_test.go
index c4fc55b..c54c0e6 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2599,3 +2599,33 @@
 		currentApiTimestampPath,
 	)
 }
+
+func TestDisableFromTextStubForCoverageBuild(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForJavaTest,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		PrepareForTestWithJacocoInstrumentation,
+		FixtureWithLastReleaseApis("foo"),
+		android.FixtureModifyConfig(func(config android.Config) {
+			config.SetApiLibraries([]string{"foo"})
+			config.SetBuildFromTextStub(true)
+		}),
+		android.FixtureModifyEnv(func(env map[string]string) {
+			env["EMMA_INSTRUMENT"] = "true"
+		}),
+	).RunTestWithBp(t, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["A.java"],
+		}
+	`)
+	android.AssertBoolEquals(t, "stub module expected to depend on from-source stub",
+		true, CheckModuleHasDependency(t, result.TestContext,
+			apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
+			apiScopePublic.sourceStubLibraryModuleName("foo")))
+
+	android.AssertBoolEquals(t, "stub module expected to not depend on from-text stub",
+		false, CheckModuleHasDependency(t, result.TestContext,
+			apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
+			apiScopePublic.apiLibraryModuleName("foo")))
+}
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index 9e7a0f1..150d62c 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -15,6 +15,7 @@
 package remoteexec
 
 import (
+	"fmt"
 	"sort"
 	"strings"
 )
@@ -84,6 +85,12 @@
 	// EnvironmentVariables is a list of environment variables whose values should be passed through
 	// to the remote execution.
 	EnvironmentVariables []string
+	// Boolean indicating whether to compare chosen exec strategy with local execution.
+	Compare bool
+	// Number of times the action should be rerun locally.
+	NumLocalRuns int
+	// Number of times the action should be rerun remotely.
+	NumRemoteRuns int
 }
 
 func init() {
@@ -135,6 +142,10 @@
 	}
 	args += " --exec_strategy=" + strategy
 
+	if r.Compare && r.NumLocalRuns >= 0 && r.NumRemoteRuns >= 0 {
+		args += fmt.Sprintf(" --compare=true --num_local_reruns=%d --num_remote_reruns=%d", r.NumLocalRuns, r.NumRemoteRuns)
+	}
+
 	if len(r.Inputs) > 0 {
 		args += " --inputs=" + strings.Join(r.Inputs, ",")
 	}
diff --git a/rust/library.go b/rust/library.go
index 2d5113b..18bf0a0 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -801,6 +801,10 @@
 }
 
 type rustLibraryAttributes struct {
+	commonLibraryAttrs
+}
+
+type commonLibraryAttrs struct {
 	Srcs            bazel.LabelListAttribute
 	Compile_data    bazel.LabelListAttribute
 	Crate_name      bazel.StringAttribute
@@ -811,7 +815,7 @@
 	Proc_macro_deps bazel.LabelListAttribute
 }
 
-func libraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
+func commonLibraryAttrsBp2build(ctx android.Bp2buildMutatorContext, m *Module) *commonLibraryAttrs {
 	lib := m.compiler.(*libraryDecorator)
 
 	srcs, compileData := srcsAndCompileDataAttrs(ctx, *lib.baseCompiler)
@@ -835,7 +839,7 @@
 		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
 	}
 
-	attrs := &rustLibraryAttributes{
+	return &commonLibraryAttrs{
 		Srcs: bazel.MakeLabelListAttribute(
 			srcs,
 		),
@@ -865,6 +869,9 @@
 		},
 	}
 
+}
+
+func libraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
 	ctx.CreateBazelTargetModule(
 		bazel.BazelTargetModuleProperties{
 			Rule_class:        "rust_library",
@@ -873,7 +880,7 @@
 		android.CommonAttributes{
 			Name: m.Name(),
 		},
-		attrs,
+		commonLibraryAttrsBp2build(ctx, m),
 	)
 }
 
@@ -946,3 +953,30 @@
 
 	return &name
 }
+
+type ffiStaticAttributes struct {
+	commonLibraryAttrs
+	Export_includes bazel.StringListAttribute
+}
+
+func ffiStaticBp2build(ctx android.Bp2buildMutatorContext, m *Module) {
+	lib := m.compiler.(*libraryDecorator)
+
+	attrs := &ffiStaticAttributes{
+		Export_includes: bazel.StringListAttribute{
+			Value: lib.Properties.Include_dirs,
+		},
+		commonLibraryAttrs: *commonLibraryAttrsBp2build(ctx, m),
+	}
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "rust_ffi_static",
+			Bzl_load_location: "//build/bazel/rules/rust:rust_ffi_static.bzl",
+		},
+		android.CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs,
+	)
+}
diff --git a/rust/rust.go b/rust/rust.go
index ba63613..19c5230 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1891,6 +1891,8 @@
 		binaryBp2build(ctx, m)
 	} else if ctx.ModuleType() == "rust_protobuf_host" || ctx.ModuleType() == "rust_protobuf" {
 		protoLibraryBp2build(ctx, m)
+	} else if ctx.ModuleType() == "rust_ffi_static" {
+		ffiStaticBp2build(ctx, m)
 	} else {
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
 	}
diff --git a/tests/genrule_sandbox_test.py b/tests/genrule_sandbox_test.py
index 0cebc2a..874859a 100755
--- a/tests/genrule_sandbox_test.py
+++ b/tests/genrule_sandbox_test.py
@@ -61,7 +61,8 @@
   module_path = os.path.join(out_dir, "soong", "module-actions.json")
 
   if not os.path.exists(module_path):
-    _build_with_soong(["json-module-graph"], target_product)
+    # Use GENRULE_SANDBOXING=false so that we don't cause re-analysis later when we do the no-sandboxing build
+    _build_with_soong(["json-module-graph"], target_product, extra_env={"GENRULE_SANDBOXING": "false"})
 
   with open(module_path) as f:
     action_graph = json.load(f)
@@ -131,7 +132,7 @@
   all_outs = list(set.union(*module_to_outs.values()))
 
   print("building without sandboxing...")
-  _build_with_soong(all_outs, args.target_product)
+  _build_with_soong(all_outs, args.target_product, extra_env={"GENRULE_SANDBOXING": "false"})
   with tempfile.TemporaryDirectory() as tempdir:
     for f in all_outs:
       subprocess.check_call(["cp", "--parents", f, tempdir])
diff --git a/ui/build/config.go b/ui/build/config.go
index 264d83e..5925b28 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -1348,7 +1348,7 @@
 }
 
 func (c *configImpl) rbeDownloadTmpDir() string {
-    for _, f := range []string{"RBE_download_tmp_dir", "FLAG_download_tmp_dir"} {
+	for _, f := range []string{"RBE_download_tmp_dir", "FLAG_download_tmp_dir"} {
 		if v, ok := c.environ.Get(f); ok {
 			return v
 		}