Merge "Support uncompressed cpio"
diff --git a/android/apex.go b/android/apex.go
index b87ff09..6bb0751 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -749,74 +749,69 @@
 	}
 	return list
 }(map[string]int{
-	"adbd":                  30,
-	"android.net.ipsec.ike": 30,
-	"androidx-constraintlayout_constraintlayout-solver": 30,
-	"androidx.annotation_annotation":                    28,
-	"androidx.arch.core_core-common":                    28,
-	"androidx.collection_collection":                    28,
-	"androidx.lifecycle_lifecycle-common":               28,
-	"apache-commons-compress":                           29,
-	"bouncycastle_ike_digests":                          30,
-	"brotli-java":                                       29,
-	"captiveportal-lib":                                 28,
-	"flatbuffer_headers":                                30,
-	"framework-permission":                              30,
-	"framework-statsd":                                  30,
-	"gemmlowp_headers":                                  30,
-	"ike-internals":                                     30,
-	"kotlinx-coroutines-android":                        28,
-	"kotlinx-coroutines-core":                           28,
-	"libadb_crypto":                                     30,
-	"libadb_pairing_auth":                               30,
-	"libadb_pairing_connection":                         30,
-	"libadb_pairing_server":                             30,
-	"libadb_protos":                                     30,
-	"libadb_tls_connection":                             30,
-	"libadbconnection_client":                           30,
-	"libadbconnection_server":                           30,
-	"libadbd_core":                                      30,
-	"libadbd_services":                                  30,
-	"libadbd":                                           30,
-	"libapp_processes_protos_lite":                      30,
-	"libasyncio":                                        30,
-	"libbrotli":                                         30,
-	"libbuildversion":                                   30,
-	"libcrypto_static":                                  30,
-	"libcrypto_utils":                                   30,
-	"libdiagnose_usb":                                   30,
-	"libeigen":                                          30,
-	"liblz4":                                            30,
-	"libmdnssd":                                         30,
-	"libneuralnetworks_common":                          30,
-	"libneuralnetworks_headers":                         30,
-	"libneuralnetworks":                                 30,
-	"libprocpartition":                                  30,
-	"libprotobuf-java-lite":                             30,
-	"libprotoutil":                                      30,
-	"libqemu_pipe":                                      30,
-	"libstats_jni":                                      30,
-	"libstatslog_statsd":                                30,
-	"libstatsmetadata":                                  30,
-	"libstatspull":                                      30,
-	"libstatssocket":                                    30,
-	"libsync":                                           30,
-	"libtextclassifier_hash_headers":                    30,
-	"libtextclassifier_hash_static":                     30,
-	"libtflite_kernel_utils":                            30,
-	"libwatchdog":                                       29,
-	"libzstd":                                           30,
-	"metrics-constants-protos":                          28,
-	"net-utils-framework-common":                        29,
-	"permissioncontroller-statsd":                       28,
-	"philox_random_headers":                             30,
-	"philox_random":                                     30,
-	"service-permission":                                30,
-	"service-statsd":                                    30,
-	"statsd-aidl-ndk_platform":                          30,
-	"statsd":                                            30,
-	"tensorflow_headers":                                30,
-	"xz-java":                                           29,
+	"adbd":                           30,
+	"android.net.ipsec.ike":          30,
+	"apache-commons-compress":        29,
+	"bouncycastle_ike_digests":       30,
+	"brotli-java":                    29,
+	"captiveportal-lib":              28,
+	"flatbuffer_headers":             30,
+	"framework-permission":           30,
+	"framework-statsd":               30,
+	"gemmlowp_headers":               30,
+	"ike-internals":                  30,
+	"kotlinx-coroutines-android":     28,
+	"kotlinx-coroutines-core":        28,
+	"libadb_crypto":                  30,
+	"libadb_pairing_auth":            30,
+	"libadb_pairing_connection":      30,
+	"libadb_pairing_server":          30,
+	"libadb_protos":                  30,
+	"libadb_tls_connection":          30,
+	"libadbconnection_client":        30,
+	"libadbconnection_server":        30,
+	"libadbd_core":                   30,
+	"libadbd_services":               30,
+	"libadbd":                        30,
+	"libapp_processes_protos_lite":   30,
+	"libasyncio":                     30,
+	"libbrotli":                      30,
+	"libbuildversion":                30,
+	"libcrypto_static":               30,
+	"libcrypto_utils":                30,
+	"libdiagnose_usb":                30,
+	"libeigen":                       30,
+	"liblz4":                         30,
+	"libmdnssd":                      30,
+	"libneuralnetworks_common":       30,
+	"libneuralnetworks_headers":      30,
+	"libneuralnetworks":              30,
+	"libprocpartition":               30,
+	"libprotobuf-java-lite":          30,
+	"libprotoutil":                   30,
+	"libqemu_pipe":                   30,
+	"libstats_jni":                   30,
+	"libstatslog_statsd":             30,
+	"libstatsmetadata":               30,
+	"libstatspull":                   30,
+	"libstatssocket":                 30,
+	"libsync":                        30,
+	"libtextclassifier_hash_headers": 30,
+	"libtextclassifier_hash_static":  30,
+	"libtflite_kernel_utils":         30,
+	"libwatchdog":                    29,
+	"libzstd":                        30,
+	"metrics-constants-protos":       28,
+	"net-utils-framework-common":     29,
+	"permissioncontroller-statsd":    28,
+	"philox_random_headers":          30,
+	"philox_random":                  30,
+	"service-permission":             30,
+	"service-statsd":                 30,
+	"statsd-aidl-ndk_platform":       30,
+	"statsd":                         30,
+	"tensorflow_headers":             30,
+	"xz-java":                        29,
 })
 
 // Function called while walking an APEX's payload dependencies.
diff --git a/android/arch.go b/android/arch.go
index abcdbbb..b277381 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -436,7 +436,7 @@
 	// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
 	// filters out non-Soong modules.  Now that we've handled them, create a
 	// normal android.BottomUpMutatorContext.
-	mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+	mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
 
 	base := module.base()
 
@@ -576,7 +576,7 @@
 	// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
 	// filters out non-Soong modules.  Now that we've handled them, create a
 	// normal android.BottomUpMutatorContext.
-	mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+	mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
 
 	base := module.base()
 
diff --git a/android/config.go b/android/config.go
index 8090889..e0f3a91 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1624,21 +1624,33 @@
 func splitConfiguredJarPair(str string) (string, string, error) {
 	pair := strings.SplitN(str, ":", 2)
 	if len(pair) == 2 {
-		return pair[0], pair[1], nil
+		apex := pair[0]
+		jar := pair[1]
+		if apex == "" {
+			return apex, jar, fmt.Errorf("invalid apex '%s' in <apex>:<jar> pair '%s', expected format: <apex>:<jar>", apex, str)
+		}
+		return apex, jar, nil
 	} else {
 		return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
 	}
 }
 
-// CreateTestConfiguredJarList is a function to create ConfiguredJarList for
-// tests.
+// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests.
 func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
-	apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
+	// Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to
+	// a json list of strings and then unmarshalling into a ConfiguredJarList instance.
+	b, err := json.Marshal(list)
 	if err != nil {
 		panic(err)
 	}
 
-	return ConfiguredJarList{apexes, jars}
+	var jarList ConfiguredJarList
+	err = json.Unmarshal(b, &jarList)
+	if err != nil {
+		panic(err)
+	}
+
+	return jarList
 }
 
 // EmptyConfiguredJarList returns an empty jar list.
diff --git a/android/config_test.go b/android/config_test.go
index 7bfc800..a11115d 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -100,6 +100,22 @@
 		assertStringEquals(t, "apex1:jarA", list1.String())
 	})
 
+	t.Run("create invalid - missing apex", func(t *testing.T) {
+		defer func() {
+			err := recover().(error)
+			assertStringEquals(t, "malformed (apex, jar) pair: 'jarA', expected format: <apex>:<jar>", err.Error())
+		}()
+		CreateTestConfiguredJarList([]string{"jarA"})
+	})
+
+	t.Run("create invalid - empty apex", func(t *testing.T) {
+		defer func() {
+			err := recover().(error)
+			assertStringEquals(t, "invalid apex '' in <apex>:<jar> pair ':jarA', expected format: <apex>:<jar>", err.Error())
+		}()
+		CreateTestConfiguredJarList([]string{":jarA"})
+	})
+
 	list2 := list1.Append("apex2", "jarB")
 	t.Run("append", func(t *testing.T) {
 		assertStringEquals(t, "apex1:jarA,apex2:jarB", list2.String())
diff --git a/android/filegroup.go b/android/filegroup.go
index 3d1bbc5..7a6cc4f 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -29,7 +29,7 @@
 // https://docs.bazel.build/versions/master/be/general.html#filegroup
 type bazelFilegroupAttributes struct {
 	Name *string
-	Srcs []string
+	Srcs bazel.LabelList
 }
 
 type bazelFilegroup struct {
@@ -52,15 +52,18 @@
 
 // TODO: Create helper functions to avoid this boilerplate.
 func FilegroupBp2Build(ctx TopDownMutatorContext) {
-	if m, ok := ctx.Module().(*fileGroup); ok {
-		name := "__bp2build__" + m.base().BaseModuleName()
-		ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
-			Name: proptools.StringPtr(name),
-			Srcs: m.properties.Srcs,
-		}, &bazel.BazelTargetModuleProperties{
-			Rule_class: "filegroup",
-		})
+	fg, ok := ctx.Module().(*fileGroup)
+	if !ok {
+		return
 	}
+
+	name := "__bp2build__" + fg.base().BaseModuleName()
+	ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
+		Name: proptools.StringPtr(name),
+		Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
+	}, &bazel.BazelTargetModuleProperties{
+		Rule_class: "filegroup",
+	})
 }
 
 type fileGroupProperties struct {
diff --git a/android/module.go b/android/module.go
index dcc2b84..1409d44 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2220,10 +2220,17 @@
 	}
 	var deps []dep
 	b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
-		if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
-			returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+		if aModule, _ := module.(Module); aModule != nil {
+			if aModule.base().BaseModuleName() == name {
+				returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+				if tag == nil || returnedTag == tag {
+					deps = append(deps, dep{aModule, returnedTag})
+				}
+			}
+		} else if b.bp.OtherModuleName(module) == name {
+			returnedTag := b.bp.OtherModuleDependencyTag(module)
 			if tag == nil || returnedTag == tag {
-				deps = append(deps, dep{aModule, returnedTag})
+				deps = append(deps, dep{module, returnedTag})
 			}
 		}
 	})
diff --git a/android/mutator.go b/android/mutator.go
index 6b19dc5..15be65f 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -45,14 +45,30 @@
 }
 
 // RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, bp2buildMutators []RegisterMutatorFunc) {
-	mctx := &registerMutatorsContext{}
-
-	sharedMutators := []RegisterMutatorFunc{
-		RegisterDefaultsPreArchMutators,
+func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
+	mctx := &registerMutatorsContext{
+		bazelConversionMode: true,
 	}
 
-	for _, f := range sharedMutators {
+	bp2buildPreArchMutators = append([]RegisterMutatorFunc{
+		RegisterNamespaceMutator,
+		RegisterDefaultsPreArchMutators,
+		// TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
+		// evaluate the impact on conversion.
+		RegisterPrebuiltsPreArchMutators,
+	},
+		preArchMutators...)
+
+	for _, f := range bp2buildPreArchMutators {
+		f(mctx)
+	}
+
+	bp2buildDepsMutators = append([]RegisterMutatorFunc{
+		registerDepsMutatorBp2Build,
+		registerPathDepsMutator,
+	}, depsMutators...)
+
+	for _, f := range bp2buildDepsMutators {
 		f(mctx)
 	}
 
@@ -77,7 +93,7 @@
 
 	register(preDeps)
 
-	mctx.BottomUp("deps", depsMutator).Parallel()
+	register([]RegisterMutatorFunc{registerDepsMutator})
 
 	register(postDeps)
 
@@ -88,8 +104,9 @@
 }
 
 type registerMutatorsContext struct {
-	mutators   []*mutator
-	finalPhase bool
+	mutators            []*mutator
+	finalPhase          bool
+	bazelConversionMode bool
 }
 
 type RegisterMutatorsContext interface {
@@ -211,6 +228,8 @@
 	finalDeps = append(finalDeps, f)
 }
 
+var bp2buildPreArchMutators = []RegisterMutatorFunc{}
+var bp2buildDepsMutators = []RegisterMutatorFunc{}
 var bp2buildMutators = []RegisterMutatorFunc{}
 
 // RegisterBp2BuildMutator registers specially crafted mutators for
@@ -219,13 +238,24 @@
 //
 // TODO(b/178068862): bring this into TestContext.
 func RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
-	mutatorName := moduleType + "_bp2build"
 	f := func(ctx RegisterMutatorsContext) {
-		ctx.TopDown(mutatorName, m)
+		ctx.TopDown(moduleType, m)
 	}
 	bp2buildMutators = append(bp2buildMutators, f)
 }
 
+// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
+// into Bazel BUILD targets that should run prior to deps and conversion.
+func PreArchBp2BuildMutators(f RegisterMutatorFunc) {
+	bp2buildPreArchMutators = append(bp2buildPreArchMutators, f)
+}
+
+// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
+// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
+func DepsBp2BuildMutators(f RegisterMutatorFunc) {
+	bp2buildDepsMutators = append(bp2buildDepsMutators, f)
+}
+
 type BaseMutatorContext interface {
 	BaseModuleContext
 
@@ -370,32 +400,38 @@
 	// variant of the current module.  The value should not be modified after being passed to
 	// SetVariationProvider.
 	SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{})
+
+	// BazelConversionMode returns whether this mutator is being run as part of Bazel Conversion.
+	BazelConversionMode() bool
 }
 
 type bottomUpMutatorContext struct {
 	bp blueprint.BottomUpMutatorContext
 	baseModuleContext
-	finalPhase bool
+	finalPhase          bool
+	bazelConversionMode bool
 }
 
 func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module,
-	finalPhase bool) BottomUpMutatorContext {
+	finalPhase, bazelConversionMode bool) BottomUpMutatorContext {
 
 	return &bottomUpMutatorContext{
-		bp:                ctx,
-		baseModuleContext: a.base().baseModuleContextFactory(ctx),
-		finalPhase:        finalPhase,
+		bp:                  ctx,
+		baseModuleContext:   a.base().baseModuleContextFactory(ctx),
+		finalPhase:          finalPhase,
+		bazelConversionMode: bazelConversionMode,
 	}
 }
 
 func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
 	finalPhase := x.finalPhase
+	bazelConversionMode := x.bazelConversionMode
 	f := func(ctx blueprint.BottomUpMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
-			m(bottomUpMutatorContextFactory(ctx, a, finalPhase))
+			m(bottomUpMutatorContextFactory(ctx, a, finalPhase, bazelConversionMode))
 		}
 	}
-	mutator := &mutator{name: name, bottomUpMutator: f}
+	mutator := &mutator{name: x.mutatorName(name), bottomUpMutator: f}
 	x.mutators = append(x.mutators, mutator)
 	return mutator
 }
@@ -406,6 +442,13 @@
 	return mutator
 }
 
+func (x *registerMutatorsContext) mutatorName(name string) string {
+	if x.bazelConversionMode {
+		return name + "_bp2build"
+	}
+	return name
+}
+
 func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle {
 	f := func(ctx blueprint.TopDownMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
@@ -416,7 +459,7 @@
 			m(actx)
 		}
 	}
-	mutator := &mutator{name: name, topDownMutator: f}
+	mutator := &mutator{name: x.mutatorName(name), topDownMutator: f}
 	x.mutators = append(x.mutators, mutator)
 	return mutator
 }
@@ -449,6 +492,16 @@
 	}
 }
 
+func registerDepsMutator(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("deps", depsMutator).Parallel()
+}
+
+func registerDepsMutatorBp2Build(ctx RegisterMutatorsContext) {
+	// TODO(b/179313531): Consider a separate mutator that only runs depsMutator for modules that are
+	// being converted to build targets.
+	ctx.BottomUp("deps", depsMutator).Parallel()
+}
+
 func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
 	for _, p := range props {
 		err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
@@ -576,12 +629,28 @@
 
 func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
 	names ...string) []blueprint.Module {
+	if b.bazelConversionMode {
+		_, noSelfDeps := RemoveFromList(b.ModuleName(), names)
+		if len(noSelfDeps) == 0 {
+			return []blueprint.Module(nil)
+		}
+		// In Bazel conversion mode, mutators should not have created any variants. So, when adding a
+		// dependency, the variations would not exist and the dependency could not be added, by
+		// specifying no variations, we will allow adding the dependency to succeed.
+		return b.bp.AddFarVariationDependencies(nil, tag, noSelfDeps...)
+	}
 
 	return b.bp.AddVariationDependencies(variations, tag, names...)
 }
 
 func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
 	tag blueprint.DependencyTag, names ...string) []blueprint.Module {
+	if b.bazelConversionMode {
+		// In Bazel conversion mode, mutators should not have created any variants. So, when adding a
+		// dependency, the variations would not exist and the dependency could not be added, by
+		// specifying no variations, we will allow adding the dependency to succeed.
+		return b.bp.AddFarVariationDependencies(nil, tag, names...)
+	}
 
 	return b.bp.AddFarVariationDependencies(variations, tag, names...)
 }
@@ -609,3 +678,7 @@
 func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) {
 	b.bp.SetVariationProvider(module, provider, value)
 }
+
+func (b *bottomUpMutatorContext) BazelConversionMode() bool {
+	return b.bazelConversionMode
+}
diff --git a/android/paths.go b/android/paths.go
index 8106958..44221be 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"android/soong/bazel"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -331,6 +332,115 @@
 	return ret
 }
 
+// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
+// order to form a Bazel-compatible label for conversion.
+type BazelConversionPathContext interface {
+	EarlyModulePathContext
+
+	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+	OtherModuleName(m blueprint.Module) string
+	OtherModuleDir(m blueprint.Module) string
+}
+
+// BazelLabelForModuleDeps returns a Bazel-compatible label for the requested modules which
+// correspond to dependencies on the module within the given ctx.
+func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
+	var labels bazel.LabelList
+	for _, module := range modules {
+		bpText := module
+		if m := SrcIsModule(module); m == "" {
+			module = ":" + module
+		}
+		if m, t := SrcIsModuleWithTag(module); m != "" {
+			l := getOtherModuleLabel(ctx, m, t)
+			l.Bp_text = bpText
+			labels.Includes = append(labels.Includes, l)
+		} else {
+			ctx.ModuleErrorf("%q, is not a module reference", module)
+		}
+	}
+	return labels
+}
+
+// BazelLabelForModuleSrc returns bazel.LabelList with paths rooted from the module's local source
+// directory. It expands globs, and resolves references to modules using the ":name" syntax to
+// bazel-compatible labels.  Properties passed as the paths or excludes argument must have been
+// annotated with struct tag `android:"path"` so that dependencies on other modules will have
+// already been handled by the path_properties mutator.
+func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
+	return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
+}
+
+// BazelLabelForModuleSrcExcludes returns bazel.LabelList with paths rooted from the module's local
+// source directory, excluding labels included in the excludes argument. It expands globs, and
+// resolves references to modules using the ":name" syntax to bazel-compatible labels. Properties
+// passed as the paths or excludes argument must have been annotated with struct tag
+// `android:"path"` so that dependencies on other modules will have already been handled by the
+// path_properties mutator.
+func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
+	excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
+	excluded := make([]string, 0, len(excludeLabels.Includes))
+	for _, e := range excludeLabels.Includes {
+		excluded = append(excluded, e.Label)
+	}
+	labels := expandSrcsForBazel(ctx, paths, excluded)
+	labels.Excludes = excludeLabels.Includes
+	return labels
+}
+
+// expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local
+// source directory, excluding labels included in the excludes argument. It expands globs, and
+// resolves references to modules using the ":name" syntax to bazel-compatible labels.  Properties
+// passed as the paths or excludes argument must have been annotated with struct tag
+// `android:"path"` so that dependencies on other modules will have already been handled by the
+// path_properties mutator.
+func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
+	labels := bazel.LabelList{
+		Includes: []bazel.Label{},
+	}
+	for _, p := range paths {
+		if m, tag := SrcIsModuleWithTag(p); m != "" {
+			l := getOtherModuleLabel(ctx, m, tag)
+			if !InList(l.Label, expandedExcludes) {
+				l.Bp_text = fmt.Sprintf(":%s", m)
+				labels.Includes = append(labels.Includes, l)
+			}
+		} else {
+			var expandedPaths []bazel.Label
+			if pathtools.IsGlob(p) {
+				globbedPaths := GlobFiles(ctx, pathForModuleSrc(ctx, p).String(), expandedExcludes)
+				globbedPaths = PathsWithModuleSrcSubDir(ctx, globbedPaths, "")
+				for _, path := range globbedPaths {
+					s := path.Rel()
+					expandedPaths = append(expandedPaths, bazel.Label{Label: s})
+				}
+			} else {
+				if !InList(p, expandedExcludes) {
+					expandedPaths = append(expandedPaths, bazel.Label{Label: p})
+				}
+			}
+			labels.Includes = append(labels.Includes, expandedPaths...)
+		}
+	}
+	return labels
+}
+
+// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
+// module. The label will be relative to the current directory if appropriate. The dependency must
+// already be resolved by either deps mutator or path deps mutator.
+func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string) bazel.Label {
+	m, _ := ctx.GetDirectDep(dep)
+	// TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
+	otherModuleName := ctx.OtherModuleName(m)
+	var label bazel.Label
+	if otherDir, dir := ctx.OtherModuleDir(m), ctx.ModuleDir(); otherDir != dir {
+		label.Label = fmt.Sprintf("//%s:%s", otherDir, otherModuleName)
+	} else {
+		label.Label = fmt.Sprintf(":%s", otherModuleName)
+	}
+	return label
+}
+
 // OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
 type OutputPaths []OutputPath
 
diff --git a/android/register.go b/android/register.go
index 02fc97e..18c743f 100644
--- a/android/register.go
+++ b/android/register.go
@@ -115,7 +115,7 @@
 		ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
 	}
 
-	RegisterMutatorsForBazelConversion(ctx.Context, bp2buildMutators)
+	RegisterMutatorsForBazelConversion(ctx.Context, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
 }
 
 // Register the pipeline of singletons, module types, and mutators for
diff --git a/android/testing.go b/android/testing.go
index 5640c29..de338bf 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -56,9 +56,9 @@
 
 type TestContext struct {
 	*Context
-	preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
-	bp2buildMutators                      []RegisterMutatorFunc
-	NameResolver                          *NameResolver
+	preArch, preDeps, postDeps, finalDeps           []RegisterMutatorFunc
+	bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
+	NameResolver                                    *NameResolver
 }
 
 func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -85,13 +85,24 @@
 // RegisterBp2BuildMutator registers a BazelTargetModule mutator for converting a module
 // type to the equivalent Bazel target.
 func (ctx *TestContext) RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
-	mutatorName := moduleType + "_bp2build"
 	f := func(ctx RegisterMutatorsContext) {
-		ctx.TopDown(mutatorName, m)
+		ctx.TopDown(moduleType, m)
 	}
 	ctx.bp2buildMutators = append(ctx.bp2buildMutators, f)
 }
 
+// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
+// into Bazel BUILD targets that should run prior to deps and conversion.
+func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
+	ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f)
+}
+
+// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
+// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
+func (ctx *TestContext) DepsBp2BuildMutators(f RegisterMutatorFunc) {
+	ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
+}
+
 func (ctx *TestContext) Register() {
 	registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
 
@@ -100,7 +111,7 @@
 
 // RegisterForBazelConversion prepares a test context for bp2build conversion.
 func (ctx *TestContext) RegisterForBazelConversion() {
-	RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildMutators)
+	RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
 }
 
 func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index fb84df8..5d00e06 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -52,6 +52,7 @@
 android.hidl.safe_union@1.0(minSdkVersion:29)
 android.hidl.token@1.0(minSdkVersion:29)
 android.hidl.token@1.0-utils(minSdkVersion:29)
+android.net.ipsec.ike(minSdkVersion:30)
 android.net.ipsec.ike(minSdkVersion:current)
 android.net.ipsec.ike.xml(minSdkVersion:(no version))
 androidx-constraintlayout_constraintlayout(minSdkVersion:14)
@@ -238,6 +239,7 @@
 libbase(minSdkVersion:29)
 libbase_headers(minSdkVersion:29)
 libbinder_headers(minSdkVersion:29)
+libbinder_headers_platform_shared(minSdkVersion:29)
 libbinderthreadstateutils(minSdkVersion:29)
 libbluetooth-types-header(minSdkVersion:29)
 libbrotli(minSdkVersion:(no version))
diff --git a/apex/apex.go b/apex/apex.go
index c897042..724a50b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -54,6 +54,8 @@
 func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
 	ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
 	ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
+	ctx.BottomUp("prebuilt_apex_select_source", prebuiltSelectSourceMutator).Parallel()
+	ctx.BottomUp("deapexer_select_source", deapexerSelectSourceMutator).Parallel()
 }
 
 func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 651cadf..8f4a285 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -78,12 +78,17 @@
 	return p.prebuilt.Name(p.ModuleBase.Name())
 }
 
-func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
-	if err := p.apexFileProperties.selectSource(ctx); err != nil {
-		ctx.ModuleErrorf("%s", err)
+func deapexerSelectSourceMutator(ctx android.BottomUpMutatorContext) {
+	p, ok := ctx.Module().(*Deapexer)
+	if !ok {
 		return
 	}
+	if err := p.apexFileProperties.selectSource(ctx); err != nil {
+		ctx.ModuleErrorf("%s", err)
+	}
+}
 
+func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
 	// Add dependencies from the java modules to which this exports files from the `.apex` file onto
 	// this module so that they can access the `DeapexerInfo` object that this provides.
 	for _, lib := range p.properties.Exported_java_libs {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index c72a9eb..3149952 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -250,12 +250,17 @@
 	return name
 }
 
-func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
-	if err := p.properties.selectSource(ctx); err != nil {
-		ctx.ModuleErrorf("%s", err)
+func prebuiltSelectSourceMutator(ctx android.BottomUpMutatorContext) {
+	p, ok := ctx.Module().(*Prebuilt)
+	if !ok {
 		return
 	}
+	if err := p.properties.selectSource(ctx); err != nil {
+		ctx.ModuleErrorf("%s", err)
+	}
+}
 
+func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
 	// Add dependencies onto the java modules that represent the java libraries that are provided by
 	// and exported from this prebuilt apex.
 	for _, lib := range p.properties.Exported_java_libs {
diff --git a/bazel/properties.go b/bazel/properties.go
index 79956e1..5b98d15 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -35,3 +35,26 @@
 	// The target label for the bzl file containing the definition of the rule class.
 	Bzl_load_location string
 }
+
+// Label is used to represent a Bazel compatible Label. Also stores the original bp text to support
+// string replacement.
+type Label struct {
+	Bp_text string
+	Label   string
+}
+
+// LabelList is used to represent a list of Bazel labels.
+type LabelList struct {
+	Includes []Label
+	Excludes []Label
+}
+
+// Append appends the fields of other labelList to the corresponding fields of ll.
+func (ll *LabelList) Append(other LabelList) {
+	if len(ll.Includes) > 0 || len(other.Includes) > 0 {
+		ll.Includes = append(ll.Includes, other.Includes...)
+	}
+	if len(ll.Excludes) > 0 || len(other.Excludes) > 0 {
+		ll.Excludes = append(other.Excludes, other.Excludes...)
+	}
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 1fa3e06..2c293ea 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
 	"fmt"
 	"reflect"
 	"strconv"
@@ -177,7 +178,7 @@
 			panic(fmt.Errorf("Unknown code-generation mode: %s", codegenMode))
 		}
 
-		buildFileToTargets[ctx.ModuleDir(m)] = append(buildFileToTargets[dir], t)
+		buildFileToTargets[dir] = append(buildFileToTargets[dir], t)
 	})
 	return buildFileToTargets
 }
@@ -349,6 +350,13 @@
 		ret += makeIndent(indent)
 		ret += "]"
 	case reflect.Struct:
+		if labels, ok := propertyValue.Interface().(bazel.LabelList); ok {
+			// TODO(b/165114590): convert glob syntax
+			return prettyPrint(reflect.ValueOf(labels.Includes), indent)
+		} else if label, ok := propertyValue.Interface().(bazel.Label); ok {
+			return fmt.Sprintf("%q", label.Label), nil
+		}
+
 		ret = "{\n"
 		// Sort and print the struct props by the key.
 		structProps := extractStructProperties(propertyValue, indent)
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index df7dd17..081b0e5 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -17,6 +17,7 @@
 import (
 	"android/soong/android"
 	"android/soong/genrule"
+	"strings"
 	"testing"
 )
 
@@ -248,22 +249,26 @@
 		ctx.RegisterForBazelConversion()
 
 		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
-		android.FailIfErrored(t, errs)
+		if Errored(t, "", errs) {
+			continue
+		}
 		_, errs = ctx.ResolveDependencies(config)
-		android.FailIfErrored(t, errs)
+		if Errored(t, "", errs) {
+			continue
+		}
 
 		bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
 		if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
-			t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
-		}
-
-		actualBazelTarget := bazelTargets[0]
-		if actualBazelTarget.content != testCase.expectedBazelTarget {
-			t.Errorf(
-				"Expected generated Bazel target to be '%s', got '%s'",
-				testCase.expectedBazelTarget,
-				actualBazelTarget.content,
-			)
+			t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
+		} else {
+			actualBazelTarget := bazelTargets[0]
+			if actualBazelTarget.content != testCase.expectedBazelTarget {
+				t.Errorf(
+					"Expected generated Bazel target to be '%s', got '%s'",
+					testCase.expectedBazelTarget,
+					actualBazelTarget.content,
+				)
+			}
 		}
 	}
 }
@@ -434,13 +439,32 @@
 }
 
 func TestModuleTypeBp2Build(t *testing.T) {
+	otherGenruleBp := map[string]string{
+		"other/Android.bp": `genrule {
+    name: "foo.tool",
+    out: ["foo_tool.out"],
+    srcs: ["foo_tool.in"],
+    cmd: "cp $(in) $(out)",
+}
+genrule {
+    name: "other.tool",
+    out: ["other_tool.out"],
+    srcs: ["other_tool.in"],
+    cmd: "cp $(in) $(out)",
+}`,
+	}
+
 	testCases := []struct {
+		description                        string
 		moduleTypeUnderTest                string
 		moduleTypeUnderTestFactory         android.ModuleFactory
 		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+		preArchMutators                    []android.RegisterMutatorFunc
+		depsMutators                       []android.RegisterMutatorFunc
 		bp                                 string
-		expectedBazelTarget                string
-		description                        string
+		expectedBazelTargets               []string
+		fs                                 map[string]string
+		dir                                string
 	}{
 		{
 			description:                        "filegroup with no srcs",
@@ -448,14 +472,16 @@
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
 			bp: `filegroup {
-	name: "foo",
-	srcs: [],
+    name: "fg_foo",
+    srcs: [],
 }`,
-			expectedBazelTarget: `filegroup(
-    name = "foo",
+			expectedBazelTargets: []string{
+				`filegroup(
+    name = "fg_foo",
     srcs = [
     ],
 )`,
+			},
 		},
 		{
 			description:                        "filegroup with srcs",
@@ -463,30 +489,140 @@
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
 			bp: `filegroup {
-	name: "foo",
-	srcs: ["a", "b"],
+    name: "fg_foo",
+    srcs: ["a", "b"],
 }`,
-			expectedBazelTarget: `filegroup(
-    name = "foo",
+			expectedBazelTargets: []string{`filegroup(
+    name = "fg_foo",
     srcs = [
         "a",
         "b",
     ],
 )`,
+			},
+		},
+		{
+			description:                        "filegroup with excludes srcs",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "fg_foo",
+    srcs: ["a", "b"],
+    exclude_srcs: ["a"],
+}`,
+			expectedBazelTargets: []string{`filegroup(
+    name = "fg_foo",
+    srcs = [
+        "b",
+    ],
+)`,
+			},
+		},
+		{
+			description:                        "filegroup with glob",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "foo",
+    srcs: ["**/*.txt"],
+}`,
+			expectedBazelTargets: []string{`filegroup(
+    name = "foo",
+    srcs = [
+        "other/a.txt",
+        "other/b.txt",
+        "other/subdir/a.txt",
+    ],
+)`,
+			},
+			fs: map[string]string{
+				"other/a.txt":        "",
+				"other/b.txt":        "",
+				"other/subdir/a.txt": "",
+				"other/file":         "",
+			},
+		},
+		{
+			description:                        "filegroup with glob in subdir",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "foo",
+    srcs: ["a.txt"],
+}`,
+			dir: "other",
+			expectedBazelTargets: []string{`filegroup(
+    name = "fg_foo",
+    srcs = [
+        "a.txt",
+        "b.txt",
+        "subdir/a.txt",
+    ],
+)`,
+			},
+			fs: map[string]string{
+				"other/Android.bp": `filegroup {
+    name: "fg_foo",
+    srcs: ["**/*.txt"],
+}`,
+				"other/a.txt":        "",
+				"other/b.txt":        "",
+				"other/subdir/a.txt": "",
+				"other/file":         "",
+			},
+		},
+		{
+			description:                        "depends_on_other_dir_module",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "foobar",
+    srcs: [
+      ":foo",
+        "c",
+    ],
+}`,
+			expectedBazelTargets: []string{`filegroup(
+    name = "foobar",
+    srcs = [
+        "//other:foo",
+        "c",
+    ],
+)`,
+			},
+			fs: map[string]string{
+				"other/Android.bp": `filegroup {
+    name: "foo",
+    srcs: ["a", "b"],
+}`,
+			},
 		},
 		{
 			description:                        "genrule with command line variable replacements",
 			moduleTypeUnderTest:                "genrule",
 			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
 			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
 			bp: `genrule {
+    name: "foo.tool",
+    out: ["foo_tool.out"],
+    srcs: ["foo_tool.in"],
+    cmd: "cp $(in) $(out)",
+}
+
+genrule {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     tools: [":foo.tool"],
     cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
 }`,
-			expectedBazelTarget: `genrule(
+			expectedBazelTargets: []string{
+				`genrule(
     name = "foo",
     cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
     outs = [
@@ -499,20 +635,39 @@
         ":foo.tool",
     ],
 )`,
+				`genrule(
+    name = "foo.tool",
+    cmd = "cp $(SRCS) $(OUTS)",
+    outs = [
+        "foo_tool.out",
+    ],
+    srcs = [
+        "foo_tool.in",
+    ],
+)`,
+			},
 		},
 		{
 			description:                        "genrule using $(locations :label)",
 			moduleTypeUnderTest:                "genrule",
 			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
 			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
 			bp: `genrule {
+    name: "foo.tools",
+    out: ["foo_tool.out", "foo_tool2.out"],
+    srcs: ["foo_tool.in"],
+    cmd: "cp $(in) $(out)",
+   }
+
+genrule {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     tools: [":foo.tools"],
     cmd: "$(locations :foo.tools) -s $(out) $(in)",
 }`,
-			expectedBazelTarget: `genrule(
+			expectedBazelTargets: []string{`genrule(
     name = "foo",
     cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
     outs = [
@@ -525,12 +680,83 @@
         ":foo.tools",
     ],
 )`,
+				`genrule(
+    name = "foo.tools",
+    cmd = "cp $(SRCS) $(OUTS)",
+    outs = [
+        "foo_tool.out",
+        "foo_tool2.out",
+    ],
+    srcs = [
+        "foo_tool.in",
+    ],
+)`,
+			},
+		},
+		{
+			description:                        "genrule using $(locations //absolute:label)",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
+			bp: `genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: ["foo.in"],
+    tool_files: [":foo.tool"],
+    cmd: "$(locations :foo.tool) -s $(out) $(in)",
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
+    outs = [
+        "foo.out",
+    ],
+    srcs = [
+        "foo.in",
+    ],
+    tools = [
+        "//other:foo.tool",
+    ],
+)`,
+			},
+			fs: otherGenruleBp,
+		},
+		{
+			description:                        "genrule srcs using $(locations //absolute:label)",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
+			bp: `genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: [":other.tool"],
+    tool_files: [":foo.tool"],
+    cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
+    outs = [
+        "foo.out",
+    ],
+    srcs = [
+        "//other:other.tool",
+    ],
+    tools = [
+        "//other:foo.tool",
+    ],
+)`,
+			},
+			fs: otherGenruleBp,
 		},
 		{
 			description:                        "genrule using $(location) label should substitute first tool label automatically",
 			moduleTypeUnderTest:                "genrule",
 			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
 			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
 			bp: `genrule {
     name: "foo",
     out: ["foo.out"],
@@ -538,9 +764,9 @@
     tool_files: [":foo.tool", ":other.tool"],
     cmd: "$(location) -s $(out) $(in)",
 }`,
-			expectedBazelTarget: `genrule(
+			expectedBazelTargets: []string{`genrule(
     name = "foo",
-    cmd = "$(location :foo.tool) -s $(OUTS) $(SRCS)",
+    cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
     outs = [
         "foo.out",
     ],
@@ -548,16 +774,19 @@
         "foo.in",
     ],
     tools = [
-        ":foo.tool",
-        ":other.tool",
+        "//other:foo.tool",
+        "//other:other.tool",
     ],
 )`,
+			},
+			fs: otherGenruleBp,
 		},
 		{
 			description:                        "genrule using $(locations) label should substitute first tool label automatically",
 			moduleTypeUnderTest:                "genrule",
 			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
 			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
 			bp: `genrule {
     name: "foo",
     out: ["foo.out"],
@@ -565,9 +794,9 @@
     tools: [":foo.tool", ":other.tool"],
     cmd: "$(locations) -s $(out) $(in)",
 }`,
-			expectedBazelTarget: `genrule(
+			expectedBazelTargets: []string{`genrule(
     name = "foo",
-    cmd = "$(locations :foo.tool) -s $(OUTS) $(SRCS)",
+    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
     outs = [
         "foo.out",
     ],
@@ -575,23 +804,26 @@
         "foo.in",
     ],
     tools = [
-        ":foo.tool",
-        ":other.tool",
+        "//other:foo.tool",
+        "//other:other.tool",
     ],
 )`,
+			},
+			fs: otherGenruleBp,
 		},
 		{
 			description:                        "genrule without tools or tool_files can convert successfully",
 			moduleTypeUnderTest:                "genrule",
 			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
 			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
 			bp: `genrule {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     cmd: "cp $(in) $(out)",
 }`,
-			expectedBazelTarget: `genrule(
+			expectedBazelTargets: []string{`genrule(
     name = "foo",
     cmd = "cp $(SRCS) $(OUTS)",
     outs = [
@@ -601,39 +833,73 @@
         "foo.in",
     ],
 )`,
+			},
 		},
 	}
 
 	dir := "."
 	for _, testCase := range testCases {
-		config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+		fs := make(map[string][]byte)
+		toParse := []string{
+			"Android.bp",
+		}
+		for f, content := range testCase.fs {
+			if strings.HasSuffix(f, "Android.bp") {
+				toParse = append(toParse, f)
+			}
+			fs[f] = []byte(content)
+		}
+		config := android.TestConfig(buildDir, nil, testCase.bp, fs)
 		ctx := android.NewTestContext(config)
 		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+		for _, m := range testCase.depsMutators {
+			ctx.DepsBp2BuildMutators(m)
+		}
 		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
 		ctx.RegisterForBazelConversion()
 
-		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
-		android.FailIfErrored(t, errs)
+		_, errs := ctx.ParseFileList(dir, toParse)
+		if Errored(t, testCase.description, errs) {
+			continue
+		}
 		_, errs = ctx.ResolveDependencies(config)
-		android.FailIfErrored(t, errs)
-
-		bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
-		if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
-			t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+		if Errored(t, testCase.description, errs) {
+			continue
 		}
 
-		actualBazelTarget := bazelTargets[0]
-		if actualBazelTarget.content != testCase.expectedBazelTarget {
-			t.Errorf(
-				"%s: Expected generated Bazel target to be '%s', got '%s'",
-				testCase.description,
-				testCase.expectedBazelTarget,
-				actualBazelTarget.content,
-			)
+		checkDir := dir
+		if testCase.dir != "" {
+			checkDir = testCase.dir
+		}
+		bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[checkDir]
+		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+		} else {
+			for i, target := range bazelTargets {
+				if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+					t.Errorf(
+						"%s: Expected generated Bazel target to be '%s', got '%s'",
+						testCase.description,
+						w,
+						g,
+					)
+				}
+			}
 		}
 	}
 }
 
+func Errored(t *testing.T, desc string, errs []error) bool {
+	t.Helper()
+	if len(errs) > 0 {
+		for _, err := range errs {
+			t.Errorf("%s: %s", desc, err)
+		}
+		return true
+	}
+	return false
+}
+
 type bp2buildMutator = func(android.TopDownMutatorContext)
 
 func TestBp2BuildInlinesDefaults(t *testing.T) {
diff --git a/cc/binary.go b/cc/binary.go
index 71c865b..999b82c 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -182,7 +182,7 @@
 		}
 	}
 
-	if !binary.static() && inList("libc", deps.StaticLibs) {
+	if !binary.static() && inList("libc", deps.StaticLibs) && !ctx.BazelConversionMode() {
 		ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
 			"from static libs or set static_executable: true")
 	}
diff --git a/cc/cc.go b/cc/cc.go
index d282b6e..df38499 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1535,6 +1535,11 @@
 	var vndkVersion string
 	var nameSuffix string
 	if c.InProduct() {
+		if c.ProductSpecific() {
+			// If the module is product specific with 'product_specific: true',
+			// do not add a name suffix because it is a base module.
+			return ""
+		}
 		vndkVersion = ctx.DeviceConfig().ProductVndkVersion()
 		nameSuffix = productSuffix
 	} else {
@@ -1741,7 +1746,7 @@
 
 func (c *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
 	if c.cachedToolchain == nil {
-		c.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
+		c.cachedToolchain = config.FindToolchainWithContext(ctx)
 	}
 	return c.cachedToolchain
 }
@@ -1833,6 +1838,12 @@
 	deps.HeaderLibs = android.LastUniqueStrings(deps.HeaderLibs)
 	deps.RuntimeLibs = android.LastUniqueStrings(deps.RuntimeLibs)
 
+	// In Bazel conversion mode, we dependency and build validations will occur in Bazel, so there is
+	// no need to do so in Soong.
+	if ctx.BazelConversionMode() {
+		return deps
+	}
+
 	for _, lib := range deps.ReexportSharedLibHeaders {
 		if !inList(lib, deps.SharedLibs) {
 			ctx.PropertyErrorf("export_shared_lib_headers", "Shared library not in shared_libs: '%s'", lib)
@@ -2891,12 +2902,12 @@
 	ccDepModule, _ := ccDep.(*Module)
 	isLLndk := ccDepModule != nil && ccDepModule.IsLlndk()
 	isVendorPublicLib := inList(libName, *vendorPublicLibraries)
-	bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
+	nonSystemVariantsExist := ccDep.HasNonSystemVariants() || isLLndk
 
-	if c, ok := ccDep.(*Module); ok {
+	if ccDepModule != nil {
 		// Use base module name for snapshots when exporting to Makefile.
-		if snapshotPrebuilt, ok := c.linker.(snapshotInterface); ok {
-			baseName := c.BaseModuleName()
+		if snapshotPrebuilt, ok := ccDepModule.linker.(snapshotInterface); ok {
+			baseName := ccDepModule.BaseModuleName()
 
 			return baseName + snapshotPrebuilt.snapshotAndroidMkSuffix()
 		}
@@ -2907,10 +2918,10 @@
 		// The vendor module is a no-vendor-variant VNDK library.  Depend on the
 		// core module instead.
 		return libName
-	} else if c.UseVndk() && bothVendorAndCoreVariantsExist {
-		// The vendor module in Make will have been renamed to not conflict with the core
-		// module, so update the dependency name here accordingly.
-		return libName + c.getNameSuffixWithVndkVersion(ctx)
+	} else if ccDep.UseVndk() && nonSystemVariantsExist && ccDepModule != nil {
+		// The vendor and product modules in Make will have been renamed to not conflict with the
+		// core module, so update the dependency name here accordingly.
+		return libName + ccDepModule.Properties.SubName
 	} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
 		return libName + vendorPublicLibrarySuffix
 	} else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7288cc4..6403547 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2712,6 +2712,14 @@
 		system_shared_libs : [],
 	}
 	cc_library {
+		name: "libproduct_vendor",
+		product_specific: true,
+		vendor_available: true,
+		no_libcrt : true,
+		nocrt : true,
+		system_shared_libs : [],
+	}
+	cc_library {
 		name: "libcore",
 		runtime_libs: ["liball_available"],
 		no_libcrt : true,
@@ -2728,7 +2736,7 @@
 	cc_library {
 		name: "libvendor2",
 		vendor: true,
-		runtime_libs: ["liball_available", "libvendor1"],
+		runtime_libs: ["liball_available", "libvendor1", "libproduct_vendor"],
 		no_libcrt : true,
 		nocrt : true,
 		system_shared_libs : [],
@@ -2751,7 +2759,7 @@
 	cc_library {
 		name: "libproduct2",
 		product_specific: true,
-		runtime_libs: ["liball_available", "libproduct1"],
+		runtime_libs: ["liball_available", "libproduct1", "libproduct_vendor"],
 		no_libcrt : true,
 		nocrt : true,
 		system_shared_libs : [],
@@ -2781,7 +2789,7 @@
 	checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
 
 	module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1"}, module)
+	checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1", "libproduct_vendor.vendor"}, module)
 
 	// runtime_libs for product variants have '.product' suffixes if the modules have both core
 	// and product variants.
@@ -2791,7 +2799,7 @@
 	checkRuntimeLibs(t, []string{"liball_available.product"}, module)
 
 	module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1"}, module)
+	checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1", "libproduct_vendor"}, module)
 }
 
 func TestExcludeRuntimeLibs(t *testing.T) {
@@ -2817,10 +2825,10 @@
 	checkRuntimeLibs(t, []string{"liball_available"}, module)
 
 	module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"liball_available", "libvendor1"}, module)
+	checkRuntimeLibs(t, []string{"liball_available", "libvendor1", "libproduct_vendor"}, module)
 
 	module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
-	checkRuntimeLibs(t, []string{"liball_available", "libproduct1"}, module)
+	checkRuntimeLibs(t, []string{"liball_available", "libproduct1", "libproduct_vendor"}, module)
 }
 
 func checkStaticLibs(t *testing.T, expected []string, module *Module) {
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 35dd10f..71c7626 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -142,6 +142,9 @@
 		// Nested and array designated initialization is nice to have.
 		"-Wno-c99-designator",
 
+		// Warnings from clang-12
+		"-Wno-gnu-folding-constant",
+
 		// Calls to the APIs that are newer than the min sdk version of the caller should be
 		// guarded with __builtin_available.
 		"-Wunguarded-availability",
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index db9092d..59c0422 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -32,12 +32,42 @@
 	toolchainFactories[os][arch] = factory
 }
 
+type toolchainContext interface {
+	Os() android.OsType
+	Arch() android.Arch
+}
+
+type conversionContext interface {
+	BazelConversionMode() bool
+}
+
+func FindToolchainWithContext(ctx toolchainContext) Toolchain {
+	t, err := findToolchain(ctx.Os(), ctx.Arch())
+	if err != nil {
+		if c, ok := ctx.(conversionContext); ok && c.BazelConversionMode() {
+			// TODO(b/179123288): determine conversion for toolchain
+			return &toolchainX86_64{}
+		} else {
+			panic(err)
+		}
+	}
+	return t
+}
+
 func FindToolchain(os android.OsType, arch android.Arch) Toolchain {
+	t, err := findToolchain(os, arch)
+	if err != nil {
+		panic(err)
+	}
+	return t
+}
+
+func findToolchain(os android.OsType, arch android.Arch) (Toolchain, error) {
 	factory := toolchainFactories[os][arch.ArchType]
 	if factory == nil {
-		panic(fmt.Errorf("Toolchain not found for %s arch %q", os.String(), arch.String()))
+		return nil, fmt.Errorf("Toolchain not found for %s arch %q", os.String(), arch.String())
 	}
-	return factory(arch)
+	return factory(arch), nil
 }
 
 type Toolchain interface {
diff --git a/cc/linkable.go b/cc/linkable.go
index ab5a552..58919a0 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -106,6 +106,8 @@
 	IsVndkExt() bool
 	IsVndkPrivate() bool
 	HasVendorVariant() bool
+	HasProductVariant() bool
+	HasNonSystemVariants() bool
 	InProduct() bool
 
 	SdkVersion() string
diff --git a/cc/linker.go b/cc/linker.go
index ff07224..6d0d416 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -328,7 +328,9 @@
 		}
 
 		deps.SystemSharedLibs = linker.Properties.System_shared_libs
-		if deps.SystemSharedLibs == nil {
+		// In Bazel conversion mode, variations have not been specified, so SystemSharedLibs may
+		// inaccuarately appear unset, which can cause issues with circular dependencies.
+		if deps.SystemSharedLibs == nil && !ctx.BazelConversionMode() {
 			// Provide a default system_shared_libs if it is unspecified. Note: If an
 			// empty list [] is specified, it implies that the module declines the
 			// default system_shared_libs.
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 9dcb5f3..c17e23d 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -100,7 +100,7 @@
 	if bazelConversionRequested(configuration) {
 		// Run the alternate pipeline of bp2build mutators and singleton to convert Blueprint to BUILD files
 		// before everything else.
-		runBp2Build(configuration, extraNinjaDeps)
+		runBp2Build(srcDir, configuration)
 		// Short-circuit and return.
 		return
 	}
@@ -162,7 +162,7 @@
 // Run Soong in the bp2build mode. This creates a standalone context that registers
 // an alternate pipeline of mutators and singletons specifically for generating
 // Bazel BUILD files instead of Ninja files.
-func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
+func runBp2Build(srcDir string, configuration android.Config) {
 	// Register an alternate set of singletons and mutators for bazel
 	// conversion for Bazel conversion.
 	bp2buildCtx := android.NewContext(configuration)
@@ -172,7 +172,20 @@
 	configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
 	bp2buildCtx.SetNameInterface(newNameResolver(configuration))
 
-	// Run the loading and analysis pipeline.
+	// The bp2build process is a purely functional process that only depends on
+	// Android.bp files. It must not depend on the values of per-build product
+	// configurations or variables, since those will generate different BUILD
+	// files based on how the user has configured their tree.
+	bp2buildCtx.SetModuleListFile(bootstrap.ModuleListFile)
+	extraNinjaDeps, err := bp2buildCtx.ListModulePaths(srcDir)
+	if err != nil {
+		panic(err)
+	}
+	extraNinjaDepsString := strings.Join(extraNinjaDeps, " \\\n ")
+
+	// Run the loading and analysis pipeline to prepare the graph of regular
+	// Modules parsed from Android.bp files, and the BazelTargetModules mapped
+	// from the regular Modules.
 	bootstrap.Main(bp2buildCtx.Context, configuration, extraNinjaDeps...)
 
 	// Run the code-generation phase to convert BazelTargetModules to BUILD files.
@@ -195,7 +208,6 @@
 	ninjaFileName := "build.ninja"
 	ninjaFile := android.PathForOutput(codegenContext, ninjaFileName)
 	ninjaFileD := android.PathForOutput(codegenContext, ninjaFileName+".d")
-	extraNinjaDepsString := strings.Join(extraNinjaDeps, " \\\n ")
 	// A workaround to create the 'nothing' ninja target so `m nothing` works,
 	// since bp2build runs without Kati, and the 'nothing' target is declared in
 	// a Makefile.
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 8c84368..7658154 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -51,6 +51,9 @@
 	// Type of the filesystem. Currently, ext4, cpio, and compressed_cpio are supported. Default
 	// is ext4.
 	Type *string
+
+	// file_contexts file to make image. Currently, only ext4 is supported.
+	File_contexts *string `android:"path"`
 }
 
 // android_filesystem packages a set of modules and their transitive dependencies into a filesystem
@@ -147,6 +150,16 @@
 	return output
 }
 
+func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.OutputPath {
+	builder := android.NewRuleBuilder(pctx, ctx)
+	fcBin := android.PathForModuleOut(ctx, "file_contexts.bin")
+	builder.Command().BuiltTool("sefcontext_compile").
+		FlagWithOutput("-o ", fcBin).
+		Input(android.PathForModuleSrc(ctx, proptools.String(f.properties.File_contexts)))
+	builder.Build("build_filesystem_file_contexts", fmt.Sprintf("Creating filesystem file contexts for %s", f.BaseModuleName()))
+	return fcBin.OutputPath
+}
+
 func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
 	type prop struct {
 		name  string
@@ -193,6 +206,10 @@
 		addStr("partition_name", f.Name())
 	}
 
+	if proptools.String(f.properties.File_contexts) != "" {
+		addPath("selinux_fc", f.buildFileContexts(ctx))
+	}
+
 	propFile = android.PathForModuleOut(ctx, "prop").OutputPath
 	builder := android.NewRuleBuilder(pctx, ctx)
 	builder.Command().Text("rm").Flag("-rf").Output(propFile)
@@ -212,6 +229,10 @@
 			"Consider adding this to bootimg module and signing the entire boot image.")
 	}
 
+	if proptools.String(f.properties.File_contexts) != "" {
+		ctx.PropertyErrorf("file_contexts", "file_contexts is not supported for compressed cpio image.")
+	}
+
 	zipFile := android.PathForModuleOut(ctx, "temp.zip").OutputPath
 	f.CopyDepsToZip(ctx, zipFile)
 
diff --git a/genrule/genrule.go b/genrule/genrule.go
index ddfb459..62aa7f8 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -47,9 +47,14 @@
 		ctx.BottomUp("genrule_tool_deps", toolDepsMutator).Parallel()
 	})
 
+	android.DepsBp2BuildMutators(RegisterGenruleBp2BuildDeps)
 	android.RegisterBp2BuildMutator("genrule", GenruleBp2Build)
 }
 
+func RegisterGenruleBp2BuildDeps(ctx android.RegisterMutatorsContext) {
+	ctx.BottomUp("genrule_tool_deps", toolDepsMutator)
+}
+
 var (
 	pctx = android.NewPackageContext("android/soong/genrule")
 
@@ -776,9 +781,9 @@
 
 type bazelGenruleAttributes struct {
 	Name  *string
-	Srcs  []string
+	Srcs  bazel.LabelList
 	Outs  []string
-	Tools []string
+	Tools bazel.LabelList
 	Cmd   string
 }
 
@@ -795,45 +800,63 @@
 }
 
 func GenruleBp2Build(ctx android.TopDownMutatorContext) {
-	if m, ok := ctx.Module().(*Module); ok {
-		name := "__bp2build__" + m.Name()
-		// Bazel only has the "tools" attribute.
-		tools := append(m.properties.Tools, m.properties.Tool_files...)
-
-		// Replace in and out variables with $< and $@
-		var cmd string
-		if m.properties.Cmd != nil {
-			cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
-			cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
-			cmd = strings.Replace(cmd, "$(genDir)", "$(GENDIR)", -1)
-			if len(tools) > 0 {
-				cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools[0]), -1)
-				cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools[0]), -1)
-			}
-		}
-
-		// The Out prop is not in an immediately accessible field
-		// in the Module struct, so use GetProperties and cast it
-		// to the known struct prop.
-		var outs []string
-		for _, propIntf := range m.GetProperties() {
-			if props, ok := propIntf.(*genRuleProperties); ok {
-				outs = props.Out
-				break
-			}
-		}
-
-		// Create the BazelTargetModule.
-		ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{
-			Name:  proptools.StringPtr(name),
-			Srcs:  m.properties.Srcs,
-			Outs:  outs,
-			Cmd:   cmd,
-			Tools: tools,
-		}, &bazel.BazelTargetModuleProperties{
-			Rule_class: "genrule",
-		})
+	m, ok := ctx.Module().(*Module)
+	if !ok {
+		return
 	}
+	name := "__bp2build__" + m.Name()
+	// Bazel only has the "tools" attribute.
+	tools := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
+	tool_files := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
+	tools.Append(tool_files)
+
+	srcs := android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)
+
+	var allReplacements bazel.LabelList
+	allReplacements.Append(tools)
+	allReplacements.Append(srcs)
+
+	// Replace in and out variables with $< and $@
+	var cmd string
+	if m.properties.Cmd != nil {
+		cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
+		cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
+		cmd = strings.Replace(cmd, "$(genDir)", "$(GENDIR)", -1)
+		if len(tools.Includes) > 0 {
+			cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools.Includes[0].Label), -1)
+			cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools.Includes[0].Label), -1)
+		}
+		for _, l := range allReplacements.Includes {
+			bpLoc := fmt.Sprintf("$(location %s)", l.Bp_text)
+			bpLocs := fmt.Sprintf("$(locations %s)", l.Bp_text)
+			bazelLoc := fmt.Sprintf("$(location %s)", l.Label)
+			bazelLocs := fmt.Sprintf("$(locations %s)", l.Label)
+			cmd = strings.Replace(cmd, bpLoc, bazelLoc, -1)
+			cmd = strings.Replace(cmd, bpLocs, bazelLocs, -1)
+		}
+	}
+
+	// The Out prop is not in an immediately accessible field
+	// in the Module struct, so use GetProperties and cast it
+	// to the known struct prop.
+	var outs []string
+	for _, propIntf := range m.GetProperties() {
+		if props, ok := propIntf.(*genRuleProperties); ok {
+			outs = props.Out
+			break
+		}
+	}
+
+	// Create the BazelTargetModule.
+	ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{
+		Name:  proptools.StringPtr(name),
+		Srcs:  srcs,
+		Outs:  outs,
+		Cmd:   cmd,
+		Tools: tools,
+	}, &bazel.BazelTargetModuleProperties{
+		Rule_class: "genrule",
+	})
 }
 
 func (m *bazelGenrule) Name() string {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index da62100..29c73c1 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -129,8 +129,6 @@
 
 	dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
 
-	buildPath := android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath
-
 	providesUsesLib := ctx.ModuleName()
 	if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
 		name := ulib.ProvidesUsesLib()
@@ -146,7 +144,6 @@
 		slimDexpreoptConfig := &dexpreopt.ModuleConfig{
 			Name:                 ctx.ModuleName(),
 			DexLocation:          dexLocation,
-			BuildPath:            buildPath,
 			EnforceUsesLibraries: d.enforceUsesLibs,
 			ProvidesUsesLibrary:  providesUsesLib,
 			ClassLoaderContexts:  d.classLoaderContexts,
@@ -218,7 +215,7 @@
 	dexpreoptConfig := &dexpreopt.ModuleConfig{
 		Name:            ctx.ModuleName(),
 		DexLocation:     dexLocation,
-		BuildPath:       buildPath,
+		BuildPath:       android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
 		DexPath:         dexJarFile,
 		ManifestPath:    d.manifestFile,
 		UncompressedDex: d.uncompressedDex,
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 0f9ef58..27f363e 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -65,7 +65,7 @@
 			srcs: ["a.java"],
 			compile_dex: true,
 	}
-	`, []string{":foo"}, nil)
+	`, []string{"platform:foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -82,7 +82,7 @@
 			jars: ["a.jar"],
 			compile_dex: true,
 	}
-	`, []string{":foo"}, nil)
+	`, []string{"platform:foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -106,7 +106,7 @@
 			compile_dex: true,
 			prefer: false,
 	}
-	`, []string{":foo"}, nil)
+	`, []string{"platform:foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -135,7 +135,7 @@
 			compile_dex: true,
 			prefer: true,
 	}
-	`, []string{":foo"}, nil)
+	`, []string{"platform:foo"}, nil)
 
 	hiddenAPI := ctx.SingletonForTests("hiddenapi")
 	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -236,7 +236,7 @@
 			jars: ["a.jar"],
 			compile_dex: true,
 	}
-	`, []string{":foo"}, &prebuiltHiddenApiDir)
+	`, []string{"platform:foo"}, &prebuiltHiddenApiDir)
 
 	expectedCpInput := prebuiltHiddenApiDir + "/hiddenapi-flags.csv"
 	expectedCpOutput := buildDir + "/hiddenapi/hiddenapi-flags.csv"
diff --git a/java/java.go b/java/java.go
index 78d974b..91944f6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2687,9 +2687,10 @@
 }
 
 func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
-	if ctx.Arch().ArchType == android.Common {
+	if ctx.Arch().ArchType == android.Common || ctx.BazelConversionMode() {
 		j.deps(ctx)
-	} else {
+	}
+	if ctx.Arch().ArchType != android.Common || ctx.BazelConversionMode() {
 		// These dependencies ensure the host installation rules will install the jar file and
 		// the jni libraries when the wrapper is installed.
 		ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
diff --git a/java/proto.go b/java/proto.go
index dc5519f..652a4da 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -82,7 +82,7 @@
 		case "lite", "":
 			ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-lite")
 		case "full":
-			if ctx.Host() {
+			if ctx.Host() || ctx.BazelConversionMode() {
 				ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-full")
 			} else {
 				ctx.PropertyErrorf("proto.type", "full java protos only supported on the host")
diff --git a/rust/binary.go b/rust/binary.go
index 2963a37..df48916 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -119,6 +119,7 @@
 	outputFile := android.PathForModuleOut(ctx, fileName)
 
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+	flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
 	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
 
 	TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
@@ -132,7 +133,7 @@
 	return outputFile
 }
 
-func (binary *binaryDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (binary *binaryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
 	// Binaries default to dylib dependencies for device, rlib for host.
 	if binary.preferRlib() {
 		return rlibAutoDep
diff --git a/rust/compiler.go b/rust/compiler.go
index c921824..586063e 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -96,7 +96,11 @@
 	// list of C shared library dependencies
 	Shared_libs []string `android:"arch_variant"`
 
-	// list of C static library dependencies
+	// list of C static library dependencies. Note, static libraries prefixed by "lib" will be passed to rustc
+	// along with "-lstatic=<name>". This will bundle the static library into rlib/static libraries so dependents do
+	// not need to also declare the static library as a dependency. Static libraries which are not prefixed by "lib"
+	// cannot be passed to rustc with this flag and will not be bundled into rlib/static libraries, and thus must
+	// be redeclared in dependents.
 	Static_libs []string `android:"arch_variant"`
 
 	// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
diff --git a/rust/fuzz.go b/rust/fuzz.go
index da8f209..6035e68 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -91,6 +91,6 @@
 	return RlibLinkage
 }
 
-func (fuzzer *fuzzDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (fuzzer *fuzzDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
 	return rlibAutoDep
 }
diff --git a/rust/image.go b/rust/image.go
index 5ff10ae..ac8c1b3 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -71,6 +71,15 @@
 	return Bool(mod.VendorProperties.Vendor_available) || Bool(mod.VendorProperties.Odm_available)
 }
 
+// Always returns false because rust modules do not support product variant.
+func (mod *Module) HasProductVariant() bool {
+	return Bool(mod.VendorProperties.Product_available)
+}
+
+func (mod *Module) HasNonSystemVariants() bool {
+	return mod.HasVendorVariant() || mod.HasProductVariant()
+}
+
 func (c *Module) InProduct() bool {
 	return false
 }
diff --git a/rust/library.go b/rust/library.go
index 6433285..7ff13ec 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -219,13 +219,17 @@
 	library.MutatedProperties.VariantIsSource = true
 }
 
-func (library *libraryDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
 	if library.preferRlib() {
 		return rlibAutoDep
 	} else if library.rlib() || library.static() {
 		return rlibAutoDep
 	} else if library.dylib() || library.shared() {
 		return dylibAutoDep
+	} else if ctx.BazelConversionMode() {
+		// In Bazel conversion mode, we are currently ignoring the deptag, so we just need to supply a
+		// compatible tag in order to add the dependency.
+		return rlibAutoDep
 	} else {
 		panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName()))
 	}
@@ -439,6 +443,7 @@
 	}
 
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+	flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
 	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
 
 	if library.dylib() {
@@ -478,7 +483,6 @@
 
 	if library.rlib() || library.dylib() {
 		library.flagExporter.exportLinkDirs(deps.linkDirs...)
-		library.flagExporter.exportDepFlags(deps.depFlags...)
 		library.flagExporter.exportLinkObjects(deps.linkObjects...)
 	}
 
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index f753e7f..115045a 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -79,6 +79,6 @@
 	return stem + String(procMacro.baseCompiler.Properties.Suffix)
 }
 
-func (procMacro *procMacroDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (procMacro *procMacroDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
 	return rlibAutoDep
 }
diff --git a/rust/rust.go b/rust/rust.go
index 2ef9daf..e1af776 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -280,10 +280,15 @@
 	SharedLibDeps android.Paths
 	StaticLibs    android.Paths
 	ProcMacros    RustLibraries
-	linkDirs      []string
-	depFlags      []string
-	linkObjects   []string
-	//ReexportedDeps android.Paths
+
+	// depFlags and depLinkFlags are rustc and linker (clang) flags.
+	depFlags     []string
+	depLinkFlags []string
+
+	// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker.
+	// Both of these are exported and propagate to dependencies.
+	linkDirs    []string
+	linkObjects []string
 
 	// Used by bindgen modules which call clang
 	depClangFlags         []string
@@ -328,12 +333,10 @@
 
 type exportedFlagsProducer interface {
 	exportLinkDirs(...string)
-	exportDepFlags(...string)
 	exportLinkObjects(...string)
 }
 
 type flagExporter struct {
-	depFlags    []string
 	linkDirs    []string
 	linkObjects []string
 }
@@ -342,17 +345,12 @@
 	flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
 }
 
-func (flagExporter *flagExporter) exportDepFlags(flags ...string) {
-	flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...))
-}
-
 func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
 	flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
 }
 
 func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
 	ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
-		Flags:       flagExporter.depFlags,
 		LinkDirs:    flagExporter.linkDirs,
 		LinkObjects: flagExporter.linkObjects,
 	})
@@ -785,7 +783,7 @@
 )
 
 type autoDeppable interface {
-	autoDep(ctx BaseModuleContext) autoDep
+	autoDep(ctx android.BottomUpMutatorContext) autoDep
 }
 
 func (mod *Module) begin(ctx BaseModuleContext) {
@@ -898,8 +896,21 @@
 			exportDep := false
 			switch {
 			case cc.IsStaticDepTag(depTag):
-				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
+				// Link cc static libraries using "-lstatic" so rustc can reason about how to handle these
+				// (for example, bundling them into rlibs).
+				//
+				// rustc does not support linking libraries with the "-l" flag unless they are prefixed by "lib".
+				// If we need to link a library that isn't prefixed by "lib", we'll just link to it directly through
+				// linkObjects; such a library may need to be redeclared by static dependents.
+				if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
+					depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
+				}
+
+				// Add this to linkObjects to pass the library directly to the linker as well. This propagates
+				// to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
 				depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
+
 				exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
 				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
 				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
@@ -1213,6 +1224,16 @@
 	return false
 }
 
+// If a library file has a "lib" prefix, extract the library name without the prefix.
+func libNameFromFilePath(filepath android.Path) (string, bool) {
+	libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
+	if strings.HasPrefix(libName, "lib") {
+		libName = libName[3:]
+		return libName, true
+	}
+	return "", false
+}
+
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var String = proptools.String
diff --git a/rust/rust_test.go b/rust/rust_test.go
index abc9af9..a32c6a7 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -230,6 +230,7 @@
 		}
 	`)
 	module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+	rustc := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustc")
 
 	// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
 	if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
@@ -251,6 +252,11 @@
 	if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
 		t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
 	}
+
+	if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=static") {
+		t.Errorf("-lstatic flag not being passed to rustc for static library")
+	}
+
 }
 
 func TestSourceProviderDeps(t *testing.T) {
diff --git a/rust/test.go b/rust/test.go
index 92b4860..3fa5f95 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -141,7 +141,7 @@
 	return flags
 }
 
-func (test *testDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (test *testDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
 	return rlibAutoDep
 }
 
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 18749b5..66e493b 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -154,9 +154,6 @@
 }
 
 func (s *ShBinary) DepsMutator(ctx android.BottomUpMutatorContext) {
-	if s.properties.Src == nil {
-		ctx.PropertyErrorf("src", "missing prebuilt source file")
-	}
 }
 
 func (s *ShBinary) OutputFile() android.OutputPath {
@@ -203,6 +200,10 @@
 }
 
 func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
+	if s.properties.Src == nil {
+		ctx.PropertyErrorf("src", "missing prebuilt source file")
+	}
+
 	s.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(s.properties.Src))
 	filename := proptools.String(s.properties.Filename)
 	filenameFromSrc := proptools.Bool(s.properties.Filename_from_src)
@@ -275,7 +276,7 @@
 	ctx.AddFarVariationDependencies(ctx.Target().Variations(), shTestDataBinsTag, s.testProperties.Data_bins...)
 	ctx.AddFarVariationDependencies(append(ctx.Target().Variations(), sharedLibVariations...),
 		shTestDataLibsTag, s.testProperties.Data_libs...)
-	if ctx.Target().Os.Class == android.Host && len(ctx.Config().Targets[android.Android]) > 0 {
+	if (ctx.Target().Os.Class == android.Host || ctx.BazelConversionMode()) && len(ctx.Config().Targets[android.Android]) > 0 {
 		deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
 		ctx.AddFarVariationDependencies(deviceVariations, shTestDataDeviceBinsTag, s.testProperties.Data_device_bins...)
 		ctx.AddFarVariationDependencies(append(deviceVariations, sharedLibVariations...),