Merge "Remove Python enables identical to global defaults."
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 872e6a0..cad9ec7 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -37,6 +37,7 @@
 
 var (
 	Bp2buildDefaultConfig = Bp2BuildConfig{
+		"art":                                   Bp2BuildDefaultTrue,
 		"art/libartbase":                        Bp2BuildDefaultTrueRecursively,
 		"art/libartpalette":                     Bp2BuildDefaultTrueRecursively,
 		"art/libdexfile":                        Bp2BuildDefaultTrueRecursively,
@@ -54,6 +55,7 @@
 		"build/soong/cc/libbuildversion":     Bp2BuildDefaultTrue, // Skip tests subdir
 		"build/soong/cc/ndkstubgen":          Bp2BuildDefaultTrue,
 		"build/soong/cc/symbolfile":          Bp2BuildDefaultTrue,
+		"build/soong/licenses":               Bp2BuildDefaultTrue,
 		"build/soong/linkerconfig":           Bp2BuildDefaultTrueRecursively,
 		"build/soong/scripts":                Bp2BuildDefaultTrueRecursively,
 
@@ -98,6 +100,7 @@
 		"external/aac":                           Bp2BuildDefaultTrueRecursively,
 		"external/arm-optimized-routines":        Bp2BuildDefaultTrueRecursively,
 		"external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
+		"external/auto":                          Bp2BuildDefaultTrue,
 		"external/auto/common":                   Bp2BuildDefaultTrueRecursively,
 		"external/auto/service":                  Bp2BuildDefaultTrueRecursively,
 		"external/boringssl":                     Bp2BuildDefaultTrueRecursively,
@@ -162,10 +165,12 @@
 		"frameworks/av/media/liberror":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/services/minijail":                    Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/module/minijail":                Bp2BuildDefaultTrueRecursively,
+		"frameworks/base/libs/androidfw":                     Bp2BuildDefaultTrue,
 		"frameworks/base/media/tests/MediaDump":              Bp2BuildDefaultTrue,
 		"frameworks/base/services/tests/servicestests/aidl":  Bp2BuildDefaultTrue,
 		"frameworks/base/startop/apps/test":                  Bp2BuildDefaultTrue,
 		"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
+		"frameworks/base/tools/aapt2":                        Bp2BuildDefaultTrue,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/arect":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/math":                        Bp2BuildDefaultTrueRecursively,
@@ -213,6 +218,7 @@
 		"packages/apps/DevCamera":                          Bp2BuildDefaultTrue,
 		"packages/apps/HTMLViewer":                         Bp2BuildDefaultTrue,
 		"packages/apps/Protips":                            Bp2BuildDefaultTrue,
+		"packages/apps/SafetyRegulatoryInfo":               Bp2BuildDefaultTrue,
 		"packages/apps/WallpaperPicker":                    Bp2BuildDefaultTrue,
 		"packages/modules/StatsD/lib/libstatssocket":       Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb":                             Bp2BuildDefaultTrue,
@@ -234,6 +240,7 @@
 		"prebuilts/runtime/mainline/platform/sdk":  Bp2BuildDefaultTrueRecursively,
 		"prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/support":            Bp2BuildDefaultTrue,
+		"prebuilts/tools":                          Bp2BuildDefaultTrue,
 		"prebuilts/tools/common/m2":                Bp2BuildDefaultTrue,
 
 		"system/apex":                                            Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
@@ -256,6 +263,7 @@
 		"system/core/libvndksupport":                             Bp2BuildDefaultTrueRecursively,
 		"system/core/property_service/libpropertyinfoparser":     Bp2BuildDefaultTrueRecursively,
 		"system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
+		"system/incremental_delivery/incfs":                      Bp2BuildDefaultTrue,
 		"system/libartpalette":                                   Bp2BuildDefaultTrueRecursively,
 		"system/libbase":                                         Bp2BuildDefaultTrueRecursively,
 		"system/libfmq":                                          Bp2BuildDefaultTrue,
@@ -275,6 +283,7 @@
 		"system/libprocinfo":                                     Bp2BuildDefaultTrue,
 		"system/libziparchive":                                   Bp2BuildDefaultTrueRecursively,
 		"system/logging":                                         Bp2BuildDefaultTrueRecursively,
+		"system/media":                                           Bp2BuildDefaultTrue,
 		"system/media/audio":                                     Bp2BuildDefaultTrueRecursively,
 		"system/media/audio_utils":                               Bp2BuildDefaultTrueRecursively,
 		"system/memory/libion":                                   Bp2BuildDefaultTrueRecursively,
@@ -283,8 +292,8 @@
 		"system/testing/gtest_extras":                            Bp2BuildDefaultTrueRecursively,
 		"system/timezone/apex":                                   Bp2BuildDefaultTrueRecursively,
 		"system/timezone/output_data":                            Bp2BuildDefaultTrueRecursively,
-		"system/tools/sysprop":                                   Bp2BuildDefaultTrue,
 		"system/tools/aidl/build/tests_bp2build":                 Bp2BuildDefaultTrue,
+		"system/tools/sysprop":                                   Bp2BuildDefaultTrue,
 		"system/unwinding/libunwindstack":                        Bp2BuildDefaultTrueRecursively,
 
 		"tools/apksig": Bp2BuildDefaultTrue,
@@ -306,6 +315,7 @@
 		// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
 		// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
 		"external/bazelbuild-rules_android":/* recursive = */ true,
+		"external/bazelbuild-rules_license":/* recursive = */ true,
 		"external/bazelbuild-kotlin-rules":/* recursive = */ true,
 		"external/bazel-skylib":/* recursive = */ true,
 		"external/guava":/* recursive = */ true,
@@ -330,6 +340,8 @@
 	}
 
 	Bp2buildModuleAlwaysConvertList = []string{
+		"libidmap2_policies",
+		"libSurfaceFlingerProp",
 		// cc mainline modules
 		"code_coverage.policy",
 		"code_coverage.policy.other",
@@ -371,7 +383,6 @@
 		"libgraphicsenv",
 		"libhardware",
 		"libhardware_headers",
-		"libincfs_headers",
 		"libnativeloader-headers",
 		"libnativewindow_headers",
 		"libneuralnetworks_headers",
@@ -494,6 +505,7 @@
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
+		"license",
 		"linker_config",
 		"java_import",
 		"java_import_host",
@@ -553,15 +565,16 @@
 		"auto_value_plugin_resources",      // TODO(b/210751803), we don't handle path property for filegroups
 
 		// go deps:
+		"aapt2-protos",                                                                               // depends on soong_zip, a go binary
 		"analyze_bcpf",                                                                               // depends on bpmodify a blueprint_go_binary.
 		"apex-protos",                                                                                // depends on soong_zip, a go binary
 		"generated_android_icu4j_src_files", "generated_android_icu4j_test_files", "icu4c_test_data", // depends on unconverted modules: soong_zip
 		"host_bionic_linker_asm",                                                  // depends on extract_linker, a go binary.
 		"host_bionic_linker_script",                                               // depends on extract_linker, a go binary.
 		"libc_musl_sysroot_bionic_arch_headers",                                   // depends on soong_zip
-		"libc_musl_sysroot_zlib_headers",                                          // depends on soong_zip and zip2zip
 		"libc_musl_sysroot_bionic_headers",                                        // 218405924, depends on soong_zip and generates duplicate srcs
 		"libc_musl_sysroot_libc++_headers", "libc_musl_sysroot_libc++abi_headers", // depends on soong_zip, zip2zip
+		"libc_musl_sysroot_zlib_headers", // depends on soong_zip and zip2zip
 		"robolectric-sqlite4java-native", // depends on soong_zip, a go binary
 		"robolectric_tzdata",             // depends on soong_zip, a go binary
 
@@ -618,6 +631,9 @@
 		// '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule
 		"toybox-static",
 
+		// aidl files not created
+		"overlayable_policy_aidl_interface",
+
 		// cc_test related.
 		// Failing host cc_tests
 		"memunreachable_unit_test",
@@ -642,6 +658,8 @@
 		"libnativebridge6-test-case",
 		"libnativebridge6prezygotefork",
 
+		"libandroidfw_tests", "aapt2_tests", // failing due to data path issues
+
 		// cc_test with unconverted deps, or are device-only (and not verified to pass yet)
 		"AMRWBEncTest",
 		"AmrnbDecoderTest",     // depends on unconverted modules: libaudioutils, libsndfile
diff --git a/android/androidmk.go b/android/androidmk.go
index 006e43d..18e3e7a 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -366,7 +366,9 @@
 	// Collate the contributions this module makes to the dist.
 	distContributions := &distContributions{}
 
-	distContributions.licenseMetadataFile = amod.licenseMetadataFile
+	if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
+		distContributions.licenseMetadataFile = amod.licenseMetadataFile
+	}
 
 	// Iterate over this module's dist structs, merged from the dist and dists properties.
 	for _, dist := range amod.Dists() {
@@ -458,10 +460,12 @@
 		ret = append(ret, fmt.Sprintf(".PHONY: %s\n", d.goals))
 		// Create dist-for-goals calls for each of the copy instructions.
 		for _, c := range d.copies {
-			ret = append(
-				ret,
-				fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))\n",
-					c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String()))
+			if distContributions.licenseMetadataFile != nil {
+				ret = append(
+					ret,
+					fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))\n",
+						c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String()))
+			}
 			ret = append(
 				ret,
 				fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", d.goals, c.from.String(), c.dest))
diff --git a/android/apex.go b/android/apex.go
index 00b7241..3c945ae 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -454,8 +454,6 @@
 	}
 	return InList(what, apex_available) ||
 		(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
-		(what == "com.android.btservices" && InList("com.android.bluetooth", apex_available)) || // TODO b/243054261
-		(what == "com.android.bluetooth" && InList("com.android.btservices", apex_available)) || // TODO b/243054261
 		(strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
 }
 
diff --git a/android/bazel.go b/android/bazel.go
index eb6aca4..dd1de7b 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -32,10 +32,13 @@
 	Bp2BuildTopLevel = "."
 )
 
-// Bp2buildAidlLibrary describes a filegroup module that are converted to aidl_library
-type Bp2buildAidlLibrary interface {
+// FileGroupAsLibrary describes a filegroup module that is converted to some library
+// such as aidl_library or proto_library.
+type FileGroupAsLibrary interface {
 	ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool
+	ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool
 	GetAidlLibraryLabel(ctx BazelConversionPathContext) string
+	GetProtoLibraryLabel(ctx BazelConversionPathContext) string
 }
 
 type BazelConversionStatus struct {
@@ -443,8 +446,8 @@
 	if ok, directoryPath := bp2buildDefaultTrueRecursively(packagePath, allowlist.defaultConfig); ok {
 		if moduleNameAllowed {
 			ctx.ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
-				" or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'",
-				directoryPath)
+				" or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'"+
+				" Module: '%s'", directoryPath, moduleName)
 			return false
 		}
 
diff --git a/android/bazel_test.go b/android/bazel_test.go
index b578cca..dbe6067 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -266,7 +266,7 @@
 		{
 			description:    "module allowlist and enabled directory",
 			shouldConvert:  false,
-			expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"},
+			expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
 			module: TestBazelModule{
 				TestModuleInfo: bazel.TestModuleInfo{
 					ModuleName: "foo",
@@ -287,7 +287,7 @@
 		{
 			description:    "module allowlist and enabled subdirectory",
 			shouldConvert:  false,
-			expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"},
+			expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
 			module: TestBazelModule{
 				TestModuleInfo: bazel.TestModuleInfo{
 					ModuleName: "foo",
diff --git a/android/filegroup.go b/android/filegroup.go
index e609f63..6b11172 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -33,6 +33,8 @@
 	ctx.RegisterModuleType("filegroup", FileGroupFactory)
 })
 
+var convertedProtoLibrarySuffix = "_bp2build_converted"
+
 // IsFilegroup checks that a module is a filegroup type
 func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool {
 	return ctx.OtherModuleType(m) == "filegroup"
@@ -117,6 +119,24 @@
 
 		ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
 	} else {
+		if fg.ShouldConvertToProtoLibrary(ctx) {
+			// TODO(b/246997908): we can remove this tag if we could figure out a
+			// solution for this bug.
+			tags := []string{"manual"}
+			attrs := &ProtoAttrs{
+				Srcs:                srcs,
+				Strip_import_prefix: fg.properties.Path,
+				Tags:                tags,
+			}
+
+			ctx.CreateBazelTargetModule(
+				bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
+				CommonAttributes{Name: fg.Name() + convertedProtoLibrarySuffix},
+				attrs)
+		}
+
+		// TODO(b/242847534): Still convert to a filegroup because other unconverted
+		// modules may depend on the filegroup
 		attrs := &bazelFilegroupAttributes{
 			Srcs: srcs,
 		}
@@ -150,14 +170,14 @@
 type fileGroup struct {
 	ModuleBase
 	BazelModuleBase
-	Bp2buildAidlLibrary
+	FileGroupAsLibrary
 	properties fileGroupProperties
 	srcs       Paths
 }
 
 var _ MixedBuildBuildable = (*fileGroup)(nil)
 var _ SourceFileProducer = (*fileGroup)(nil)
-var _ Bp2buildAidlLibrary = (*fileGroup)(nil)
+var _ FileGroupAsLibrary = (*fileGroup)(nil)
 
 // filegroup contains a list of files that are referenced by other modules
 // properties (such as "srcs") using the syntax ":<name>". filegroup are
@@ -243,11 +263,19 @@
 }
 
 func (fg *fileGroup) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool {
+	return fg.shouldConvertToLibrary(ctx, ".aidl")
+}
+
+func (fg *fileGroup) ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool {
+	return fg.shouldConvertToLibrary(ctx, ".proto")
+}
+
+func (fg *fileGroup) shouldConvertToLibrary(ctx BazelConversionPathContext, suffix string) bool {
 	if len(fg.properties.Srcs) == 0 || !fg.ShouldConvertWithBp2build(ctx) {
 		return false
 	}
 	for _, src := range fg.properties.Srcs {
-		if !strings.HasSuffix(src, ".aidl") {
+		if !strings.HasSuffix(src, suffix) {
 			return false
 		}
 	}
@@ -255,6 +283,14 @@
 }
 
 func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string {
+	return fg.getFileGroupAsLibraryLabel(ctx)
+}
+
+func (fg *fileGroup) GetProtoLibraryLabel(ctx BazelConversionPathContext) string {
+	return fg.getFileGroupAsLibraryLabel(ctx) + convertedProtoLibrarySuffix
+}
+
+func (fg *fileGroup) getFileGroupAsLibraryLabel(ctx BazelConversionPathContext) string {
 	if ctx.OtherModuleDir(fg.module) == ctx.ModuleDir() {
 		return ":" + fg.Name()
 	} else {
@@ -265,12 +301,19 @@
 // Given a name in srcs prop, check to see if the name references a filegroup
 // and the filegroup is converted to aidl_library
 func IsConvertedToAidlLibrary(ctx BazelConversionPathContext, name string) bool {
+	if fg, ok := ToFileGroupAsLibrary(ctx, name); ok {
+		return fg.ShouldConvertToAidlLibrary(ctx)
+	}
+	return false
+}
+
+func ToFileGroupAsLibrary(ctx BazelConversionPathContext, name string) (FileGroupAsLibrary, bool) {
 	if module, ok := ctx.ModuleFromName(name); ok {
 		if IsFilegroup(ctx, module) {
-			if fg, ok := module.(Bp2buildAidlLibrary); ok {
-				return fg.ShouldConvertToAidlLibrary(ctx)
+			if fg, ok := module.(FileGroupAsLibrary); ok {
+				return fg, true
 			}
 		}
 	}
-	return false
+	return nil, false
 }
diff --git a/android/gen_notice.go b/android/gen_notice.go
index 2eb6bec..008aac5 100644
--- a/android/gen_notice.go
+++ b/android/gen_notice.go
@@ -111,6 +111,9 @@
 }
 
 func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
+	if ctx.ContainsProperty("licenses") {
+		ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
+	}
 	if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
 		ctx.ModuleErrorf("can be html or xml but not both")
 	}
@@ -195,6 +198,16 @@
 	return nil, fmt.Errorf("unrecognized tag %q", tag)
 }
 
+var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)
+
+// Implements AndroidMkEntriesProvider
+func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
+	return []AndroidMkEntries{AndroidMkEntries{
+		Class:      "ETC",
+		OutputFile: OptionalPathForPath(m.output),
+	}}
+}
+
 // missingReferencesRule emits an ErrorRule for missing module references.
 func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
 	if len(m.missing) < 1 {
diff --git a/android/gen_notice_test.go b/android/gen_notice_test.go
index b45ce4f..99d982b 100644
--- a/android/gen_notice_test.go
+++ b/android/gen_notice_test.go
@@ -12,6 +12,19 @@
 	expectedErrors []string
 }{
 	{
+		name: "gen_notice must not accept licenses property",
+		fs: map[string][]byte{
+			"top/Android.bp": []byte(`
+				gen_notice {
+					name: "top_license",
+					licenses: ["other_license"],
+				}`),
+		},
+		expectedErrors: []string{
+			`not supported on "gen_notice" modules`,
+		},
+	},
+	{
 		name: "bad gen_notice",
 		fs: map[string][]byte{
 			"top/Android.bp": []byte(`
diff --git a/android/license.go b/android/license.go
index ebee055..cde5e6e 100644
--- a/android/license.go
+++ b/android/license.go
@@ -15,7 +15,10 @@
 package android
 
 import (
+	"android/soong/bazel"
+	"fmt"
 	"github.com/google/blueprint"
+	"os"
 )
 
 type licenseKindDependencyTag struct {
@@ -48,14 +51,55 @@
 	Visibility []string
 }
 
+var _ Bazelable = &licenseModule{}
+
 type licenseModule struct {
 	ModuleBase
 	DefaultableModuleBase
 	SdkBase
+	BazelModuleBase
 
 	properties licenseProperties
 }
 
+type bazelLicenseAttributes struct {
+	License_kinds    []string
+	Copyright_notice *string
+	License_text     bazel.LabelAttribute
+	Package_name     *string
+	Visibility       []string
+}
+
+func (m *licenseModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+	attrs := &bazelLicenseAttributes{
+		License_kinds:    m.properties.License_kinds,
+		Copyright_notice: m.properties.Copyright_notice,
+		Package_name:     m.properties.Package_name,
+		Visibility:       m.properties.Visibility,
+	}
+
+	// TODO(asmundak): Soong supports multiple license texts while Bazel's license
+	// rule does not. Have android_license create a genrule to concatenate multiple
+	// license texts.
+	if len(m.properties.License_text) > 1 && ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE") {
+		fmt.Fprintf(os.Stderr, "warning: using only the first license_text item from //%s:%s\n",
+			ctx.ModuleDir(), m.Name())
+	}
+	if len(m.properties.License_text) >= 1 {
+		attrs.License_text.SetValue(BazelLabelForModuleSrcSingle(ctx, m.properties.License_text[0]))
+	}
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "android_license",
+			Bzl_load_location: "//build/bazel/rules/license:license.bzl",
+		},
+		CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs)
+}
+
 func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
 	ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...)
 }
@@ -78,7 +122,7 @@
 	module := &licenseModule{}
 
 	base := module.base()
-	module.AddProperties(&base.nameProperties, &module.properties)
+	module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
 
 	// The visibility property needs to be checked and parsed by the visibility module.
 	setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
@@ -86,6 +130,7 @@
 	InitSdkAwareModule(module)
 	initAndroidModuleBase(module)
 	InitDefaultableModule(module)
+	InitBazelModule(module)
 
 	return module
 }
diff --git a/android/license_kind.go b/android/license_kind.go
index 838dedd..24b91e4 100644
--- a/android/license_kind.go
+++ b/android/license_kind.go
@@ -14,6 +14,8 @@
 
 package android
 
+import "android/soong/bazel"
+
 func init() {
 	RegisterLicenseKindBuildComponents(InitRegistrationContext)
 }
@@ -32,13 +34,39 @@
 	Visibility []string
 }
 
+var _ Bazelable = &licenseKindModule{}
+
 type licenseKindModule struct {
 	ModuleBase
 	DefaultableModuleBase
+	BazelModuleBase
 
 	properties licenseKindProperties
 }
 
+type bazelLicenseKindAttributes struct {
+	Conditions []string
+	Url        string
+	Visibility []string
+}
+
+func (m *licenseKindModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+	attrs := &bazelLicenseKindAttributes{
+		Conditions: m.properties.Conditions,
+		Url:        m.properties.Url,
+		Visibility: m.properties.Visibility,
+	}
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "license_kind",
+			Bzl_load_location: "@rules_license//rules:license_kind.bzl",
+		},
+		CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs)
+}
+
 func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) {
 	// Nothing to do.
 }
@@ -51,13 +79,14 @@
 	module := &licenseKindModule{}
 
 	base := module.base()
-	module.AddProperties(&base.nameProperties, &module.properties)
+	module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
 
 	// The visibility property needs to be checked and parsed by the visibility module.
 	setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
 
 	initAndroidModuleBase(module)
 	InitDefaultableModule(module)
+	InitBazelModule(module)
 
 	return module
 }
diff --git a/android/module.go b/android/module.go
index 5908233..5d520f4 100644
--- a/android/module.go
+++ b/android/module.go
@@ -917,6 +917,8 @@
 	Name string
 	// Data mapped from: Required
 	Data bazel.LabelListAttribute
+
+	Tags bazel.StringListAttribute
 }
 
 // constraintAttributes represents Bazel attributes pertaining to build constraints,
@@ -1169,7 +1171,9 @@
 	mod := ctx.Module().base()
 	// Assert passed-in attributes include Name
 	if len(attrs.Name) == 0 {
-		ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
+		if ctx.ModuleType() != "package" {
+			ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
+		}
 	}
 
 	depsToLabelList := func(deps []string) bazel.LabelListAttribute {
diff --git a/android/namespace.go b/android/namespace.go
index fc7bc29..a3ff761 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -166,10 +166,10 @@
 	return namespace
 }
 
-// A NamelessModule can never be looked up by name.  It must still implement Name(), but the return
-// value doesn't have to be unique.
-type NamelessModule interface {
-	Nameless()
+// A NamespacelessModule can never be looked up by name.  It must still implement Name(), and the name
+// still has to be unique.
+type NamespacelessModule interface {
+	Namespaceless()
 }
 
 func (r *NameResolver) NewModule(ctx blueprint.NamespaceContext, moduleGroup blueprint.ModuleGroup, module blueprint.Module) (namespace blueprint.Namespace, errs []error) {
@@ -183,7 +183,7 @@
 		return nil, nil
 	}
 
-	if _, ok := module.(NamelessModule); ok {
+	if _, ok := module.(NamespacelessModule); ok {
 		return nil, nil
 	}
 
diff --git a/android/package.go b/android/package.go
index 878e4c4..2bf6521 100644
--- a/android/package.go
+++ b/android/package.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"android/soong/bazel"
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -37,12 +38,33 @@
 	Default_applicable_licenses []string
 }
 
+type bazelPackageAttributes struct {
+	Default_visibility          []string
+	Default_applicable_licenses bazel.LabelListAttribute
+}
+
 type packageModule struct {
 	ModuleBase
+	BazelModuleBase
 
 	properties packageProperties
 }
 
+var _ Bazelable = &packageModule{}
+
+func (p *packageModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class: "package",
+		},
+		CommonAttributes{},
+		&bazelPackageAttributes{
+			Default_applicable_licenses: bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, p.properties.Default_applicable_licenses)),
+			// FIXME(asmundak): once b/221436821 is resolved
+			Default_visibility: []string{"//visibility:public"},
+		})
+}
+
 func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) {
 	// Nothing to do.
 }
@@ -59,7 +81,7 @@
 func PackageFactory() Module {
 	module := &packageModule{}
 
-	module.AddProperties(&module.properties)
+	module.AddProperties(&module.properties, &module.commonProperties.BazelConversionStatus)
 
 	// The name is the relative path from build root to the directory containing this
 	// module. Set that name at the earliest possible moment that information is available
@@ -76,5 +98,7 @@
 	// its checking and parsing phases so make it the primary licenses property.
 	setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses)
 
+	InitBazelModule(module)
+
 	return module
 }
diff --git a/android/proto.go b/android/proto.go
index 25cecf4..3cac9a1 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -155,14 +155,16 @@
 
 // Bp2buildProtoInfo contains information necessary to pass on to language specific conversion.
 type Bp2buildProtoInfo struct {
-	Type *string
-	Name string
+	Type       *string
+	Name       string
+	Proto_libs bazel.LabelList
 }
 
-type protoAttrs struct {
+type ProtoAttrs struct {
 	Srcs                bazel.LabelListAttribute
 	Strip_import_prefix *string
 	Deps                bazel.LabelListAttribute
+	Tags                []string
 }
 
 // For each package in the include_dirs property a proto_library target should
@@ -179,44 +181,71 @@
 		return info, false
 	}
 
-	info.Name = m.Name() + "_proto"
-	attrs := protoAttrs{
-		Srcs: srcs,
-	}
+	var protoLibraries bazel.LabelList
+	var directProtoSrcs bazel.LabelList
 
-	for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
-		for _, rawProps := range configToProps {
-			var props *ProtoProperties
-			var ok bool
-			if props, ok = rawProps.(*ProtoProperties); !ok {
-				ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
-			}
-			if axis == bazel.NoConfigAxis {
-				info.Type = props.Proto.Type
-
-				if !proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
-					// an empty string indicates to strips the package path
-					path := ""
-					attrs.Strip_import_prefix = &path
-				}
-
-				for _, dir := range props.Proto.Include_dirs {
-					if dep, ok := includeDirsToProtoDeps[dir]; ok {
-						attrs.Deps.Add(bazel.MakeLabelAttribute(dep))
-					} else {
-						ctx.PropertyErrorf("Could not find the proto_library target for include dir", dir)
-					}
-				}
-			} else if props.Proto.Type != info.Type && props.Proto.Type != nil {
-				ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
-			}
+	// For filegroups that should be converted to proto_library just collect the
+	// labels of converted proto_library targets.
+	for _, protoSrc := range srcs.Value.Includes {
+		src := protoSrc.OriginalModuleName
+		if fg, ok := ToFileGroupAsLibrary(ctx, src); ok &&
+			fg.ShouldConvertToProtoLibrary(ctx) {
+			protoLibraries.Add(&bazel.Label{
+				Label: fg.GetProtoLibraryLabel(ctx),
+			})
+		} else {
+			directProtoSrcs.Add(&protoSrc)
 		}
 	}
 
-	ctx.CreateBazelTargetModule(
-		bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
-		CommonAttributes{Name: info.Name},
-		&attrs)
+	info.Name = m.Name() + "_proto"
+
+	if len(directProtoSrcs.Includes) > 0 {
+		attrs := ProtoAttrs{
+			Srcs: bazel.MakeLabelListAttribute(directProtoSrcs),
+		}
+		attrs.Deps.Append(bazel.MakeLabelListAttribute(protoLibraries))
+
+		for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
+			for _, rawProps := range configToProps {
+				var props *ProtoProperties
+				var ok bool
+				if props, ok = rawProps.(*ProtoProperties); !ok {
+					ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
+				}
+				if axis == bazel.NoConfigAxis {
+					info.Type = props.Proto.Type
+
+					if !proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
+						// an empty string indicates to strips the package path
+						path := ""
+						attrs.Strip_import_prefix = &path
+					}
+
+					for _, dir := range props.Proto.Include_dirs {
+						if dep, ok := includeDirsToProtoDeps[dir]; ok {
+							attrs.Deps.Add(bazel.MakeLabelAttribute(dep))
+						} else {
+							ctx.PropertyErrorf("Could not find the proto_library target for include dir", dir)
+						}
+					}
+				} else if props.Proto.Type != info.Type && props.Proto.Type != nil {
+					ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
+				}
+			}
+		}
+
+		ctx.CreateBazelTargetModule(
+			bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
+			CommonAttributes{Name: info.Name},
+			&attrs)
+
+		protoLibraries.Add(&bazel.Label{
+			Label: ":" + info.Name,
+		})
+	}
+
+	info.Proto_libs = protoLibraries
 
 	return info, true
 }
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index cd36ae0..c0f4523 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -172,7 +172,7 @@
 		"soong_config_module_type_import_" + fmt.Sprintf("%p", m)
 }
 
-func (*soongConfigModuleTypeImport) Nameless()                                 {}
+func (*soongConfigModuleTypeImport) Namespaceless()                            {}
 func (*soongConfigModuleTypeImport) GenerateAndroidBuildActions(ModuleContext) {}
 
 // Create dummy modules for soong_config_module_type and soong_config_*_variable
@@ -280,9 +280,9 @@
 }
 
 func (m *soongConfigModuleTypeModule) Name() string {
-	return m.properties.Name
+	return m.properties.Name + fmt.Sprintf("%p", m)
 }
-func (*soongConfigModuleTypeModule) Nameless()                                     {}
+func (*soongConfigModuleTypeModule) Namespaceless()                                {}
 func (*soongConfigModuleTypeModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
 
 type soongConfigStringVariableDummyModule struct {
@@ -315,15 +315,15 @@
 }
 
 func (m *soongConfigStringVariableDummyModule) Name() string {
-	return m.properties.Name
+	return m.properties.Name + fmt.Sprintf("%p", m)
 }
-func (*soongConfigStringVariableDummyModule) Nameless()                                     {}
+func (*soongConfigStringVariableDummyModule) Namespaceless()                                {}
 func (*soongConfigStringVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
 
 func (m *soongConfigBoolVariableDummyModule) Name() string {
-	return m.properties.Name
+	return m.properties.Name + fmt.Sprintf("%p", m)
 }
-func (*soongConfigBoolVariableDummyModule) Nameless()                                     {}
+func (*soongConfigBoolVariableDummyModule) Namespaceless()                                {}
 func (*soongConfigBoolVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
 
 // importModuleTypes registers the module factories for a list of module types defined
diff --git a/apex/apex.go b/apex/apex.go
index 949809a..2e54e7e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -3054,36 +3054,6 @@
 	//
 	// Module separator
 	//
-	m["com.android.bluetooth"] = []string{
-		"bluetooth-protos-lite",
-		"internal_include_headers",
-		"libaudio-a2dp-hw-utils",
-		"libaudio-hearing-aid-hw-utils",
-		"libbluetooth",
-		"libbluetooth-types",
-		"libbluetooth-types-header",
-		"libbluetooth_gd",
-		"libbluetooth_headers",
-		"libbluetooth_jni",
-		"libbt-audio-hal-interface",
-		"libbt-bta",
-		"libbt-common",
-		"libbt-hci",
-		"libbt-platform-protos-lite",
-		"libbt-protos-lite",
-		"libbt-sbc-decoder",
-		"libbt-sbc-encoder",
-		"libbt-stack",
-		"libbt-utils",
-		"libbtcore",
-		"libbtdevice",
-		"libbte",
-		"libbtif",
-		"libchrome",
-	}
-	//
-	// Module separator
-	//
 	m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"}
 	//
 	// Module separator
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 7ff202b..b6bbd67 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -69,6 +69,9 @@
 
 	AndroidAndInApex  = "android-in_apex"
 	AndroidAndNonApex = "android-non_apex"
+
+	InApex  = "in_apex"
+	NonApex = "non_apex"
 )
 
 func PowerSetWithoutEmptySet[T any](items []T) [][]T {
@@ -198,6 +201,12 @@
 		AndroidAndNonApex:          "//build/bazel/rules/apex:android-non_apex",
 		ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
 	}
+
+	inApexMap = map[string]string{
+		InApex:                     "//build/bazel/rules/apex:in_apex",
+		NonApex:                    "//build/bazel/rules/apex:non_apex",
+		ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
+	}
 )
 
 // basic configuration types
@@ -210,6 +219,7 @@
 	osArch
 	productVariables
 	osAndInApex
+	inApex
 )
 
 func osArchString(os string, arch string) string {
@@ -224,6 +234,7 @@
 		osArch:           "arch_os",
 		productVariables: "product_variables",
 		osAndInApex:      "os_in_apex",
+		inApex:           "in_apex",
 	}[ct]
 }
 
@@ -251,6 +262,10 @@
 		if _, ok := osAndInApexMap[config]; !ok {
 			panic(fmt.Errorf("Unknown os+in_apex config: %s", config))
 		}
+	case inApex:
+		if _, ok := inApexMap[config]; !ok {
+			panic(fmt.Errorf("Unknown in_apex config: %s", config))
+		}
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
 	}
@@ -276,6 +291,8 @@
 		return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
 	case osAndInApex:
 		return osAndInApexMap[config]
+	case inApex:
+		return inApexMap[config]
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
 	}
@@ -292,6 +309,8 @@
 	OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
 	// An axis for os+in_apex-specific configurations
 	OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
+	// An axis for in_apex-specific configurations
+	InApexAxis = ConfigurationAxis{configurationType: inApex}
 )
 
 // ProductVariableConfigurationAxis returns an axis for the given product variable
diff --git a/bazel/properties.go b/bazel/properties.go
index 11f6247..c329e41 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -720,7 +720,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		lla.Value = list
-	case arch, os, osArch, productVariables, osAndInApex:
+	case arch, os, osArch, productVariables, osAndInApex, inApex:
 		if lla.ConfigurableValues == nil {
 			lla.ConfigurableValues = make(configurableLabelLists)
 		}
@@ -736,7 +736,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		return lla.Value
-	case arch, os, osArch, productVariables, osAndInApex:
+	case arch, os, osArch, productVariables, osAndInApex, inApex:
 		return lla.ConfigurableValues[axis][config]
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 3d9fc5a..7c9af1a 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -63,8 +63,11 @@
         "java_library_host_conversion_test.go",
         "java_plugin_conversion_test.go",
         "java_proto_conversion_test.go",
+        "license_conversion_test.go",
+        "license_kind_conversion_test.go",
         "linker_config_conversion_test.go",
         "ndk_headers_conversion_test.go",
+        "package_conversion_test.go",
         "performance_test.go",
         "prebuilt_etc_conversion_test.go",
         "python_binary_conversion_test.go",
diff --git a/bp2build/androidbp_to_build_templates.go b/bp2build/androidbp_to_build_templates.go
index 5fed4fa..9b21c32 100644
--- a/bp2build/androidbp_to_build_templates.go
+++ b/bp2build/androidbp_to_build_templates.go
@@ -23,7 +23,7 @@
 
 	// A macro call in the BUILD file representing a Soong module, with space
 	// for expanding more attributes.
-	soongModuleTarget = `soong_module(
+	soongModuleTargetTemplate = `soong_module(
     name = "%s",
     soong_module_name = "%s",
     soong_module_type = "%s",
@@ -31,10 +31,13 @@
     soong_module_deps = %s,
 %s)`
 
-	bazelTarget = `%s(
+	ruleTargetTemplate = `%s(
     name = "%s",
 %s)`
 
+	unnamedRuleTargetTemplate = `%s(
+%s)`
+
 	// A simple provider to mark and differentiate Soong module rule shims from
 	// regular Bazel rules. Every Soong module rule shim returns a
 	// SoongModuleInfo provider, and can only depend on rules returning
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index ca8185e..ee162b2 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -64,7 +64,16 @@
 // BazelTargets is a typedef for a slice of BazelTarget objects.
 type BazelTargets []BazelTarget
 
-// sort a list of BazelTargets in-place by name
+func (targets BazelTargets) packageRule() *BazelTarget {
+	for _, target := range targets {
+		if target.ruleClass == "package" {
+			return &target
+		}
+	}
+	return nil
+}
+
+// sort a list of BazelTargets in-place, by name, and by generated/handcrafted types.
 func (targets BazelTargets) sort() {
 	sort.Slice(targets, func(i, j int) bool {
 		return targets[i].name < targets[j].name
@@ -77,7 +86,9 @@
 func (targets BazelTargets) String() string {
 	var res string
 	for i, target := range targets {
-		res += target.content
+		if target.ruleClass != "package" {
+			res += target.content
+		}
 		if i != len(targets)-1 {
 			res += "\n\n"
 		}
@@ -391,18 +402,19 @@
 	// Return the Bazel target with rule class and attributes, ready to be
 	// code-generated.
 	attributes := propsToAttributes(props.Attrs)
+	var content string
 	targetName := m.TargetName()
+	if targetName != "" {
+		content = fmt.Sprintf(ruleTargetTemplate, ruleClass, targetName, attributes)
+	} else {
+		content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes)
+	}
 	return BazelTarget{
 		name:            targetName,
 		packageName:     m.TargetPackage(),
 		ruleClass:       ruleClass,
 		bzlLoadLocation: bzlLoadLocation,
-		content: fmt.Sprintf(
-			bazelTarget,
-			ruleClass,
-			targetName,
-			attributes,
-		),
+		content:         content,
 	}, nil
 }
 
@@ -436,7 +448,7 @@
 	return BazelTarget{
 		name: targetName,
 		content: fmt.Sprintf(
-			soongModuleTarget,
+			soongModuleTargetTemplate,
 			targetName,
 			ctx.ModuleName(m),
 			canonicalizeModuleType(ctx.ModuleType(m)),
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 67d4a1c..1c9fba2 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -45,6 +45,7 @@
 
 type ccBinaryBp2buildTestCase struct {
 	description string
+	filesystem  map[string]string
 	blueprint   string
 	targets     []testBazelTarget
 }
@@ -79,6 +80,7 @@
 			ModuleTypeUnderTestFactory: cc.BinaryFactory,
 			Description:                description,
 			Blueprint:                  binaryReplacer.Replace(testCase.blueprint),
+			Filesystem:                 testCase.filesystem,
 		})
 	})
 }
@@ -94,6 +96,7 @@
 			ModuleTypeUnderTestFactory: cc.BinaryHostFactory,
 			Description:                description,
 			Blueprint:                  hostBinaryReplacer.Replace(testCase.blueprint),
+			Filesystem:                 testCase.filesystem,
 		})
 	})
 }
@@ -101,6 +104,9 @@
 func TestBasicCcBinary(t *testing.T) {
 	runCcBinaryTests(t, ccBinaryBp2buildTestCase{
 		description: "basic -- properties -> attrs with little/no transformation",
+		filesystem: map[string]string{
+			soongCcVersionLibBpPath: soongCcVersionLibBp,
+		},
 		blueprint: `
 {rule_name} {
     name: "foo",
@@ -146,9 +152,10 @@
         "keep_symbols_list": ["symbol"],
         "none": True,
     }`,
-				"sdk_version":     `"current"`,
-				"min_sdk_version": `"29"`,
-				"use_version_lib": `True`,
+				"sdk_version":        `"current"`,
+				"min_sdk_version":    `"29"`,
+				"use_version_lib":    `True`,
+				"whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
 			},
 			},
 		},
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 880ae75..f581706 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -27,7 +27,16 @@
 	soongCcLibraryPreamble = `
 cc_defaults {
     name: "linux_bionic_supported",
-}`
+}
+`
+
+	soongCcVersionLibBpPath = "build/soong/cc/libbuildversion/Android.bp"
+	soongCcVersionLibBp     = `
+cc_library_static {
+	name: "libbuildversion",
+	bazel_module: { bp2build_available: false },
+}
+`
 
 	soongCcProtoLibraries = `
 cc_library {
@@ -62,9 +71,10 @@
 		ModuleTypeUnderTest:        "cc_library",
 		ModuleTypeUnderTestFactory: cc.LibraryFactory,
 		Filesystem: map[string]string{
-			"android.cpp": "",
-			"bionic.cpp":  "",
-			"darwin.cpp":  "",
+			soongCcVersionLibBpPath: soongCcVersionLibBp,
+			"android.cpp":           "",
+			"bionic.cpp":            "",
+			"darwin.cpp":            "",
 			// Refer to cc.headerExts for the supported header extensions in Soong.
 			"header.h":         "",
 			"header.hh":        "",
@@ -143,9 +153,10 @@
         "//build/bazel/platforms/os:linux_bionic": ["bionic.cpp"],
         "//conditions:default": [],
     })`,
-			"sdk_version":     `"current"`,
-			"min_sdk_version": `"29"`,
-			"use_version_lib": `True`,
+			"sdk_version":                       `"current"`,
+			"min_sdk_version":                   `"29"`,
+			"use_version_lib":                   `True`,
+			"implementation_whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
 		}),
 	})
 }
@@ -1337,6 +1348,7 @@
 		"strip":                    true,
 		"inject_bssl_hash":         true,
 		"has_stubs":                true,
+		"use_version_lib":          true,
 	}
 
 	sharedAttrs := AttrNameToString{}
@@ -2078,7 +2090,8 @@
 				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 				"deps":                              `[":libprotobuf-cpp-lite"]`,
 			}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+				"dynamic_deps":                      `[":libprotobuf-cpp-lite"]`,
+				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 			}),
 		},
 	})
@@ -2104,7 +2117,8 @@
 				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 				"deps":                              `[":libprotobuf-cpp-lite"]`,
 			}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+				"dynamic_deps":                      `[":libprotobuf-cpp-lite"]`,
+				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 			}),
 		},
 	})
@@ -2129,7 +2143,8 @@
 				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 				"deps":                              `[":libprotobuf-cpp-lite"]`,
 			}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+				"dynamic_deps":                      `[":libprotobuf-cpp-lite"]`,
+				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 			}),
 		},
 	})
@@ -2156,7 +2171,8 @@
 				"implementation_whole_archive_deps": `[":foo_cc_proto"]`,
 				"deps":                              `[":libprotobuf-cpp-full"]`,
 			}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"dynamic_deps": `[":libprotobuf-cpp-full"]`,
+				"dynamic_deps":                      `[":libprotobuf-cpp-full"]`,
+				"implementation_whole_archive_deps": `[":foo_cc_proto"]`,
 			}),
 		},
 	})
@@ -2183,7 +2199,8 @@
 				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 				"deps":                              `[":libprotobuf-cpp-lite"]`,
 			}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+				"dynamic_deps":                      `[":libprotobuf-cpp-lite"]`,
+				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 			}),
 		},
 	})
@@ -2239,7 +2256,8 @@
 				"deps":                              `[":libprotobuf-cpp-lite"]`,
 				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 			}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+				"dynamic_deps":                      `[":libprotobuf-cpp-lite"]`,
+				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
 			}),
 		},
 	})
@@ -2261,6 +2279,134 @@
 	})
 }
 
+func TestCcLibraryConvertedProtoFilegroups(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: soongCcProtoPreamble + `
+filegroup {
+	name: "a_fg_proto",
+	srcs: ["a_fg.proto"],
+}
+
+cc_library {
+	name: "a",
+	srcs: [
+    ":a_fg_proto",
+    "a.proto",
+  ],
+	proto: {
+		export_proto_headers: true,
+	},
+	include_build_directory: false,
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("proto_library", "a_proto", AttrNameToString{
+				"deps": `[":a_fg_proto_bp2build_converted"]`,
+				"srcs": `["a.proto"]`,
+			}), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
+				"deps": `[
+        ":a_fg_proto_bp2build_converted",
+        ":a_proto",
+    ]`,
+			}), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
+				"deps":               `[":libprotobuf-cpp-lite"]`,
+				"whole_archive_deps": `[":a_cc_proto_lite"]`,
+			}), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
+				"whole_archive_deps": `[":a_cc_proto_lite"]`,
+			}), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
+				"srcs": `["a_fg.proto"]`,
+				"tags": `["manual"]`,
+			}), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
+				"srcs": `["a_fg.proto"]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryConvertedProtoFilegroupsNoProtoFiles(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: soongCcProtoPreamble + `
+filegroup {
+	name: "a_fg_proto",
+	srcs: ["a_fg.proto"],
+}
+
+cc_library {
+	name: "a",
+	srcs: [
+    ":a_fg_proto",
+  ],
+	proto: {
+		export_proto_headers: true,
+	},
+	include_build_directory: false,
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
+				"deps": `[":a_fg_proto_bp2build_converted"]`,
+			}), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
+				"deps":               `[":libprotobuf-cpp-lite"]`,
+				"whole_archive_deps": `[":a_cc_proto_lite"]`,
+			}), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
+				"whole_archive_deps": `[":a_cc_proto_lite"]`,
+			}), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
+				"srcs": `["a_fg.proto"]`,
+				"tags": `["manual"]`,
+			}), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
+				"srcs": `["a_fg.proto"]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryExternalConvertedProtoFilegroups(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Filesystem: map[string]string{
+			"path/to/A/Android.bp": `
+filegroup {
+	name: "a_fg_proto",
+	srcs: ["a_fg.proto"],
+}`,
+		},
+		Blueprint: soongCcProtoPreamble + `
+cc_library {
+	name: "a",
+	srcs: [
+    ":a_fg_proto",
+    "a.proto",
+  ],
+	proto: {
+		export_proto_headers: true,
+	},
+	include_build_directory: false,
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("proto_library", "a_proto", AttrNameToString{
+				"deps": `["//path/to/A:a_fg_proto_bp2build_converted"]`,
+				"srcs": `["a.proto"]`,
+			}), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
+				"deps": `[
+        "//path/to/A:a_fg_proto_bp2build_converted",
+        ":a_proto",
+    ]`,
+			}), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
+				"deps":               `[":libprotobuf-cpp-lite"]`,
+				"whole_archive_deps": `[":a_cc_proto_lite"]`,
+			}), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
+				"whole_archive_deps": `[":a_cc_proto_lite"]`,
+			}),
+		},
+	})
+}
+
 func TestCcLibraryProtoFilegroups(t *testing.T) {
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		ModuleTypeUnderTest:        "cc_library",
@@ -2556,6 +2702,40 @@
 	)
 }
 
+func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "stub target generation of the same lib across configs should not result in duplicates",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Filesystem: map[string]string{
+			"bar.map.txt": "",
+		},
+		Blueprint: `
+cc_library {
+	name: "barlib",
+	stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
+	bazel_module: { bp2build_available: false },
+}
+cc_library {
+	name: "foolib",
+	shared_libs: ["barlib"],
+	target: {
+		android: {
+			shared_libs: ["barlib"],
+		},
+	},
+	bazel_module: { bp2build_available: true },
+}`,
+		ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
+			"implementation_dynamic_deps": `select({
+        "//build/bazel/rules/apex:android-in_apex": [":barlib_stub_libs_current"],
+        "//conditions:default": [":barlib"],
+    })`,
+			"local_includes": `["."]`,
+		}),
+	})
+}
+
 func TestCcLibraryEscapeLdflags(t *testing.T) {
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		ModuleTypeUnderTest:        "cc_library",
@@ -2792,10 +2972,9 @@
 				"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
 				"local_includes":                    `["."]`,
 			}),
-			// TODO(b/239311679) Add implementation_whole_archive_deps to cc_library_shared
-			// for bp2build to be fully correct. This fallback is affecting proto as well.
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"local_includes": `["."]`,
+				"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+				"local_includes":                    `["."]`,
 			}),
 		},
 	})
@@ -2829,10 +3008,9 @@
 				"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
 				"local_includes":                    `["."]`,
 			}),
-			// TODO(b/239311679) Add implementation_whole_archive_deps to cc_library_shared
-			// for bp2build to be fully correct. This fallback is affecting proto as well.
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"local_includes": `["."]`,
+				"local_includes":                    `["."]`,
+				"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
 			}),
 		},
 	})
@@ -2871,3 +3049,86 @@
 		},
 	})
 }
+
+func TestCcLibraryWithTargetApex(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library with target.apex",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library {
+    name: "foo",
+	shared_libs: ["bar", "baz"],
+	static_libs: ["baz", "buh"],
+	target: {
+        apex: {
+            exclude_shared_libs: ["bar"],
+            exclude_static_libs: ["buh"],
+        }
+    }
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+        "//build/bazel/rules/apex:non_apex": [":buh__BP2BUILD__MISSING__DEP"],
+        "//conditions:default": [],
+    })`,
+				"implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+        "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+        "//build/bazel/rules/apex:non_apex": [":buh__BP2BUILD__MISSING__DEP"],
+        "//conditions:default": [],
+    })`,
+				"implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+        "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryWithTargetApexAndExportLibHeaders(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library with target.apex and export_shared|static_lib_headers",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+cc_library_static {
+    name: "foo",
+	shared_libs: ["bar", "baz"],
+    static_libs: ["abc"],
+    export_shared_lib_headers: ["baz"],
+    export_static_lib_headers: ["abc"],
+	target: {
+        apex: {
+            exclude_shared_libs: ["baz", "bar"],
+            exclude_static_libs: ["abc"],
+        }
+    }
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+				"implementation_dynamic_deps": `select({
+        "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
+        "//conditions:default": [],
+    })`,
+				"dynamic_deps": `select({
+        "//build/bazel/rules/apex:non_apex": [":baz__BP2BUILD__MISSING__DEP"],
+        "//conditions:default": [],
+    })`,
+				"deps": `select({
+        "//build/bazel/rules/apex:non_apex": [":abc__BP2BUILD__MISSING__DEP"],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 4d8e59b..6aa8ebe 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -454,6 +454,9 @@
 
 func TestCcLibrarySharedUseVersionLib(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Filesystem: map[string]string{
+			soongCcVersionLibBpPath: soongCcVersionLibBp,
+		},
 		Blueprint: soongCcProtoPreamble + `cc_library_shared {
         name: "foo",
         use_version_lib: true,
@@ -461,7 +464,8 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
-				"use_version_lib": "True",
+				"use_version_lib":                   "True",
+				"implementation_whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
 			}),
 		},
 	})
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 316fa3e..37722ed 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1485,14 +1485,37 @@
 
 func TestCcLibraryStaticUseVersionLib(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		Filesystem: map[string]string{
+			soongCcVersionLibBpPath: soongCcVersionLibBp,
+		},
 		Blueprint: soongCcProtoPreamble + `cc_library_static {
 	name: "foo",
 	use_version_lib: true,
+	static_libs: ["libbuildversion"],
 	include_build_directory: false,
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
-				"use_version_lib": "True",
+				"implementation_whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryStaticUseVersionLibHasDep(t *testing.T) {
+	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		Filesystem: map[string]string{
+			soongCcVersionLibBpPath: soongCcVersionLibBp,
+		},
+		Blueprint: soongCcProtoPreamble + `cc_library_static {
+	name: "foo",
+	use_version_lib: true,
+	whole_static_libs: ["libbuildversion"],
+	include_build_directory: false,
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+				"whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
 			}),
 		},
 	})
diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 9b7748f..8c2d30d 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -148,3 +148,27 @@
 		},
 	})
 }
+
+func TestCcTest_TestOptions_Tags(t *testing.T) {
+	runCcTestTestCase(t, ccTestBp2buildTestCase{
+		description: "cc test with test_options.tags converted to tags",
+		blueprint: `
+cc_test {
+    name: "mytest",
+    host_supported: true,
+    srcs: ["test.cpp"],
+    test_options: { tags: ["no-remote"] },
+}
+`,
+		targets: []testBazelTarget{
+			{"cc_test", "mytest", AttrNameToString{
+				"tags":           `["no-remote"]`,
+				"local_includes": `["."]`,
+				"srcs":           `["test.cpp"]`,
+				"gtest":          "True",
+				"isolated":       "True",
+			},
+			},
+		},
+	})
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 731b17e..b6190c6 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -96,10 +96,14 @@
 # This file was automatically generated by bp2build for the Bazel migration project.
 # Feel free to edit or test it, but do *not* check it into your version control system.
 `
-
-			// Hardcode the default visibility.
-			content += "package(default_visibility = [\"//visibility:public\"])\n"
 			content += targets.LoadStatements()
+			content += "\n\n"
+			// Get package rule from the handcrafted BUILD file, otherwise emit the default one.
+			prText := "package(default_visibility = [\"//visibility:public\"])\n"
+			if pr := targets.packageRule(); pr != nil {
+				prText = pr.content
+			}
+			content += prText
 		} else if mode == QueryView {
 			content = soongModuleLoad
 		}
@@ -160,7 +164,7 @@
 		// internal to Soong only, and these fields do not have PkgPath.
 		return true
 	}
-	// fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc
+	// fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc.
 	// but cannot be set in a .bp file
 	if proptools.HasTag(field, "blueprint", "mutated") {
 		return true
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index de09a17..e978fb3 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -15,10 +15,10 @@
 package bp2build
 
 import (
-	"android/soong/android"
 	"fmt"
-
 	"testing"
+
+	"android/soong/android"
 )
 
 func runFilegroupTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -121,3 +121,44 @@
     ]`}),
 		}})
 }
+
+func TestFilegroupWithProtoSrcs(t *testing.T) {
+	runFilegroupTestCase(t, Bp2buildTestCase{
+		Description: "filegroup with proto and non-proto srcs",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+filegroup {
+		name: "foo",
+		srcs: ["proto/foo.proto"],
+		path: "proto",
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("proto_library", "foo_bp2build_converted", AttrNameToString{
+				"srcs":                `["proto/foo.proto"]`,
+				"strip_import_prefix": `"proto"`,
+				"tags":                `["manual"]`}),
+			MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
+				"srcs": `["proto/foo.proto"]`}),
+		}})
+}
+
+func TestFilegroupWithProtoAndNonProtoSrcs(t *testing.T) {
+	runFilegroupTestCase(t, Bp2buildTestCase{
+		Description: "filegroup with proto and non-proto srcs",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+filegroup {
+    name: "foo",
+    srcs: [
+		"foo.proto",
+		"buf.cpp",
+	],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
+				"srcs": `[
+        "foo.proto",
+        "buf.cpp",
+    ]`}),
+		}})
+}
diff --git a/bp2build/license_conversion_test.go b/bp2build/license_conversion_test.go
new file mode 100644
index 0000000..ea6b27a
--- /dev/null
+++ b/bp2build/license_conversion_test.go
@@ -0,0 +1,81 @@
+// Copyright 2022 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"
+	"testing"
+)
+
+func registerLicenseModuleTypes(_ android.RegistrationContext) {}
+
+func TestLicenseBp2Build(t *testing.T) {
+	tests := []struct {
+		description string
+		module      string
+		expected    ExpectedRuleTarget
+	}{
+		{
+			description: "license kind and text notice",
+			module: `
+license {
+    name: "my_license",
+    license_kinds: [ "SPDX-license-identifier-Apache-2.0"],
+    license_text: [ "NOTICE"],
+}`,
+			expected: ExpectedRuleTarget{
+				"android_license",
+				"my_license",
+				AttrNameToString{
+					"license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
+					"license_text":  `"NOTICE"`,
+				},
+				android.HostAndDeviceDefault,
+			},
+		},
+		{
+			description: "visibility, package_name, copyright_notice",
+			module: `
+license {
+	name: "my_license",
+    package_name: "my_package",
+    visibility: [":__subpackages__"],
+    copyright_notice: "Copyright © 2022",
+}`,
+			expected: ExpectedRuleTarget{
+				"android_license",
+				"my_license",
+				AttrNameToString{
+					"copyright_notice": `"Copyright © 2022"`,
+					"package_name":     `"my_package"`,
+					"visibility":       `[":__subpackages__"]`,
+				},
+				android.HostAndDeviceDefault,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		RunBp2BuildTestCase(t,
+			registerLicenseModuleTypes,
+			Bp2buildTestCase{
+				Description:                test.description,
+				ModuleTypeUnderTest:        "license",
+				ModuleTypeUnderTestFactory: android.LicenseFactory,
+				Blueprint:                  test.module,
+				ExpectedBazelTargets:       []string{test.expected.String()},
+			})
+	}
+}
diff --git a/bp2build/license_kind_conversion_test.go b/bp2build/license_kind_conversion_test.go
new file mode 100644
index 0000000..eda116c
--- /dev/null
+++ b/bp2build/license_kind_conversion_test.go
@@ -0,0 +1,69 @@
+// Copyright 2022 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"
+	"testing"
+)
+
+func registerLicenseKindModuleTypes(_ android.RegistrationContext) {}
+
+func TestLicenseKindBp2Build(t *testing.T) {
+	tests := []struct {
+		description string
+		module      string
+		expected    ExpectedRuleTarget
+	}{
+		{
+			description: "license_kind",
+			module: `
+license_kind {
+    name: "my_license",
+    conditions: [
+        "by_exception_only",
+        "not_allowed",
+    ],
+    url: "https://spdx.org/licenses/0BSD",
+    visibility: ["//visibility:public"],
+}`,
+			expected: ExpectedRuleTarget{
+				"license_kind",
+				"my_license",
+				AttrNameToString{
+					"conditions": `[
+        "by_exception_only",
+        "not_allowed",
+    ]`,
+					"url":        `"https://spdx.org/licenses/0BSD"`,
+					"visibility": `["//visibility:public"]`,
+				},
+				android.HostAndDeviceDefault,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		RunBp2BuildTestCase(t,
+			registerLicenseKindModuleTypes,
+			Bp2buildTestCase{
+				Description:                test.description,
+				ModuleTypeUnderTest:        "license_kind",
+				ModuleTypeUnderTestFactory: android.LicenseKindFactory,
+				Blueprint:                  test.module,
+				ExpectedBazelTargets:       []string{test.expected.String()},
+			})
+	}
+}
diff --git a/bp2build/package_conversion_test.go b/bp2build/package_conversion_test.go
new file mode 100644
index 0000000..3704b2d
--- /dev/null
+++ b/bp2build/package_conversion_test.go
@@ -0,0 +1,85 @@
+// Copyright 2022 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/genrule"
+	"testing"
+)
+
+func registerDependentModules(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("license", android.LicenseFactory)
+	ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
+}
+
+func TestPackage(t *testing.T) {
+	tests := []struct {
+		description string
+		modules     string
+		expected    []ExpectedRuleTarget
+	}{
+		{
+			description: "with default applicable licenses",
+			modules: `
+license {
+  name: "my_license",
+  visibility: [":__subpackages__"],
+  license_kinds: ["SPDX-license-identifier-Apache-2.0"],
+  license_text: ["NOTICE"],
+}
+
+package {
+  default_applicable_licenses: ["my_license"],
+}
+`,
+			expected: []ExpectedRuleTarget{
+				{
+					"package",
+					"",
+					AttrNameToString{
+						"default_applicable_licenses": `[":my_license"]`,
+						"default_visibility":          `["//visibility:public"]`,
+					},
+					android.HostAndDeviceDefault,
+				},
+				{
+					"android_license",
+					"my_license",
+					AttrNameToString{
+						"license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
+						"license_text":  `"NOTICE"`,
+						"visibility":    `[":__subpackages__"]`,
+					},
+					android.HostAndDeviceDefault,
+				},
+			},
+		},
+	}
+	for _, test := range tests {
+		expected := make([]string, 0, len(test.expected))
+		for _, e := range test.expected {
+			expected = append(expected, e.String())
+		}
+		RunBp2BuildTestCase(t, registerDependentModules,
+			Bp2buildTestCase{
+				Description:                test.description,
+				ModuleTypeUnderTest:        "package",
+				ModuleTypeUnderTestFactory: android.PackageFactory,
+				Blueprint:                  test.modules,
+				ExpectedBazelTargets:       expected,
+			})
+	}
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index ac1268c..edc5c4a 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -141,7 +141,7 @@
 		android.FailIfErrored(t, errs)
 	}
 	if actualCount, expectedCount := len(bazelTargets), len(tc.ExpectedBazelTargets); actualCount != expectedCount {
-		t.Errorf("%s: Expected %d bazel target (%s), got `%d`` (%s)",
+		t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
 			tc.Description, expectedCount, tc.ExpectedBazelTargets, actualCount, bazelTargets)
 	} else {
 		for i, target := range bazelTargets {
@@ -429,7 +429,9 @@
 	}
 
 	attrStrings := make([]string, 0, len(attrs)+1)
-	attrStrings = append(attrStrings, fmt.Sprintf(`    name = "%s",`, name))
+	if name != "" {
+		attrStrings = append(attrStrings, fmt.Sprintf(`    name = "%s",`, name))
+	}
 	for _, k := range android.SortedStringKeys(attrs) {
 		attrStrings = append(attrStrings, fmt.Sprintf("    %s = %s,", k, attrs[k]))
 	}
@@ -450,3 +452,14 @@
 func MakeBazelTarget(typ, name string, attrs AttrNameToString) string {
 	return makeBazelTargetHostOrDevice(typ, name, attrs, android.DeviceSupported)
 }
+
+type ExpectedRuleTarget struct {
+	Rule  string
+	Name  string
+	Attrs AttrNameToString
+	Hod   android.HostOrDeviceSupported
+}
+
+func (ebr ExpectedRuleTarget) String() string {
+	return makeBazelTargetHostOrDevice(ebr.Rule, ebr.Name, ebr.Attrs, ebr.Hod)
+}
diff --git a/cc/Android.bp b/cc/Android.bp
index 2963c77..91a3fb0 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -45,7 +45,6 @@
         "snapshot_utils.go",
         "stl.go",
         "strip.go",
-        "sysprop.go",
         "tidy.go",
         "util.go",
         "vendor_snapshot.go",
@@ -99,6 +98,7 @@
         "library_headers_test.go",
         "library_stub_test.go",
         "library_test.go",
+        "lto_test.go",
         "ndk_test.go",
         "object_test.go",
         "prebuilt_test.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index e001d24..95ac598 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -79,10 +79,10 @@
 			if !exists || !android.IsFilegroup(otherModuleCtx, m) {
 				return labelStr, false
 			}
-			// If the filegroup is already converted to aidl_library, skip creating
-			// _c_srcs, _as_srcs, _cpp_srcs filegroups
-			fg, _ := m.(android.Bp2buildAidlLibrary)
-			if fg.ShouldConvertToAidlLibrary(ctx) {
+			// If the filegroup is already converted to aidl_library or proto_library,
+			// skip creating _c_srcs, _as_srcs, _cpp_srcs filegroups
+			fg, _ := m.(android.FileGroupAsLibrary)
+			if fg.ShouldConvertToAidlLibrary(ctx) || fg.ShouldConvertToProtoLibrary(ctx) {
 				return labelStr, false
 			}
 			return labelStr + suffix, true
@@ -506,19 +506,6 @@
 	return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs
 }
 
-// Given a name in srcs prop, check to see if the name references a filegroup
-// and the filegroup is converted to aidl_library
-func isConvertedToAidlLibrary(ctx android.BazelConversionPathContext, name string) bool {
-	if module, ok := ctx.ModuleFromName(name); ok {
-		if android.IsFilegroup(ctx, module) {
-			if fg, ok := module.(android.Bp2buildAidlLibrary); ok {
-				return fg.ShouldConvertToAidlLibrary(ctx)
-			}
-		}
-	}
-	return false
-}
-
 func bp2buildStdVal(std *string, prefix string, useGnu bool) *string {
 	defaultVal := prefix + "_std_default"
 	// If c{,pp}std properties are not specified, don't generate them in the BUILD file.
@@ -759,78 +746,57 @@
 	}
 }
 
-func bp2buildAidlLibraries(
-	ctx android.Bp2buildMutatorContext,
-	m *Module,
-	aidlSrcs bazel.LabelListAttribute,
-) bazel.LabelList {
-	var aidlLibraries bazel.LabelList
-	var directAidlSrcs bazel.LabelList
-
-	// Make a list of labels that correspond to filegroups that are already converted to aidl_library
-	for _, aidlSrc := range aidlSrcs.Value.Includes {
-		src := aidlSrc.OriginalModuleName
-		if isConvertedToAidlLibrary(ctx, src) {
-			module, _ := ctx.ModuleFromName(src)
-			fg, _ := module.(android.Bp2buildAidlLibrary)
-			aidlLibraries.Add(&bazel.Label{
-				Label: fg.GetAidlLibraryLabel(ctx),
-			})
-		} else {
-			directAidlSrcs.Add(&aidlSrc)
-		}
-	}
-
-	if len(directAidlSrcs.Includes) > 0 {
-		aidlLibraryLabel := m.Name() + "_aidl_library"
-		ctx.CreateBazelTargetModule(
-			bazel.BazelTargetModuleProperties{
-				Rule_class:        "aidl_library",
-				Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
-			},
-			android.CommonAttributes{Name: aidlLibraryLabel},
-			&aidlLibraryAttributes{
-				Srcs: bazel.MakeLabelListAttribute(directAidlSrcs),
-			},
-		)
-		aidlLibraries.Add(&bazel.Label{
-			Label: ":" + aidlLibraryLabel,
-		})
-	}
-	return aidlLibraries
-}
-
 func bp2buildCcAidlLibrary(
 	ctx android.Bp2buildMutatorContext,
 	m *Module,
-	aidlSrcs bazel.LabelListAttribute,
+	aidlLabelList bazel.LabelListAttribute,
 ) *bazel.LabelAttribute {
-	suffix := "_cc_aidl_library"
-	ccAidlLibrarylabel := m.Name() + suffix
+	if !aidlLabelList.IsEmpty() {
+		aidlLibs, aidlSrcs := aidlLabelList.Partition(func(src bazel.Label) bool {
+			if fg, ok := android.ToFileGroupAsLibrary(ctx, src.OriginalModuleName); ok &&
+				fg.ShouldConvertToAidlLibrary(ctx) {
+				return true
+			}
+			return false
+		})
 
-	aidlLibraries := bp2buildAidlLibraries(ctx, m, aidlSrcs)
+		if !aidlSrcs.IsEmpty() {
+			aidlLibName := m.Name() + "_aidl_library"
+			ctx.CreateBazelTargetModule(
+				bazel.BazelTargetModuleProperties{
+					Rule_class:        "aidl_library",
+					Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+				},
+				android.CommonAttributes{Name: aidlLibName},
+				&aidlLibraryAttributes{
+					Srcs: aidlSrcs,
+				},
+			)
+			aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
+		}
 
-	if aidlLibraries.IsEmpty() {
-		return nil
+		if !aidlLibs.IsEmpty() {
+			ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
+			ctx.CreateBazelTargetModule(
+				bazel.BazelTargetModuleProperties{
+					Rule_class:        "cc_aidl_library",
+					Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
+				},
+				android.CommonAttributes{Name: ccAidlLibrarylabel},
+				&ccAidlLibraryAttributes{
+					Deps: aidlLibs,
+				},
+			)
+			label := &bazel.LabelAttribute{
+				Value: &bazel.Label{
+					Label: ":" + ccAidlLibrarylabel,
+				},
+			}
+			return label
+		}
 	}
 
-	ctx.CreateBazelTargetModule(
-		bazel.BazelTargetModuleProperties{
-			Rule_class:        "cc_aidl_library",
-			Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
-		},
-		android.CommonAttributes{Name: ccAidlLibrarylabel},
-		&ccAidlLibraryAttributes{
-			Deps: bazel.MakeLabelListAttribute(aidlLibraries),
-		},
-	)
-
-	label := &bazel.LabelAttribute{
-		Value: &bazel.Label{
-			Label: ":" + ccAidlLibrarylabel,
-		},
-	}
-	return label
+	return nil
 }
 
 func bp2BuildParseSdkAttributes(module *Module) sdkAttributes {
@@ -872,19 +838,77 @@
 
 var (
 	soongSystemSharedLibs = []string{"libc", "libm", "libdl"}
+	versionLib            = "libbuildversion"
 )
 
+// resolveTargetApex re-adds the shared and static libs in target.apex.exclude_shared|static_libs props to non-apex variant
+// since all libs are already excluded by default
+func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPathContext, isBinary bool, props *BaseLinkerProperties) {
+	sharedLibsForNonApex := maybePartitionExportedAndImplementationsDeps(
+		ctx,
+		true,
+		props.Target.Apex.Exclude_shared_libs,
+		props.Export_shared_lib_headers,
+		bazelLabelForSharedDeps,
+	)
+	dynamicDeps := la.dynamicDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+	implDynamicDeps := la.implementationDynamicDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+	(&dynamicDeps).Append(sharedLibsForNonApex.export)
+	(&implDynamicDeps).Append(sharedLibsForNonApex.implementation)
+	la.dynamicDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, dynamicDeps)
+	la.implementationDynamicDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, implDynamicDeps)
+
+	staticLibsForNonApex := maybePartitionExportedAndImplementationsDeps(
+		ctx,
+		!isBinary,
+		props.Target.Apex.Exclude_static_libs,
+		props.Export_static_lib_headers,
+		bazelLabelForSharedDeps,
+	)
+	deps := la.deps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+	implDeps := la.implementationDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+	(&deps).Append(staticLibsForNonApex.export)
+	(&implDeps).Append(staticLibsForNonApex.implementation)
+	la.deps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, deps)
+	la.implementationDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, implDeps)
+}
+
 func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
 	// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
 	var axisFeatures []string
 
 	wholeStaticLibs := android.FirstUniqueStrings(props.Whole_static_libs)
-	la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs))
+	staticLibs := android.FirstUniqueStrings(android.RemoveListFromList(props.Static_libs, wholeStaticLibs))
+	if axis == bazel.NoConfigAxis {
+		la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib)
+		if proptools.Bool(props.Use_version_lib) {
+			versionLibAlreadyInDeps := android.InList(versionLib, wholeStaticLibs)
+			// remove from static libs so there is no duplicate dependency
+			_, staticLibs = android.RemoveFromList(versionLib, staticLibs)
+			// only add the dep if it is not in progress
+			if !versionLibAlreadyInDeps {
+				if isBinary {
+					wholeStaticLibs = append(wholeStaticLibs, versionLib)
+				} else {
+					la.implementationWholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, []string{versionLib}, props.Exclude_static_libs))
+				}
+			}
+		}
+	}
+
 	// Excludes to parallel Soong:
 	// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
-	staticLibs := android.FirstUniqueStrings(android.RemoveListFromList(props.Static_libs, wholeStaticLibs))
+	la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs))
 
-	staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, staticLibs, props.Exclude_static_libs, props.Export_static_lib_headers, bazelLabelForStaticDepsExcludes)
+	staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(
+		ctx,
+		!isBinary,
+		staticLibs,
+		// Exclude static libs in Exclude_static_libs and Target.Apex.Exclude_static_libs props
+		append(props.Exclude_static_libs, props.Target.Apex.Exclude_static_libs...),
+		props.Export_static_lib_headers,
+		bazelLabelForStaticDepsExcludes,
+	)
 
 	headerLibs := android.FirstUniqueStrings(props.Header_libs)
 	hDeps := maybePartitionExportedAndImplementationsDeps(ctx, !isBinary, headerLibs, props.Export_header_lib_headers, bazelLabelForHeaderDeps)
@@ -916,9 +940,19 @@
 		la.usedSystemDynamicDepAsDynamicDep[el] = true
 	}
 
-	sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, props.Exclude_shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
+	sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(
+		ctx,
+		!isBinary,
+		sharedLibs,
+		// Exclude shared libs in Exclude_shared_libs and Target.Apex.Exclude_shared_libs props
+		append(props.Exclude_shared_libs, props.Target.Apex.Exclude_shared_libs...),
+		props.Export_shared_lib_headers,
+		bazelLabelForSharedDepsExcludes,
+	)
 	la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
 	la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
+	la.resolveTargetApexProp(ctx, isBinary, props)
+
 	if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) {
 		// If a dependency in la.implementationDynamicDeps has stubs, its stub variant should be
 		// used when the dependency is linked in a APEX. The dependencies in NoConfigAxis and
@@ -947,14 +981,14 @@
 				(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
 				(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
 				(&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, inApexSelectValue)
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, nonApexSelectValue)
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, defaultSelectValue)
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue))
 			} else if config == bazel.OsAndroid {
 				(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
 				(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, inApexSelectValue)
-				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, nonApexSelectValue)
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
 			}
 		}
 	}
@@ -990,10 +1024,6 @@
 	la.linkopts.SetSelectValue(axis, config, parseCommandLineFlags(linkerFlags, false, filterOutClangUnknownCflags))
 	la.useLibcrt.SetSelectValue(axis, config, props.libCrt())
 
-	if axis == bazel.NoConfigAxis {
-		la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib)
-	}
-
 	// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
 	if props.crt() != nil {
 		if axis == bazel.NoConfigAxis {
diff --git a/cc/cc.go b/cc/cc.go
index 3129160..d42ab6d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -51,7 +51,6 @@
 		ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("version", versionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
-		ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
 	})
 
 	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -2392,18 +2391,8 @@
 		}
 	}
 
-	// sysprop_library has to support both C++ and Java. So sysprop_library internally creates one
-	// C++ implementation library and one Java implementation library. When a module links against
-	// sysprop_library, the C++ implementation library has to be linked. syspropImplLibraries is a
-	// map from sysprop_library to implementation library; it will be used in whole_static_libs,
-	// static_libs, and shared_libs.
-	syspropImplLibraries := syspropImplLibraries(actx.Config())
-
 	for _, lib := range deps.WholeStaticLibs {
 		depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true}
-		if impl, ok := syspropImplLibraries[lib]; ok {
-			lib = impl
-		}
 
 		lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
 
@@ -2421,10 +2410,6 @@
 			depTag.excludeInApex = true
 		}
 
-		if impl, ok := syspropImplLibraries[lib]; ok {
-			lib = impl
-		}
-
 		lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
 
 		actx.AddVariationDependencies([]blueprint.Variation{
@@ -2454,10 +2439,6 @@
 			depTag.excludeInApex = true
 		}
 
-		if impl, ok := syspropImplLibraries[lib]; ok {
-			lib = impl
-		}
-
 		name, version := StubsLibNameAndVersion(lib)
 		sharedLibNames = append(sharedLibNames, name)
 
diff --git a/cc/config/global.go b/cc/config/global.go
index f920471..a7701b9 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -316,9 +316,6 @@
 		"device/",
 		"vendor/",
 	}
-
-	// Directories with warnings from Android.mk files.
-	WarningAllowedOldProjects = []string{}
 )
 
 // BazelCcToolchainVars generates bzl file content containing variables for
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 1b126de..07b95e1 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -109,7 +109,7 @@
 	}, "-l")
 
 	muslCrtBeginStaticBinary, muslCrtEndStaticBinary   = []string{"libc_musl_crtbegin_static"}, []string{"libc_musl_crtend"}
-	muslCrtBeginSharedBinary, muslCrtEndSharedBinary   = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}, []string{"libc_musl_crtend"}
+	muslCrtBeginSharedBinary, muslCrtEndSharedBinary   = []string{"libc_musl_crtbegin_dynamic"}, []string{"libc_musl_crtend"}
 	muslCrtBeginSharedLibrary, muslCrtEndSharedLibrary = []string{"libc_musl_crtbegin_so"}, []string{"libc_musl_crtend_so"}
 
 	muslDefaultSharedLibraries = []string{"libc_musl"}
diff --git a/cc/library.go b/cc/library.go
index 8804bbb..a8653a0 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -339,14 +339,15 @@
 		Copts:   *compilerAttrs.copts.Clone().Append(sharedAttrs.Copts),
 		Hdrs:    *compilerAttrs.hdrs.Clone().Append(sharedAttrs.Hdrs),
 
-		Deps:                        *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps),
-		Implementation_deps:         *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps),
-		Dynamic_deps:                *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps),
-		Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps),
-		Whole_archive_deps:          *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps),
-		System_dynamic_deps:         *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps),
-		Runtime_deps:                linkerAttrs.runtimeDeps,
-		sdkAttributes:               bp2BuildParseSdkAttributes(m),
+		Deps:                              *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps),
+		Implementation_deps:               *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps),
+		Dynamic_deps:                      *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps),
+		Implementation_dynamic_deps:       *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps),
+		Whole_archive_deps:                *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps),
+		Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
+		System_dynamic_deps:               *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps),
+		Runtime_deps:                      linkerAttrs.runtimeDeps,
+		sdkAttributes:                     bp2BuildParseSdkAttributes(m),
 	}
 
 	staticTargetAttrs := &bazelCcLibraryStaticAttributes{
@@ -366,7 +367,6 @@
 		Stl:                      compilerAttrs.stl,
 		Cpp_std:                  compilerAttrs.cppStd,
 		C_std:                    compilerAttrs.cStd,
-		Use_version_lib:          linkerAttrs.useVersionLib,
 
 		Features: baseAttributes.features,
 	}
@@ -2630,8 +2630,7 @@
 		attrs = &bazelCcLibraryStaticAttributes{
 			staticOrSharedAttributes: commonAttrs,
 
-			Use_libcrt:      linkerAttrs.useLibcrt,
-			Use_version_lib: linkerAttrs.useVersionLib,
+			Use_libcrt: linkerAttrs.useLibcrt,
 
 			Rtti:    compilerAttrs.rtti,
 			Stl:     compilerAttrs.stl,
diff --git a/cc/lto_test.go b/cc/lto_test.go
new file mode 100644
index 0000000..b52f2b6
--- /dev/null
+++ b/cc/lto_test.go
@@ -0,0 +1,90 @@
+// Copyright 2021 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 cc
+
+import (
+	"android/soong/android"
+	"strings"
+	"testing"
+
+	"github.com/google/blueprint"
+)
+
+func TestThinLtoDeps(t *testing.T) {
+	bp := `
+	cc_library {
+		name: "lto_enabled",
+		srcs: ["src.c"],
+		static_libs: ["foo"],
+		shared_libs: ["bar"],
+		lto: {
+			thin: true,
+		}
+	}
+	cc_library {
+		name: "foo",
+		static_libs: ["baz"],
+	}
+	cc_library {
+		name: "bar",
+		static_libs: ["qux"],
+	}
+	cc_library {
+		name: "baz",
+	}
+	cc_library {
+		name: "qux",
+	}
+`
+
+	result := android.GroupFixturePreparers(
+		prepareForCcTest,
+	).RunTestWithBp(t, bp)
+
+	libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
+	libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
+	libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
+
+	hasDep := func(m android.Module, wantDep android.Module) bool {
+		var found bool
+		result.VisitDirectDeps(m, func(dep blueprint.Module) {
+			if dep == wantDep {
+				found = true
+			}
+		})
+		return found
+	}
+
+	if !hasDep(libLto, libFoo) {
+		t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
+	}
+
+	if !hasDep(libFoo, libBaz) {
+		t.Errorf("'lto_enabled' missing dependency on thin lto variant of transitive dep 'baz'")
+	}
+
+	barVariants := result.ModuleVariantsForTests("bar")
+	for _, v := range barVariants {
+		if strings.Contains(v, "lto-thin") {
+			t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
+		}
+	}
+	quxVariants := result.ModuleVariantsForTests("qux")
+	for _, v := range quxVariants {
+		if strings.Contains(v, "lto-thin") {
+			t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
+		}
+	}
+}
diff --git a/cc/makevars.go b/cc/makevars.go
index 8154436..de8a8f2 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -53,7 +53,6 @@
 
 func makeStringOfWarningAllowedProjects() string {
 	allProjects := append([]string{}, config.WarningAllowedProjects...)
-	allProjects = append(allProjects, config.WarningAllowedOldProjects...)
 	sort.Strings(allProjects)
 	// Makefile rules use pattern "path/%" to match module paths.
 	if len(allProjects) > 0 {
diff --git a/cc/object.go b/cc/object.go
index 65a11e0..1a96b72 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"strings"
 
 	"android/soong/android"
 	"android/soong/bazel"
@@ -254,22 +255,31 @@
 
 	var outputFile android.Path
 	builderFlags := flagsToBuilderFlags(flags)
+	outputName := ctx.ModuleName()
+	if !strings.HasSuffix(outputName, objectExtension) {
+		outputName += objectExtension
+	}
 
 	if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
-		outputFile = objs.objFiles[0]
-
-		if String(object.Properties.Prefix_symbols) != "" {
-			output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
-			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), outputFile,
-				builderFlags, output)
-			outputFile = output
-		}
-	} else {
-		output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
+		output := android.PathForModuleOut(ctx, outputName)
 		outputFile = output
 
 		if String(object.Properties.Prefix_symbols) != "" {
-			input := android.PathForModuleOut(ctx, "unprefixed", ctx.ModuleName()+objectExtension)
+			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), objs.objFiles[0],
+				builderFlags, output)
+		} else {
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   android.Cp,
+				Input:  objs.objFiles[0],
+				Output: output,
+			})
+		}
+	} else {
+		output := android.PathForModuleOut(ctx, outputName)
+		outputFile = output
+
+		if String(object.Properties.Prefix_symbols) != "" {
+			input := android.PathForModuleOut(ctx, "unprefixed", outputName)
 			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
 				builderFlags, output)
 			output = input
diff --git a/cc/object_test.go b/cc/object_test.go
index 259a892..5359a35 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -15,6 +15,7 @@
 package cc
 
 import (
+	"fmt"
 	"testing"
 
 	"android/soong/android"
@@ -107,3 +108,65 @@
 	expectedOutputFiles := []string{"outputbase/execroot/__main__/bazel_out.o"}
 	android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
 }
+
+func TestCcObjectOutputFile(t *testing.T) {
+	testcases := []struct {
+		name       string
+		moduleName string
+		bp         string
+	}{
+		{
+			name:       "normal",
+			moduleName: "foo",
+			bp: `
+				srcs: ["bar.c"],
+			`,
+		},
+		{
+			name:       "suffix",
+			moduleName: "foo.o",
+			bp: `
+				srcs: ["bar.c"],
+			`,
+		},
+		{
+			name:       "keep symbols",
+			moduleName: "foo",
+			bp: `
+				srcs: ["bar.c"],
+				prefix_symbols: "foo_",
+			`,
+		},
+		{
+			name:       "partial linking",
+			moduleName: "foo",
+			bp: `
+				srcs: ["bar.c", "baz.c"],
+			`,
+		},
+		{
+			name:       "partial linking and prefix symbols",
+			moduleName: "foo",
+			bp: `
+				srcs: ["bar.c", "baz.c"],
+				prefix_symbols: "foo_",
+			`,
+		},
+	}
+
+	for _, testcase := range testcases {
+		bp := fmt.Sprintf(`
+			cc_object {
+				name: "%s",
+				%s
+			}
+		`, testcase.moduleName, testcase.bp)
+		t.Run(testcase.name, func(t *testing.T) {
+			ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
+			android.AssertPathRelativeToTopEquals(t, "expected output file foo.o",
+				fmt.Sprintf("out/soong/.intermediates/%s/android_arm64_armv8-a/foo.o", testcase.moduleName),
+				ctx.ModuleForTests(testcase.moduleName, "android_arm64_armv8-a").Output("foo.o").Output)
+		})
+	}
+
+}
diff --git a/cc/proto.go b/cc/proto.go
index 8e6d5ed..cf5ed04 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -178,7 +178,7 @@
 	var ret bp2buildProtoDeps
 
 	protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
-	if !ok {
+	if !ok || protoInfo.Proto_libs.IsEmpty() {
 		return ret
 	}
 
@@ -201,9 +201,8 @@
 	dep := android.BazelLabelForModuleDepSingle(ctx, depName)
 	ret.protoDep = &bazel.LabelAttribute{Value: &dep}
 
-	protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
 	var protoAttrs protoAttributes
-	protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
+	protoAttrs.Deps.SetValue(protoInfo.Proto_libs)
 
 	name := m.Name() + suffix
 
diff --git a/cc/sysprop.go b/cc/sysprop.go
deleted file mode 100644
index f578b50..0000000
--- a/cc/sysprop.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// 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 cc
-
-// This file contains a map to redirect dependencies towards sysprop_library.
-// As sysprop_library has to support both Java and C++, sysprop_library internally
-// generates cc_library and java_library. For example, the following sysprop_library
-//
-//     sysprop_library {
-//         name: "foo",
-//     }
-//
-// will internally generate with prefix "lib"
-//
-//     cc_library {
-//         name: "libfoo",
-//     }
-//
-// When a cc module links against "foo", build system will redirect the
-// dependency to "libfoo". To do that, SyspropMutator gathers all sysprop_library,
-// records their cc implementation library names to a map. The map will be used in
-// cc.Module.DepsMutator.
-
-import (
-	"sync"
-
-	"android/soong/android"
-)
-
-type syspropLibraryInterface interface {
-	BaseModuleName() string
-	CcImplementationModuleName() string
-}
-
-var (
-	syspropImplLibrariesKey  = android.NewOnceKey("syspropImplLibirares")
-	syspropImplLibrariesLock sync.Mutex
-)
-
-func syspropImplLibraries(config android.Config) map[string]string {
-	return config.Once(syspropImplLibrariesKey, func() interface{} {
-		return make(map[string]string)
-	}).(map[string]string)
-}
-
-// gather list of sysprop libraries
-func SyspropMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(syspropLibraryInterface); ok {
-		syspropImplLibraries := syspropImplLibraries(mctx.Config())
-		syspropImplLibrariesLock.Lock()
-		defer syspropImplLibrariesLock.Unlock()
-
-		// BaseModuleName is the name of sysprop_library
-		// CcImplementationModuleName is the name of cc_library generated by sysprop_library
-		syspropImplLibraries[m.BaseModuleName()] = m.CcImplementationModuleName()
-	}
-}
diff --git a/cc/test.go b/cc/test.go
index 28a0e5e..715c537 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -659,6 +659,7 @@
 	testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
 
 	var data bazel.LabelListAttribute
+	var tags bazel.StringListAttribute
 
 	testBinaryProps := m.GetArchVariantProperties(ctx, &TestBinaryProperties{})
 	for axis, configToProps := range testBinaryProps {
@@ -670,6 +671,7 @@
 				combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_bins))
 				combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs))
 				data.SetSelectValue(axis, config, combinedData)
+				tags.SetSelectValue(axis, config, p.Test_options.Tags)
 			}
 		}
 	}
@@ -690,6 +692,7 @@
 		android.CommonAttributes{
 			Name: m.Name(),
 			Data: data,
+			Tags: tags,
 		},
 		&testBinaryAttrs)
 }
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index 1cf64de..c420567 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -29,6 +29,7 @@
 
 	"google.golang.org/protobuf/proto"
 
+	"android/soong/cmd/extract_apks/bundle_proto"
 	android_bundle_proto "android/soong/cmd/extract_apks/bundle_proto"
 	"android/soong/third_party/zip"
 )
@@ -75,7 +76,7 @@
 		return nil, err
 	}
 	bytes := make([]byte, tocFile.FileHeader.UncompressedSize64)
-	if _, err := rc.Read(bytes); err != io.EOF {
+	if _, err := rc.Read(bytes); err != nil && err != io.EOF {
 		return nil, err
 	}
 	rc.Close()
@@ -197,6 +198,49 @@
 	*android_bundle_proto.MultiAbiTargeting
 }
 
+type multiAbiValue []*bundle_proto.Abi
+
+func (m multiAbiValue) compare(other multiAbiValue) int {
+	min := func(a, b int) int {
+		if a < b {
+			return a
+		}
+		return b
+	}
+
+	sortAbis := func(abiSlice multiAbiValue) func(i, j int) bool {
+		return func(i, j int) bool {
+			// sort priorities greatest to least
+			return multiAbiPriorities[abiSlice[i].Alias] > multiAbiPriorities[abiSlice[j].Alias]
+		}
+	}
+
+	m = append(multiAbiValue{}, m...)
+	sort.Slice(m, sortAbis(m))
+	other = append(multiAbiValue{}, other...)
+	sort.Slice(other, sortAbis(other))
+
+	for i := 0; i < min(len(m), len(other)); i++ {
+		if multiAbiPriorities[m[i].Alias] > multiAbiPriorities[other[i].Alias] {
+			return 1
+		}
+		if multiAbiPriorities[m[i].Alias] < multiAbiPriorities[other[i].Alias] {
+			return -1
+		}
+	}
+
+	if len(m) == len(other) {
+		return 0
+	}
+	if len(m) > len(other) {
+		return 1
+	}
+	return -1
+}
+
+// this logic should match the logic in bundletool at
+// https://github.com/google/bundletool/blob/ae0fc0162fd80d92ef8f4ef4527c066f0106942f/src/main/java/com/android/tools/build/bundletool/device/MultiAbiMatcher.java#L43
+// (note link is the commit at time of writing; but logic should always match the latest)
 func (t multiAbiTargetingMatcher) matches(config TargetConfig) bool {
 	if t.MultiAbiTargeting == nil {
 		return true
@@ -204,31 +248,45 @@
 	if _, ok := config.abis[android_bundle_proto.Abi_UNSPECIFIED_CPU_ARCHITECTURE]; ok {
 		return true
 	}
-	// Find the one with the highest priority.
-	highestPriority := 0
-	for _, v := range t.GetValue() {
-		for _, a := range v.GetAbi() {
-			if _, ok := config.abis[a.Alias]; ok {
-				if highestPriority < multiAbiPriorities[a.Alias] {
-					highestPriority = multiAbiPriorities[a.Alias]
-				}
+
+	multiAbiIsValid := func(m multiAbiValue) bool {
+		for _, abi := range m {
+			if _, ok := config.abis[abi.Alias]; !ok {
+				return false
 			}
 		}
+		return true
 	}
-	if highestPriority == 0 {
+
+	// ensure that the current value is valid for our config
+	valueSetContainsViableAbi := false
+	multiAbiSet := t.GetValue()
+	for _, multiAbi := range multiAbiSet {
+		if multiAbiIsValid(multiAbi.GetAbi()) {
+			valueSetContainsViableAbi = true
+		}
+	}
+
+	if !valueSetContainsViableAbi {
 		return false
 	}
+
 	// See if there are any matching alternatives with a higher priority.
-	for _, v := range t.GetAlternatives() {
-		for _, a := range v.GetAbi() {
-			if _, ok := config.abis[a.Alias]; ok {
-				if highestPriority < multiAbiPriorities[a.Alias] {
-					// There's a better one. Skip this one.
-					return false
-				}
+	for _, altMultiAbi := range t.GetAlternatives() {
+		if !multiAbiIsValid(altMultiAbi.GetAbi()) {
+			continue
+		}
+
+		for _, multiAbi := range multiAbiSet {
+			valueAbis := multiAbiValue(multiAbi.GetAbi())
+			altAbis := multiAbiValue(altMultiAbi.GetAbi())
+			if valueAbis.compare(altAbis) < 0 {
+				// An alternative has a higher priority, don't use this one
+				return false
 			}
 		}
 	}
+
 	return true
 }
 
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index f5e4046..c1d712d 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -420,6 +420,370 @@
 	}
 }
 
+func TestSelectApks_ApexSet_Variants(t *testing.T) {
+	testCases := []testDesc{
+		{
+			protoText: `
+variant {
+	targeting {
+		sdk_version_targeting {value {min {value: 29}}}
+		multi_abi_targeting {
+			value {abi {alias: ARMEABI_V7A}}
+			alternatives {
+				abi {alias: ARMEABI_V7A}
+				abi {alias: ARM64_V8A}
+			}
+			alternatives {abi {alias: ARM64_V8A}}
+			alternatives {abi {alias: X86}}
+			alternatives {
+				abi {alias: X86}
+				abi {alias: X86_64}
+			}
+		}
+	}
+	apk_set {
+		module_metadata {
+			name: "base"
+			delivery_type: INSTALL_TIME
+		}
+		apk_description {
+			targeting {
+				multi_abi_targeting {
+					value {abi {alias: ARMEABI_V7A}}
+					alternatives {
+						abi {alias: ARMEABI_V7A}
+						abi {alias: ARM64_V8A}
+					}
+					alternatives {abi {alias: ARM64_V8A}}
+					alternatives {abi {alias: X86}}
+					alternatives {
+						abi {alias: X86}
+						abi {alias: X86_64}
+					}
+				}
+			}
+			path: "standalones/standalone-armeabi_v7a.apex"
+		}
+	}
+	variant_number: 0
+}
+variant {
+	targeting {
+		sdk_version_targeting {value {min {value: 29}}}
+		multi_abi_targeting {
+			value {abi {alias: ARM64_V8A}}
+			alternatives {abi {alias: ARMEABI_V7A}}
+			alternatives {
+				abi {alias: ARMEABI_V7A}
+				abi {alias: ARM64_V8A}
+			}
+			alternatives {abi {alias: X86}}
+			alternatives {
+				abi {alias: X86}
+				abi {alias: X86_64}
+			}
+		}
+	}
+	apk_set {
+		module_metadata {
+			name: "base"
+			delivery_type: INSTALL_TIME
+		}
+		apk_description {
+			targeting {
+				multi_abi_targeting {
+					value {abi {alias: ARM64_V8A}}
+					alternatives {abi {alias: ARMEABI_V7A}}
+					alternatives {
+						abi {alias: ARMEABI_V7A}
+						abi {alias: ARM64_V8A}
+					}
+					alternatives {abi {alias: X86}}
+					alternatives {
+						abi {alias: X86}
+						abi {alias: X86_64}
+					}
+				}
+			}
+			path: "standalones/standalone-arm64_v8a.apex"
+		}
+	}
+	variant_number: 1
+}
+variant {
+	targeting {
+		sdk_version_targeting {value {min {value: 29}}}
+		multi_abi_targeting {
+			value {
+				abi {alias: ARMEABI_V7A}
+				abi {alias: ARM64_V8A}
+			}
+			alternatives {abi {alias: ARMEABI_V7A}}
+			alternatives {abi {alias: ARM64_V8A}}
+			alternatives {abi {alias: X86}}
+			alternatives {
+				abi {alias: X86}
+				abi {alias: X86_64}
+			}
+		}
+	}
+	apk_set {
+		module_metadata {
+			name: "base"
+			delivery_type: INSTALL_TIME
+		}
+		apk_description {
+			targeting {
+				multi_abi_targeting {
+					value {
+						abi {alias: ARMEABI_V7A}
+						abi {alias: ARM64_V8A}
+					}
+					alternatives {abi {alias: ARMEABI_V7A}}
+					alternatives {abi {alias: ARM64_V8A}}
+					alternatives {abi {alias: X86}}
+					alternatives {
+						abi {alias: X86}
+						abi {alias: X86_64}
+					}
+				}
+			}
+			path: "standalones/standalone-armeabi_v7a.arm64_v8a.apex"
+		}
+	}
+	variant_number: 2
+}
+variant {
+	targeting {
+		sdk_version_targeting {value {min {value: 29}}}
+		multi_abi_targeting {
+			value {abi {alias: X86}}
+			alternatives {abi {alias: ARMEABI_V7A}}
+			alternatives {
+				abi {alias: ARMEABI_V7A}
+				abi {alias: ARM64_V8A}
+			}
+			alternatives {abi {alias: ARM64_V8A}}
+			alternatives {
+				abi {alias: X86}
+				abi {alias: X86_64}
+			}
+		}
+	}
+	apk_set {
+		module_metadata {
+			name: "base"
+			delivery_type: INSTALL_TIME
+		}
+		apk_description {
+			targeting {
+				multi_abi_targeting {
+					value {abi {alias: X86}}
+					alternatives {abi {alias: ARMEABI_V7A}}
+					alternatives {
+						abi {alias: ARMEABI_V7A}
+						abi {alias: ARM64_V8A}
+					}
+					alternatives {abi {alias: ARM64_V8A}}
+					alternatives {
+						abi {alias: X86}
+						abi {alias: X86_64}
+					}
+				}
+			}
+			path: "standalones/standalone-x86.apex"
+		}
+	}
+	variant_number: 3
+}
+variant {
+	targeting {
+		sdk_version_targeting {value {min {value: 29}}}
+		multi_abi_targeting {
+			value {
+				abi {alias: X86}
+				abi {alias: X86_64}
+			}
+			alternatives {abi {alias: ARMEABI_V7A}}
+			alternatives {
+				abi {alias: ARMEABI_V7A}
+				abi {alias: ARM64_V8A}
+			}
+			alternatives {abi {alias: ARM64_V8A}}
+			alternatives {abi {alias: X86}}
+		}
+	}
+	apk_set {
+		module_metadata {
+			name: "base"
+			delivery_type: INSTALL_TIME
+		}
+		apk_description {
+			targeting {
+				multi_abi_targeting {
+					value {
+						abi {alias: X86}
+						abi {alias: X86_64}
+					}
+					alternatives {abi {alias: ARMEABI_V7A}}
+					alternatives {
+						abi {alias: ARMEABI_V7A}
+						abi {alias: ARM64_V8A}
+					}
+					alternatives {abi {alias: ARM64_V8A}}
+					alternatives {abi {alias: X86}}
+				}
+			}
+			path: "standalones/standalone-x86.x86_64.apex"
+		}
+  }
+  variant_number: 4
+}
+`,
+			configs: []testConfigDesc{
+				{
+					name: "multi-variant multi-target ARM",
+					targetConfig: TargetConfig{
+						sdkVersion: 33,
+						screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+							bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+						},
+						abis: map[bp.Abi_AbiAlias]int{
+							bp.Abi_ARM64_V8A:   0,
+							bp.Abi_ARMEABI_V7A: 1,
+						},
+					},
+					expected: SelectionResult{
+						"base",
+						[]string{
+							"standalones/standalone-armeabi_v7a.arm64_v8a.apex",
+						},
+					},
+				},
+				{
+					name: "multi-variant single-target arm",
+					targetConfig: TargetConfig{
+						sdkVersion: 33,
+						screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+							bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+						},
+						abis: map[bp.Abi_AbiAlias]int{
+							bp.Abi_ARMEABI_V7A: 0,
+						},
+					},
+					expected: SelectionResult{
+						"base",
+						[]string{
+							"standalones/standalone-armeabi_v7a.apex",
+						},
+					},
+				},
+				{
+					name: "multi-variant single-target arm64",
+					targetConfig: TargetConfig{
+						sdkVersion: 33,
+						screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+							bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+						},
+						abis: map[bp.Abi_AbiAlias]int{
+							bp.Abi_ARM64_V8A: 0,
+						},
+					},
+					expected: SelectionResult{
+						"base",
+						[]string{
+							"standalones/standalone-arm64_v8a.apex",
+						},
+					},
+				},
+				{
+					name: "multi-variant multi-target x86",
+					targetConfig: TargetConfig{
+						sdkVersion: 33,
+						screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+							bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+						},
+						abis: map[bp.Abi_AbiAlias]int{
+							bp.Abi_X86:    0,
+							bp.Abi_X86_64: 1,
+						},
+					},
+					expected: SelectionResult{
+						"base",
+						[]string{
+							"standalones/standalone-x86.x86_64.apex",
+						},
+					},
+				},
+				{
+					name: "multi-variant single-target x86",
+					targetConfig: TargetConfig{
+						sdkVersion: 33,
+						screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+							bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+						},
+						abis: map[bp.Abi_AbiAlias]int{
+							bp.Abi_X86: 0,
+						},
+					},
+					expected: SelectionResult{
+						"base",
+						[]string{
+							"standalones/standalone-x86.apex",
+						},
+					},
+				},
+				{
+					name: "multi-variant single-target x86_64",
+					targetConfig: TargetConfig{
+						sdkVersion: 33,
+						screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+							bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+						},
+						abis: map[bp.Abi_AbiAlias]int{
+							bp.Abi_X86_64: 0,
+						},
+					},
+					expected: SelectionResult{},
+				},
+				{
+					name: "multi-variant multi-target cross-target",
+					targetConfig: TargetConfig{
+						sdkVersion: 33,
+						screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+							bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+						},
+						abis: map[bp.Abi_AbiAlias]int{
+							bp.Abi_ARM64_V8A: 0,
+							bp.Abi_X86_64:    1,
+						},
+					},
+					expected: SelectionResult{
+						"base",
+						[]string{
+							"standalones/standalone-arm64_v8a.apex",
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, testCase := range testCases {
+		var toc bp.BuildApksResult
+		if err := prototext.Unmarshal([]byte(testCase.protoText), &toc); err != nil {
+			t.Fatal(err)
+		}
+		for _, config := range testCase.configs {
+			t.Run(config.name, func(t *testing.T) {
+				actual := selectApks(&toc, config.targetConfig)
+				if !reflect.DeepEqual(config.expected, actual) {
+					t.Errorf("expected %v, got %v", config.expected, actual)
+				}
+			})
+		}
+	}
+}
+
 type testZip2ZipWriter struct {
 	entries map[string]string
 }
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index d8011d6..fdfd22e 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -201,6 +201,11 @@
 	if apex := global.AllApexSystemServerJars(ctx).ApexOfJar(lib); apex != "" {
 		return fmt.Sprintf("/apex/%s/javalib/%s.jar", apex, lib)
 	}
+
+	if apex := global.AllPlatformSystemServerJars(ctx).ApexOfJar(lib); apex == "system_ext" {
+		return fmt.Sprintf("/system_ext/framework/%s.jar", lib)
+	}
+
 	return fmt.Sprintf("/system/framework/%s.jar", lib)
 }
 
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 07e4fad..429b5ff 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -59,6 +59,15 @@
 		android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
 }
 
+func testSystemExtSystemServerModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
+	return createTestModuleConfig(
+		name,
+		fmt.Sprintf("/system_ext/framework/%s.jar", name),
+		android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)),
+		android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)),
+		android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
+}
+
 func createTestModuleConfig(name, dexLocation string, buildPath, dexPath, enforceUsesLibrariesStatusFile android.OutputPath) *ModuleConfig {
 	return &ModuleConfig{
 		Name:                            name,
@@ -213,6 +222,29 @@
 	android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
 }
 
+func TestDexPreoptSystemExtSystemServerJars(t *testing.T) {
+	config := android.TestConfig("out", nil, "", nil)
+	ctx := android.BuilderContextForTesting(config)
+	globalSoong := globalSoongConfigForTests()
+	global := GlobalConfigForTests(ctx)
+	module := testSystemExtSystemServerModuleConfig(ctx, "service-A")
+
+	global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(
+		[]string{"system_ext:service-A"})
+
+	rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	wantInstalls := android.RuleBuilderInstalls{
+		{android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system_ext/framework/oat/arm/service-A.odex"},
+		{android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system_ext/framework/oat/arm/service-A.vdex"},
+	}
+
+	android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
+}
+
 func TestDexPreoptApexStandaloneSystemServerJars(t *testing.T) {
 	config := android.TestConfig("out", nil, "", nil)
 	ctx := android.BuilderContextForTesting(config)
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 9316807..42a11fb 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -840,22 +840,7 @@
 
 // isTestFragment returns true if the current module is a test bootclasspath_fragment.
 func (b *BootclasspathFragmentModule) isTestFragment() bool {
-	if b.testFragment {
-		return true
-	}
-
-	// TODO(b/194063708): Once test fragments all use bootclasspath_fragment_test
-	// Some temporary exceptions until all test fragments use the
-	// bootclasspath_fragment_test module type.
-	name := b.BaseModuleName()
-	if strings.HasPrefix(name, "test_") {
-		return true
-	}
-	if name == "apex.apexd_test_bootclasspath-fragment" {
-		return true
-	}
-
-	return false
+	return b.testFragment
 }
 
 // produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files)
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index c63df59..2541f14 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -408,22 +408,6 @@
 			},
 		}
 
-		bootclasspath_fragment {
-			name: "test_fragment",
-			contents: ["mysdklibrary"],
-			hidden_api: {
-				split_packages: [],
-			},
-		}
-
-		bootclasspath_fragment {
-			name: "apex.apexd_test_bootclasspath-fragment",
-			contents: ["mysdklibrary"],
-			hidden_api: {
-				split_packages: [],
-			},
-		}
-
 		bootclasspath_fragment_test {
 			name: "a_test_fragment",
 			contents: ["mysdklibrary"],
@@ -445,12 +429,6 @@
 	fragment := result.Module("myfragment", "android_common").(*BootclasspathFragmentModule)
 	android.AssertBoolEquals(t, "not a test fragment", false, fragment.isTestFragment())
 
-	fragment = result.Module("test_fragment", "android_common").(*BootclasspathFragmentModule)
-	android.AssertBoolEquals(t, "is a test fragment by prefix", true, fragment.isTestFragment())
-
 	fragment = result.Module("a_test_fragment", "android_common").(*BootclasspathFragmentModule)
 	android.AssertBoolEquals(t, "is a test fragment by type", true, fragment.isTestFragment())
-
-	fragment = result.Module("apex.apexd_test_bootclasspath-fragment", "android_common").(*BootclasspathFragmentModule)
-	android.AssertBoolEquals(t, "is a test fragment by name", true, fragment.isTestFragment())
 }
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 0785f89..578dc2b 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -365,7 +365,10 @@
 // sysprop_library creates schematized APIs from sysprop description files (.sysprop).
 // Both Java and C++ modules can link against sysprop_library, and API stability check
 // against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
-// is performed.
+// is performed. Note that the generated C++ module has its name prefixed with
+// `lib`, and it is this module that should be depended on from other C++
+// modules; i.e., if the sysprop_library module is named `foo`, C++ modules
+// should depend on `libfoo`.
 func syspropLibraryFactory() android.Module {
 	m := &syspropLibrary{}
 
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 88ef615..80b86e0 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -209,32 +209,32 @@
 		cc_library {
 			name: "cc-client-platform",
 			srcs: ["d.cpp"],
-			static_libs: ["sysprop-platform"],
+			static_libs: ["libsysprop-platform"],
 		}
 
 		cc_library_static {
 			name: "cc-client-platform-static",
 			srcs: ["d.cpp"],
-			whole_static_libs: ["sysprop-platform"],
+			whole_static_libs: ["libsysprop-platform"],
 		}
 
 		cc_library {
 			name: "cc-client-product",
 			srcs: ["d.cpp"],
 			product_specific: true,
-			static_libs: ["sysprop-platform-on-product", "sysprop-vendor-on-product"],
+			static_libs: ["libsysprop-platform-on-product", "libsysprop-vendor-on-product"],
 		}
 
 		cc_library {
 			name: "cc-client-vendor",
 			srcs: ["d.cpp"],
 			soc_specific: true,
-			static_libs: ["sysprop-platform", "sysprop-vendor"],
+			static_libs: ["libsysprop-platform", "libsysprop-vendor"],
 		}
 
 		cc_binary_host {
 			name: "hostbin",
-			static_libs: ["sysprop-platform"],
+			static_libs: ["libsysprop-platform"],
 		}
 	`)
 
diff --git a/tests/lib.sh b/tests/lib.sh
index 7248ade..4b4d908 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -123,6 +123,7 @@
   symlink_directory prebuilts/jdk
   symlink_directory external/bazel-skylib
   symlink_directory external/bazelbuild-rules_android
+  symlink_directory external/bazelbuild-rules_license
   symlink_directory external/bazelbuild-kotlin-rules
 
   symlink_file WORKSPACE