Merge "add java_import to mixed build"
diff --git a/android/Android.bp b/android/Android.bp
index cbd3459..f58a472 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -88,6 +88,7 @@
         "test_asserts.go",
         "test_suites.go",
         "testing.go",
+        "updatable_modules.go",
         "util.go",
         "variable.go",
         "visibility.go",
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 9decfbd..5b440b9 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -367,6 +367,7 @@
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
+		"linker_config",
 		"java_import",
 		"java_import_host",
 	}
@@ -441,7 +442,6 @@
 		"art-script",                                                 // depends on unconverted modules: dalvikvm, dex2oat
 		"bin2c_fastdeployagent",                                      // depends on unconverted modules: deployagent
 		"com.android.runtime",                                        // depends on unconverted modules: bionic-linker-config, linkerconfig
-		"conv_linker_config",                                         // depends on unconverted modules: linker_config_proto
 		"currysrc",                                                   // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
 		"dex2oat-script",                                             // depends on unconverted modules: dex2oat
 		"generated_android_icu4j_resources",                          // depends on unconverted modules: android_icu4j_srcgen_binary, soong_zip
diff --git a/android/androidmk.go b/android/androidmk.go
index d6fe06d..006e43d 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -604,10 +604,6 @@
 		}
 	}
 
-	if len(base.noticeFiles) > 0 {
-		a.AddStrings("LOCAL_NOTICE_FILE", strings.Join(base.noticeFiles.Strings(), " "))
-	}
-
 	if host {
 		makeOs := base.Os().String()
 		if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 1d0a6d5..c030aa8 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -32,14 +32,14 @@
 // There is often a similar method for Bazel as there is for Soong path handling and should be used
 // in similar circumstances
 //
-// Bazel                                Soong
-//
-// BazelLabelForModuleSrc               PathForModuleSrc
-// BazelLabelForModuleSrcExcludes       PathForModuleSrcExcludes
-// BazelLabelForModuleDeps              n/a
-// tbd                                  PathForSource
-// tbd                                  ExistentPathsForSources
-// PathForBazelOut                      PathForModuleOut
+//   Bazel                                Soong
+//   ==============================================================
+//   BazelLabelForModuleSrc               PathForModuleSrc
+//   BazelLabelForModuleSrcExcludes       PathForModuleSrcExcludes
+//   BazelLabelForModuleDeps              n/a
+//   tbd                                  PathForSource
+//   tbd                                  ExistentPathsForSources
+//   PathForBazelOut                      PathForModuleOut
 //
 // Use cases:
 //  * Module contains a property (often tagged `android:"path"`) that expects paths *relative to the
@@ -68,7 +68,7 @@
 //   cannot be resolved,the function will panic. This is often due to the dependency not being added
 //   via an AddDependency* method.
 
-// A minimal context interface to check if a module should be converted by bp2build,
+// BazelConversionContext is a minimal context interface to check if a module should be converted by bp2build,
 // with functions containing information to match against allowlists and denylists.
 // If a module is deemed to be convertible by bp2build, then it should rely on a
 // BazelConversionPathContext for more functions for dep/path features.
diff --git a/android/config.go b/android/config.go
index a5337d0..8c01bee 100644
--- a/android/config.go
+++ b/android/config.go
@@ -761,6 +761,10 @@
 	return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
 }
 
+func (c *config) PlatformSdkFinal() bool {
+	return Bool(c.productVariables.Platform_sdk_final)
+}
+
 func (c *config) PlatformSdkCodename() string {
 	return String(c.productVariables.Platform_sdk_codename)
 }
@@ -1446,8 +1450,8 @@
 	return Bool(c.productVariables.ForceApexSymlinkOptimization)
 }
 
-func (c *config) CompressedApex() bool {
-	return Bool(c.productVariables.CompressedApex)
+func (c *config) ApexCompressionEnabled() bool {
+	return Bool(c.productVariables.CompressedApex) && !c.UnbundledBuildApps()
 }
 
 func (c *config) EnforceSystemCertificate() bool {
diff --git a/android/license_metadata.go b/android/license_metadata.go
index f2ab0a4..4ee5bf7 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -15,7 +15,6 @@
 package android
 
 import (
-	"fmt"
 	"sort"
 	"strings"
 
@@ -67,6 +66,11 @@
 			return
 		}
 
+		// Defaults add properties and dependencies that get processed on their own.
+		if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
+			return
+		}
+
 		if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
 			info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
 			allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
@@ -139,8 +143,6 @@
 	if len(outputFiles) > 0 {
 		args = append(args,
 			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
-	} else {
-		args = append(args, fmt.Sprintf("-t //%s:%s", ctx.ModuleDir(), ctx.ModuleName()))
 	}
 
 	// Installed files
diff --git a/android/metrics.go b/android/metrics.go
index 1580f82..ecda026 100644
--- a/android/metrics.go
+++ b/android/metrics.go
@@ -32,8 +32,13 @@
 	Variants int
 }
 
-func ReadSoongMetrics(config Config) SoongMetrics {
-	return config.Get(soongMetricsOnceKey).(SoongMetrics)
+func readSoongMetrics(config Config) (SoongMetrics, bool) {
+	soongMetrics, ok := config.Peek(soongMetricsOnceKey)
+	if ok {
+		return soongMetrics.(SoongMetrics), true
+	} else {
+		return SoongMetrics{}, false
+	}
 }
 
 func init() {
@@ -60,9 +65,11 @@
 func collectMetrics(config Config, eventHandler metrics.EventHandler) *soong_metrics_proto.SoongBuildMetrics {
 	metrics := &soong_metrics_proto.SoongBuildMetrics{}
 
-	soongMetrics := ReadSoongMetrics(config)
-	metrics.Modules = proto.Uint32(uint32(soongMetrics.Modules))
-	metrics.Variants = proto.Uint32(uint32(soongMetrics.Variants))
+	soongMetrics, ok := readSoongMetrics(config)
+	if ok {
+		metrics.Modules = proto.Uint32(uint32(soongMetrics.Modules))
+		metrics.Variants = proto.Uint32(uint32(soongMetrics.Variants))
+	}
 
 	memStats := runtime.MemStats{}
 	runtime.ReadMemStats(&memStats)
diff --git a/android/module.go b/android/module.go
index 7173c0d..4dbfdd3 100644
--- a/android/module.go
+++ b/android/module.go
@@ -515,7 +515,6 @@
 	ExportedToMake() bool
 	InitRc() Paths
 	VintfFragments() Paths
-	NoticeFiles() Paths
 	EffectiveLicenseFiles() Paths
 
 	AddProperties(props ...interface{})
@@ -831,9 +830,6 @@
 	// names of other modules to install on target if this module is installed
 	Target_required []string `android:"arch_variant"`
 
-	// relative path to a file to include in the list of notices for the device
-	Notice *string `android:"path"`
-
 	// The OsType of artifacts that this module variant is responsible for creating.
 	//
 	// Set by osMutator
@@ -1423,7 +1419,6 @@
 	checkbuildFiles      Paths
 	packagingSpecs       []PackagingSpec
 	packagingSpecsDepSet *packagingSpecsDepSet
-	noticeFiles          Paths
 	// katiInstalls tracks the install rules that were created by Soong but are being exported
 	// to Make to convert to ninja rules so that Make can add additional dependencies.
 	katiInstalls katiInstalls
@@ -2054,10 +2049,6 @@
 	return String(m.commonProperties.Owner)
 }
 
-func (m *ModuleBase) NoticeFiles() Paths {
-	return m.noticeFiles
-}
-
 func (m *ModuleBase) setImageVariation(variant string) {
 	m.commonProperties.ImageVariation = variant
 }
@@ -2317,19 +2308,6 @@
 			}
 		})
 
-		m.noticeFiles = make([]Path, 0)
-		optPath := OptionalPath{}
-		notice := proptools.StringDefault(m.commonProperties.Notice, "")
-		if module := SrcIsModule(notice); module != "" {
-			optPath = ctx.ExpandOptionalSource(&notice, "notice")
-		} else if notice != "" {
-			noticePath := filepath.Join(ctx.ModuleDir(), notice)
-			optPath = ExistentPathForSource(ctx, noticePath)
-		}
-		if optPath.Valid() {
-			m.noticeFiles = append(m.noticeFiles, optPath.Path())
-		}
-
 		licensesPropertyFlattener(ctx)
 		if ctx.Failed() {
 			return
diff --git a/android/neverallow.go b/android/neverallow.go
index 357cae5..aa47bca 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -58,7 +58,6 @@
 	AddNeverAllowRules(createMakefileGoalRules()...)
 	AddNeverAllowRules(createInitFirstStageRules()...)
 	AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
-	AddNeverAllowRules(createNoticeDeprecationRules()...)
 }
 
 // Add a NeverAllow rule to the set of rules to apply.
@@ -239,15 +238,6 @@
 	}
 }
 
-func createNoticeDeprecationRules() []Rule {
-	return []Rule{
-		NeverAllow().
-			WithMatcher("notice", isSetMatcherInstance).
-			NotIn("vendor/linaro/linux-firmware/").
-			Because("notice has been replaced by licenses/default_applicable_licenses"),
-	}
-}
-
 func neverallowMutator(ctx BottomUpMutatorContext) {
 	m, ok := ctx.Module().(Module)
 	if !ok {
diff --git a/android/onceper.go b/android/onceper.go
index 481cdea..fa415d1 100644
--- a/android/onceper.go
+++ b/android/onceper.go
@@ -79,6 +79,17 @@
 	return once.maybeWaitFor(key, v)
 }
 
+// Peek returns the value previously computed with Once for a given key.  If Once has not
+// been called for the given key Peek will return ok == false.
+func (once *OncePer) Peek(key OnceKey) (interface{}, bool) {
+	v, ok := once.values.Load(key)
+	if !ok {
+		return nil, false
+	}
+
+	return once.maybeWaitFor(key, v), true
+}
+
 // OnceStringSlice is the same as Once, but returns the value cast to a []string
 func (once *OncePer) OnceStringSlice(key OnceKey, value func() []string) []string {
 	return once.Once(key, func() interface{} { return value() }).([]string)
diff --git a/apex/constants.go b/android/updatable_modules.go
similarity index 82%
rename from apex/constants.go
rename to android/updatable_modules.go
index c68edb7..71c76c5 100644
--- a/apex/constants.go
+++ b/android/updatable_modules.go
@@ -12,11 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package apex
+package android
 
-// This file contains branch specific constants. They are stored in a separate
-// file to minimise the potential of merge conflicts between branches when
-// the code from the package is changed.
+// This file contains branch specific constants for building updatable modules.
+// They are stored in a separate file to minimise the potential of merge
+// conflicts between branches when the code from the package is changed.
 
 // The default manifest version for all the modules on this branch.
 // This version code will be used only if there is no version field in the
@@ -33,4 +33,4 @@
 // * AOSP            - xx9990000
 // * x-mainline-prod - xx9990000
 // * master          - 990090000
-const defaultManifestVersion = "339990000"
+const DefaultUpdatableModuleVersion = "339990000"
diff --git a/apex/Android.bp b/apex/Android.bp
index 6533c61..018d030 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -26,7 +26,7 @@
         "apex_sdk_member.go",
         "apex_singleton.go",
         "builder.go",
-        "constants.go",
+        "bp2build.go",
         "deapexer.go",
         "key.go",
         "prebuilt.go",
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 938c8ed..3373211 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -168,10 +168,6 @@
 			if len(newDataPaths) > 0 {
 				fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(android.AndroidMkDataPaths(newDataPaths), " "))
 			}
-
-			if fi.module != nil && len(fi.module.NoticeFiles()) > 0 {
-				fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(fi.module.NoticeFiles().Strings(), " "))
-			}
 		} else {
 			modulePath = pathWhenActivated
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated)
diff --git a/apex/apex.go b/apex/apex.go
index 4394a30..09a5784 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1857,7 +1857,11 @@
 		a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_backing.txt"))
 		// b/239084755
 		a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_using.xml"))
-		a.installedFile = ctx.InstallFile(a.installDir, a.Name()+a.installSuffix(), a.outputFile,
+		installSuffix := imageApexSuffix
+		if a.isCompressed {
+			installSuffix = imageCapexSuffix
+		}
+		a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
 			a.compatSymlinks.Paths()...)
 	default:
 		panic(fmt.Errorf("unexpected apex_type for the ProcessBazelQuery: %v", a.properties.ApexType))
@@ -1878,18 +1882,13 @@
 }
 
 func (a *apexBundle) setCompression(ctx android.ModuleContext) {
-	a.isCompressed = (a.properties.ApexType == imageApex) &&
-		((ctx.Config().CompressedApex() &&
-			proptools.BoolDefault(a.overridableProperties.Compressible, false) &&
-			!a.testApex && !ctx.Config().UnbundledBuildApps()) ||
-			a.testOnlyShouldForceCompression())
-}
-
-func (a apexBundle) installSuffix() string {
-	if a.isCompressed {
-		return imageCapexSuffix
+	if a.properties.ApexType != imageApex {
+		a.isCompressed = false
+	} else if a.testOnlyShouldForceCompression() {
+		a.isCompressed = true
+	} else {
+		a.isCompressed = ctx.Config().ApexCompressionEnabled() && a.isCompressable()
 	}
-	return imageApexSuffix
 }
 
 func (a *apexBundle) setSystemLibLink(ctx android.ModuleContext) {
@@ -1966,6 +1965,10 @@
 	}
 }
 
+func (a apexBundle) isCompressable() bool {
+	return proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex
+}
+
 func (a *apexBundle) commonBuildActions(ctx android.ModuleContext) bool {
 	a.checkApexAvailability(ctx)
 	a.checkUpdatable(ctx)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 6abd8ff..5282941 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -443,7 +443,6 @@
 			srcs: ["mylib.cpp"],
 			system_shared_libs: [],
 			stl: "none",
-			notice: "custom_notice",
 			static_libs: ["libstatic"],
 			// TODO: remove //apex_available:platform
 			apex_available: [
@@ -467,7 +466,6 @@
 			srcs: ["mylib.cpp"],
 			system_shared_libs: [],
 			stl: "none",
-			notice: "custom_notice_for_static_lib",
 			// TODO: remove //apex_available:platform
 			apex_available: [
 				"//apex_available:platform",
@@ -619,7 +617,7 @@
 			java_libs: ["myjar"],
 			apps: ["AppFoo"],
 			rros: ["rro"],
-			bpfs: ["bpf", "netd_test"],
+			bpfs: ["bpf", "netdTest"],
 			updatable: false,
 		}
 
@@ -673,8 +671,8 @@
 		}
 
 		bpf {
-			name: "netd_test",
-			srcs: ["netd_test.c"],
+			name: "netdTest",
+			srcs: ["netdTest.c"],
 			sub_dir: "netd",
 		}
 
@@ -687,7 +685,7 @@
 		"overlay/blue/rro.apk",
 		"etc/bpf/bpf.o",
 		"etc/bpf/bpf2.o",
-		"etc/bpf/netd/netd_test.o",
+		"etc/bpf/netd/netdTest.o",
 	})
 }
 
@@ -6153,7 +6151,7 @@
 			name: "override_myapex",
 			base: "myapex",
 			apps: ["override_app"],
-			bpfs: ["override_bpf"],
+			bpfs: ["overrideBpf"],
 			prebuilts: ["override_myetc"],
 			bootclasspath_fragments: ["override_bootclasspath_fragment"],
 			systemserverclasspath_fragments: ["override_systemserverclasspath_fragment"],
@@ -6203,8 +6201,8 @@
 		}
 
 		bpf {
-			name: "override_bpf",
-			srcs: ["override_bpf.c"],
+			name: "overrideBpf",
+			srcs: ["overrideBpf.c"],
 		}
 
 		prebuilt_etc {
@@ -6307,7 +6305,7 @@
 	ensureContains(t, copyCmds, "image.apex/app/override_app@TEST.BUILD_ID/override_app.apk")
 
 	ensureNotContains(t, copyCmds, "image.apex/etc/bpf/bpf.o")
-	ensureContains(t, copyCmds, "image.apex/etc/bpf/override_bpf.o")
+	ensureContains(t, copyCmds, "image.apex/etc/bpf/overrideBpf.o")
 
 	ensureNotContains(t, copyCmds, "image.apex/etc/myetc")
 	ensureContains(t, copyCmds, "image.apex/etc/override_myetc")
@@ -6341,7 +6339,7 @@
 	data.Custom(&builder, name, "TARGET_", "", data)
 	androidMk := builder.String()
 	ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
-	ensureContains(t, androidMk, "LOCAL_MODULE := override_bpf.o.override_myapex")
+	ensureContains(t, androidMk, "LOCAL_MODULE := overrideBpf.o.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE := override_bcplib.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE := override_systemserverlib.override_myapex")
diff --git a/apex/bp2build.go b/apex/bp2build.go
new file mode 100644
index 0000000..221ab13
--- /dev/null
+++ b/apex/bp2build.go
@@ -0,0 +1,30 @@
+// Copyright (C) 2022 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 apex
+
+import (
+	"android/soong/android"
+	"strings"
+)
+
+// This file contains the bp2build integration for the apex package.
+
+// Export constants as Starlark using bp2build to Bazel.
+func BazelApexToolchainVars() string {
+	content := []string{
+		"# GENERATED BY SOONG. DO NOT EDIT.",
+		"default_manifest_version = " + android.DefaultUpdatableModuleVersion, // constants.go is different in every branch.
+	}
+	return strings.Join(content, "\n")
+}
diff --git a/apex/builder.go b/apex/builder.go
index 95435f5..f1b1448 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -214,7 +214,7 @@
 		Args: map[string]string{
 			"provideNativeLibs": strings.Join(provideNativeLibs, " "),
 			"requireNativeLibs": strings.Join(requireNativeLibs, " "),
-			"default_version":   defaultManifestVersion,
+			"default_version":   android.DefaultUpdatableModuleVersion,
 			"opt":               strings.Join(optCommands, " "),
 		},
 	})
@@ -549,8 +549,6 @@
 	outHostBinDir := ctx.Config().HostToolPath(ctx, "").String()
 	prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
 
-	// Figure out if we need to compress the apex.
-	compressionEnabled := ctx.Config().CompressedApex() && proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex && !ctx.Config().UnbundledBuildApps()
 	if apexType == imageApex {
 
 		////////////////////////////////////////////////////////////////////////////////////
@@ -635,10 +633,15 @@
 		implicitInputs = append(implicitInputs, noticeAssetPath)
 		optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeAssetPath.String()))
 
-		if (moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) && !a.shouldGenerateHashtree()) && !compressionEnabled {
-			// Apexes which are supposed to be installed in builtin dirs(/system, etc)
-			// don't need hashtree for activation. Therefore, by removing hashtree from
-			// apex bundle (filesystem image in it, to be specific), we can save storage.
+		// Apexes which are supposed to be installed in builtin dirs(/system, etc)
+		// don't need hashtree for activation. Therefore, by removing hashtree from
+		// apex bundle (filesystem image in it, to be specific), we can save storage.
+		needHashTree := moduleMinSdkVersion.LessThanOrEqualTo(android.SdkVersion_Android10) ||
+			a.shouldGenerateHashtree()
+		if ctx.Config().ApexCompressionEnabled() && a.isCompressable() {
+			needHashTree = true
+		}
+		if !needHashTree {
 			optFlags = append(optFlags, "--no_hashtree")
 		}
 
@@ -806,6 +809,7 @@
 		return
 	}
 
+	installSuffix := suffix
 	a.setCompression(ctx)
 	if a.isCompressed {
 		unsignedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+imageCapexSuffix+".unsigned")
@@ -835,6 +839,7 @@
 			Args:        args,
 		})
 		a.outputFile = signedCompressedOutputFile
+		installSuffix = imageCapexSuffix
 	}
 
 	if !a.installable() {
@@ -842,7 +847,7 @@
 	}
 
 	// Install to $OUT/soong/{target,host}/.../apex.
-	a.installedFile = ctx.InstallFile(a.installDir, a.Name()+a.installSuffix(), a.outputFile,
+	a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
 		a.compatSymlinks.Paths()...)
 
 	// installed-files.txt is dist'ed
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index d580e5a..21526c3 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -86,7 +86,6 @@
 			},
 			system_shared_libs: [],
 			stl: "none",
-			notice: "custom_notice",
 		}
 		` + vndkLibrariesTxtFiles("current")
 
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 3a2bf0f..53056c7 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -499,19 +499,11 @@
 
 func TestBazelOutRemovalFromInputDepsets(t *testing.T) {
 	const inputString = `{
-  "artifacts": [{
-    "id": 1,
-    "pathFragmentId": 10
-  }, {
-    "id": 2,
-    "pathFragmentId": 20
-  }, {
-    "id": 3,
-    "pathFragmentId": 30
-  }, {
-    "id": 4,
-    "pathFragmentId": 40
-  }],
+  "artifacts": [
+    { "id": 1, "pathFragmentId": 10 },
+    { "id": 2, "pathFragmentId": 20 },
+    { "id": 3, "pathFragmentId": 30 },
+    { "id": 4, "pathFragmentId": 40 }],
   "depSetOfFiles": [{
     "id": 1111,
     "directArtifactIds": [3 , 4]
@@ -525,28 +517,14 @@
     "outputIds": [2],
     "primaryOutputId": 1
   }],
-  "pathFragments": [{
-    "id": 10,
-    "label": "input"
-  }, {
-    "id": 20,
-    "label": "output"
-  }, {
-    "id": 30,
-    "label": "dep1",
-    "parentId": 50
-  }, {
-    "id": 40,
-    "label": "dep2",
-    "parentId": 60
-  }, {
-    "id": 50,
-    "label": "bazel_tools",
-    "parentId": 60
-  }, {
-    "id": 60,
-    "label": ".."
-  }]
+  "pathFragments": [
+    { "id": 10, "label": "input" },
+    { "id": 20, "label": "output" },
+    { "id": 30, "label": "dep1", "parentId": 50 },
+    { "id": 40, "label": "dep2", "parentId": 60 },
+    { "id": 50, "label": "bazel_tools", "parentId": 60 },
+    { "id": 60, "label": ".."}
+  ]
 }`
 	actualBuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
 	if len(actualDepsets) != 1 {
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 34548ed..07557d6 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -20,15 +20,16 @@
         "soong-android",
         "soong-android-allowlists",
         "soong-android-soongconfig",
-        "soong-shared",
         "soong-apex",
         "soong-bazel",
         "soong-cc",
         "soong-cc-config",
         "soong-etc",
         "soong-genrule",
+        "soong-linkerconfig",
         "soong-python",
         "soong-sh",
+        "soong-shared",
         "soong-starlark-format",
         "soong-ui-metrics",
     ],
@@ -58,6 +59,7 @@
         "java_library_host_conversion_test.go",
         "java_plugin_conversion_test.go",
         "java_proto_conversion_test.go",
+        "linker_config_conversion_test.go",
         "performance_test.go",
         "prebuilt_etc_conversion_test.go",
         "python_binary_conversion_test.go",
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index 5bff956..0e3d2a5 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -29,7 +29,9 @@
 func Codegen(ctx *CodegenContext) CodegenMetrics {
 	// This directory stores BUILD files that could be eventually checked-in.
 	bp2buildDir := android.PathForOutput(ctx, "bp2build")
-	android.RemoveAllOutputDir(bp2buildDir)
+	if err := android.RemoveAllOutputDir(bp2buildDir); err != nil {
+		fmt.Printf("ERROR: Encountered error while cleaning %s: %s", bp2buildDir, err.Error())
+	}
 
 	res, errs := GenerateBazelTargets(ctx, true)
 	if len(errs) > 0 {
@@ -52,7 +54,9 @@
 // Get the output directory and create it if it doesn't exist.
 func getOrCreateOutputDir(outputDir android.OutputPath, ctx android.PathContext, dir string) android.OutputPath {
 	dirPath := outputDir.Join(ctx, dir)
-	android.CreateOutputDirIfNonexistent(dirPath, os.ModePerm)
+	if err := android.CreateOutputDirIfNonexistent(dirPath, os.ModePerm); err != nil {
+		fmt.Printf("ERROR: path %s: %s", dirPath, err.Error())
+	}
 	return dirPath
 }
 
@@ -60,13 +64,13 @@
 func writeFiles(ctx android.PathContext, outputDir android.OutputPath, files []BazelFile) {
 	for _, f := range files {
 		p := getOrCreateOutputDir(outputDir, ctx, f.Dir).Join(ctx, f.Basename)
-		if err := writeFile(ctx, p, f.Contents); err != nil {
+		if err := writeFile(p, f.Contents); err != nil {
 			panic(fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err))
 		}
 	}
 }
 
-func writeFile(ctx android.PathContext, pathToFile android.OutputPath, content string) error {
+func writeFile(pathToFile android.OutputPath, content string) error {
 	// These files are made editable to allow users to modify and iterate on them
 	// in the source tree.
 	return android.WriteFileToOutputDir(pathToFile, []byte(content), 0644)
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a96a3fc..415becb 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -161,22 +161,22 @@
 	unconvertedDepMode unconvertedDepsMode
 }
 
-func (c *CodegenContext) Mode() CodegenMode {
-	return c.mode
+func (ctx *CodegenContext) Mode() CodegenMode {
+	return ctx.mode
 }
 
 // CodegenMode is an enum to differentiate code-generation modes.
 type CodegenMode int
 
 const (
-	// Bp2Build: generate BUILD files with targets buildable by Bazel directly.
+	// Bp2Build - generate BUILD files with targets buildable by Bazel directly.
 	//
 	// This mode is used for the Soong->Bazel build definition conversion.
 	Bp2Build CodegenMode = iota
 
-	// QueryView: generate BUILD files with targets representing fully mutated
+	// QueryView - generate BUILD files with targets representing fully mutated
 	// Soong modules, representing the fully configured Soong module graph with
-	// variants and dependency endges.
+	// variants and dependency edges.
 	//
 	// This mode is used for discovering and introspecting the existing Soong
 	// module graph.
@@ -470,13 +470,13 @@
 		})
 	}
 
-	for p, _ := range ignoredPropNames {
+	for p := range ignoredPropNames {
 		delete(props.Attrs, p)
 	}
 	attributes := propsToAttributes(props.Attrs)
 
 	depLabelList := "[\n"
-	for depLabel, _ := range depLabels {
+	for depLabel := range depLabels {
 		depLabelList += fmt.Sprintf("        %q,\n", depLabel)
 	}
 	depLabelList += "    ]"
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index be09616..74729e4 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -569,3 +569,58 @@
 		},
 	})
 }
+
+func TestCcLibrarySharedClangUnknownFlags(t *testing.T) {
+	runCcLibrarySharedTestCase(t, bp2buildTestCase{
+		blueprint: soongCcProtoPreamble + `cc_library_shared {
+	name: "foo",
+	conlyflags: ["-a", "-finline-functions"],
+	cflags: ["-b","-finline-functions"],
+	cppflags: ["-c", "-finline-functions"],
+	ldflags: ["-d","-finline-functions", "-e"],
+	include_build_directory: false,
+}`,
+		expectedBazelTargets: []string{
+			makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+				"conlyflags": `["-a"]`,
+				"copts":      `["-b"]`,
+				"cppflags":   `["-c"]`,
+				"linkopts": `[
+        "-d",
+        "-e",
+    ]`,
+			}),
+		},
+	})
+}
+
+func TestCCLibraryFlagSpaceSplitting(t *testing.T) {
+	runCcLibrarySharedTestCase(t, bp2buildTestCase{
+		blueprint: soongCcProtoPreamble + `cc_library_shared {
+	name: "foo",
+	conlyflags: [ "-include header.h"],
+	cflags: ["-include header.h"],
+	cppflags: ["-include header.h"],
+	version_script: "version_script",
+	include_build_directory: false,
+}`,
+		expectedBazelTargets: []string{
+			makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+				"additional_linker_inputs": `["version_script"]`,
+				"conlyflags": `[
+        "-include",
+        "header.h",
+    ]`,
+				"copts": `[
+        "-include",
+        "header.h",
+    ]`,
+				"cppflags": `[
+        "-include",
+        "header.h",
+    ]`,
+				"linkopts": `["-Wl,--version-script,$(location version_script)"]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 4246f7d..8cf9bea 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -10,6 +10,8 @@
 	cc_config "android/soong/cc/config"
 	java_config "android/soong/java/config"
 
+	"android/soong/apex"
+
 	"github.com/google/blueprint/proptools"
 )
 
@@ -28,6 +30,9 @@
 	files = append(files, newFile("java_toolchain", GeneratedBuildFileName, "")) // Creates a //java_toolchain package.
 	files = append(files, newFile("java_toolchain", "constants.bzl", java_config.BazelJavaToolchainVars(cfg)))
 
+	files = append(files, newFile("apex_toolchain", GeneratedBuildFileName, "")) // Creates a //apex_toolchain package.
+	files = append(files, newFile("apex_toolchain", "constants.bzl", apex.BazelApexToolchainVars()))
+
 	files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
 
 	files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index b0d0740..0cb711c 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -104,6 +104,14 @@
 			basename: "constants.bzl",
 		},
 		{
+			dir:      "apex_toolchain",
+			basename: GeneratedBuildFileName,
+		},
+		{
+			dir:      "apex_toolchain",
+			basename: "constants.bzl",
+		},
+		{
 			dir:      "metrics",
 			basename: "converted_modules.txt",
 		},
diff --git a/bp2build/linker_config_conversion_test.go b/bp2build/linker_config_conversion_test.go
new file mode 100644
index 0000000..4662af4
--- /dev/null
+++ b/bp2build/linker_config_conversion_test.go
@@ -0,0 +1,59 @@
+// 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 (
+	"fmt"
+	"testing"
+
+	"android/soong/linkerconfig"
+)
+
+func runLinkerConfigTestCase(t *testing.T, tc bp2buildTestCase) {
+	t.Helper()
+	(&tc).moduleTypeUnderTest = "linker_config"
+	(&tc).moduleTypeUnderTestFactory = linkerconfig.LinkerConfigFactory
+	runBp2BuildTestCaseSimple(t, tc)
+}
+
+func TestLinkerConfigConvertsSrc(t *testing.T) {
+	runLinkerConfigTestCase(t,
+		bp2buildTestCase{
+			blueprint: `
+linker_config {
+	name: "foo",
+	src: "a.json",
+}
+`,
+			expectedBazelTargets: []string{makeBazelTarget("linker_config", "foo", attrNameToString{
+				"src": `"a.json"`,
+			})},
+		})
+
+}
+
+func TestLinkerConfigNoSrc(t *testing.T) {
+	runLinkerConfigTestCase(t,
+		bp2buildTestCase{
+			blueprint: `
+linker_config {
+	name: "foo",
+}
+`,
+			expectedBazelTargets: []string{},
+			expectedErr:          fmt.Errorf("Android.bp:2:1: module \"foo\": src: empty src is not supported"),
+		})
+
+}
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index c5075e5..78e7b0e 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -22,7 +22,7 @@
 	children map[string]*node
 }
 
-// Ensures that the a node for the given path exists in the tree and returns it.
+// Ensures that the node for the given path exists in the tree and returns it.
 func ensureNodeExists(root *node, path string) *node {
 	if path == "" {
 		return root
@@ -126,11 +126,11 @@
 	buildFilesMap := readdirToMap(shared.JoinPath(topdir, buildFilesDir))
 
 	allEntries := make(map[string]bool)
-	for n, _ := range srcDirMap {
+	for n := range srcDirMap {
 		allEntries[n] = true
 	}
 
-	for n, _ := range buildFilesMap {
+	for n := range buildFilesMap {
 		allEntries[n] = true
 	}
 
@@ -140,7 +140,7 @@
 		os.Exit(1)
 	}
 
-	for f, _ := range allEntries {
+	for f := range allEntries {
 		if f[0] == '.' {
 			continue // Ignore dotfiles
 		}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 14b2d84..5d2533f 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"io"
+	"path/filepath"
 	"strings"
 
 	"android/soong/android"
@@ -154,6 +155,9 @@
 	srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
 
 	for _, src := range srcs {
+		if strings.ContainsRune(filepath.Base(src.String()), '_') {
+			ctx.ModuleErrorf("invalid character '_' in source name")
+		}
 		obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
 
 		ctx.Build(pctx, android.BuildParams{
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index 51fbc15..6e39096 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -30,8 +30,9 @@
 	cc.PrepareForTestWithCcDefaultModules,
 	android.FixtureMergeMockFs(
 		map[string][]byte{
-			"bpf.c":       nil,
-			"BpfTest.cpp": nil,
+			"bpf.c":              nil,
+			"bpf_invalid_name.c": nil,
+			"BpfTest.cpp":        nil,
 		},
 	),
 	PrepareForTestWithBpf,
@@ -58,3 +59,15 @@
 	// value is not available for testing from this package.
 	// TODO(jungjw): Add a check for data or move this test to the cc package.
 }
+
+func TestBpfSourceName(t *testing.T) {
+	bp := `
+		bpf {
+			name: "bpf_invalid_name.o",
+			srcs: ["bpf_invalid_name.c"],
+		}
+	`
+	prepareForBpfTest.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+		`\QAndroid.bp:2:3: module "bpf_invalid_name.o" variant "android_common": invalid character '_' in source name\E`)).
+		RunTestWithBp(t, bp)
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index fa30d09..6cd6733 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -20,6 +20,7 @@
 
 	"android/soong/android"
 	"android/soong/bazel"
+	"android/soong/cc/config"
 
 	"github.com/google/blueprint"
 
@@ -156,7 +157,7 @@
 	attrs := staticOrSharedAttributes{}
 
 	setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
-		attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag))
+		attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag))
 		attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
 		attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
 
@@ -326,16 +327,39 @@
 	return strings.HasPrefix(flag, "-std=")
 }
 
-func parseCommandLineFlags(soongFlags []string, filterOut filterOutFn) []string {
+func filterOutClangUnknownCflags(flag string) bool {
+	for _, f := range config.ClangUnknownCflags {
+		if f == flag {
+			return true
+		}
+	}
+	return false
+}
+
+func parseCommandLineFlags(soongFlags []string, noCoptsTokenization bool, filterOut ...filterOutFn) []string {
 	var result []string
 	for _, flag := range soongFlags {
-		if filterOut != nil && filterOut(flag) {
+		skipFlag := false
+		for _, filter := range filterOut {
+			if filter != nil && filter(flag) {
+				skipFlag = true
+			}
+		}
+		if skipFlag {
 			continue
 		}
 		// Soong's cflags can contain spaces, like `-include header.h`. For
 		// Bazel's copts, split them up to be compatible with the
 		// no_copts_tokenization feature.
-		result = append(result, strings.Split(flag, " ")...)
+		if noCoptsTokenization {
+			result = append(result, strings.Split(flag, " ")...)
+		} else {
+			// Soong's Version Script and Dynamic List Properties are added as flags
+			// to Bazel's linkopts using "($location label)" syntax.
+			// Splitting on spaces would separate this into two different flags
+			// "($ location" and "label)"
+			result = append(result, flag)
+		}
 	}
 	return result
 }
@@ -362,10 +386,10 @@
 	// overridden. In Bazel we always allow overriding, via flags; however, this can cause
 	// incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other
 	// cases.
-	ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag))
-	ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, nil))
-	ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, nil))
-	ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, nil))
+	ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag, filterOutClangUnknownCflags))
+	ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, true, nil))
+	ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, true, filterOutClangUnknownCflags))
+	ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, true, filterOutClangUnknownCflags))
 	ca.rtti.SetSelectValue(axis, config, props.Rtti)
 }
 
@@ -721,7 +745,7 @@
 		linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--dynamic-list,$(location %s)", label.Label))
 	}
 
-	la.linkopts.SetSelectValue(axis, config, linkerFlags)
+	la.linkopts.SetSelectValue(axis, config, parseCommandLineFlags(linkerFlags, false, filterOutClangUnknownCflags))
 	la.useLibcrt.SetSelectValue(axis, config, props.libCrt())
 
 	if axis == bazel.NoConfigAxis {
diff --git a/cc/library.go b/cc/library.go
index bd6ccb5..ff485cf 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1616,14 +1616,18 @@
 
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
 	if library.sabi.shouldCreateSourceAbiDump() {
-		var vndkVersion string
-
+		var version string
 		if ctx.useVndk() {
 			// For modules linking against vndk, follow its vndk version
-			vndkVersion = ctx.Module().(*Module).VndkVersion()
+			version = ctx.Module().(*Module).VndkVersion()
 		} else {
-			// Regard the other modules as PLATFORM_VNDK_VERSION
-			vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
+			// After sdk finalizatoin, the ABI of the latest API level must be consistent with the source code
+			// so the chosen reference dump is the PLATFORM_SDK_VERSION.
+			if ctx.Config().PlatformSdkFinal() {
+				version = ctx.Config().PlatformSdkVersion().String()
+			} else {
+				version = "current"
+			}
 		}
 
 		exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
@@ -1642,7 +1646,7 @@
 
 		addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
 
-		refAbiDumpFile := getRefAbiDumpFile(ctx, vndkVersion, fileName)
+		refAbiDumpFile := getRefAbiDumpFile(ctx, version, fileName)
 		if refAbiDumpFile != nil {
 			library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
 				refAbiDumpFile, fileName, exportedHeaderFlags,
diff --git a/cc/testing.go b/cc/testing.go
index 6b858d5..d70ec9b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -194,7 +194,6 @@
 			native_coverage: false,
 			system_shared_libs: [],
 			stl: "none",
-			notice: "custom_notice",
 		}
 		cc_library {
 			name: "libprofile-clang-extras",
@@ -205,7 +204,6 @@
 			native_coverage: false,
 			system_shared_libs: [],
 			stl: "none",
-			notice: "custom_notice",
 		}
 		cc_library {
 			name: "libprofile-extras_ndk",
@@ -214,7 +212,6 @@
 			native_coverage: false,
 			system_shared_libs: [],
 			stl: "none",
-			notice: "custom_notice",
 			sdk_version: "current",
 		}
 		cc_library {
@@ -224,7 +221,6 @@
 			native_coverage: false,
 			system_shared_libs: [],
 			stl: "none",
-			notice: "custom_notice",
 			sdk_version: "current",
 		}
 
diff --git a/cc/vndk.go b/cc/vndk.go
index bf6148b..4cd4d42 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -671,12 +671,8 @@
 	snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
 
 	configsDir := filepath.Join(snapshotArchDir, "configs")
-	noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
 	includeDir := filepath.Join(snapshotArchDir, "include")
 
-	// set of notice files copied.
-	noticeBuilt := make(map[string]bool)
-
 	// paths of VNDK modules for GPL license checking
 	modulePaths := make(map[string]string)
 
@@ -762,16 +758,6 @@
 		moduleNames[stem] = ctx.ModuleName(m)
 		modulePaths[stem] = ctx.ModuleDir(m)
 
-		if len(m.NoticeFiles()) > 0 {
-			noticeName := stem + ".txt"
-			// skip already copied notice file
-			if _, ok := noticeBuilt[noticeName]; !ok {
-				noticeBuilt[noticeName] = true
-				snapshotOutputs = append(snapshotOutputs, combineNoticesRule(
-					ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName)))
-			}
-		}
-
 		if ctx.Config().VndkSnapshotBuildArtifacts() {
 			headers = append(headers, m.SnapshotHeaders()...)
 		}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index c583a49..53422cd 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -220,7 +220,7 @@
 // doChosenActivity runs Soong for a specific activity, like bp2build, queryview
 // or the actual Soong build for the build.ninja file. Returns the top level
 // output file of the specific activity.
-func doChosenActivity(configuration android.Config, extraNinjaDeps []string, logDir string) string {
+func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string, logDir string) string {
 	mixedModeBuild := configuration.BazelContext.BazelEnabled()
 	generateBazelWorkspace := bp2buildMarker != ""
 	generateQueryView := bazelQueryViewDir != ""
@@ -236,7 +236,6 @@
 
 	blueprintArgs := cmdlineArgs
 
-	ctx := newContext(configuration)
 	if mixedModeBuild {
 		runMixedModeBuild(configuration, ctx, extraNinjaDeps)
 	} else {
@@ -284,7 +283,6 @@
 		}
 	}
 
-	writeMetrics(configuration, *ctx.EventHandler, logDir)
 	return cmdlineArgs.OutFile
 }
 
@@ -344,7 +342,13 @@
 	// change between every CI build, so tracking it would require re-running Soong for every build.
 	logDir := availableEnv["LOG_DIR"]
 
-	finalOutputFile := doChosenActivity(configuration, extraNinjaDeps, logDir)
+	ctx := newContext(configuration)
+	ctx.EventHandler.Begin("soong_build")
+
+	finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps, logDir)
+
+	ctx.EventHandler.End("soong_build")
+	writeMetrics(configuration, *ctx.EventHandler, logDir)
 
 	writeUsedEnvironmentFile(configuration, finalOutputFile)
 }
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 1a87b30..2474cbc 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -106,21 +106,21 @@
 	// A brief description of what the fuzzed code does.
 	Description string `json:"description,omitempty"`
 	// Can this code be triggered remotely or only locally.
-	Remotely_accessible bool `json:"remotely_accessible,omitempty"`
+	Remotely_accessible *bool `json:"remotely_accessible,omitempty"`
 	// Is the fuzzed code host only, i.e. test frameworks or support utilities.
-	Host_only bool `json:"host_only,omitempty"`
+	Host_only *bool `json:"host_only,omitempty"`
 	// Can third party/untrusted apps supply data to fuzzed code.
-	Untrusted_data bool `json:"untrusted_data,omitempty"`
+	Untrusted_data *bool `json:"untrusted_data,omitempty"`
 	// Is the code being fuzzed in a privileged, constrained or any other
 	// context from:
 	// https://source.android.com/security/overview/updates-resources#context_types.
 	Privilege_level PrivilegedLevel `json:"privilege_level,omitempty"`
 	// Can the fuzzed code isolated or can be called by multiple users/processes.
-	Isolated bool `json:"users_isolation,omitempty"`
+	Isolated *bool `json:"users_isolation,omitempty"`
 	// When code was relaeased or will be released.
 	Production_date string `json:"production_date,omitempty"`
 	// Prevents critical service functionality like phone calls, bluetooth, etc.
-	Critical bool `json:"critical,omitempty"`
+	Critical *bool `json:"critical,omitempty"`
 	// Specify whether to enable continuous fuzzing on devices. Defaults to true.
 	Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
 	// Specify whether to enable continuous fuzzing on host. Defaults to true.
diff --git a/java/Android.bp b/java/Android.bp
index e25accf..9df4ab4 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -76,6 +76,7 @@
         "tradefed.go",
     ],
     testSrcs: [
+        "aar_test.go",
         "androidmk_test.go",
         "app_import_test.go",
         "app_set_test.go",
diff --git a/java/aar.go b/java/aar.go
index cf84309..5c87b20 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -570,12 +570,24 @@
 
 	a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
 	a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
+
+	prebuiltJniPackages := android.Paths{}
+	ctx.VisitDirectDeps(func(module android.Module) {
+		if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+			prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
+		}
+	})
+	if len(prebuiltJniPackages) > 0 {
+		ctx.SetProvider(JniPackageProvider, JniPackageInfo{
+			JniPackages: prebuiltJniPackages,
+		})
+	}
 }
 
 // android_library builds and links sources into a `.jar` file for the device along with Android resources.
 //
 // An android_library has a single variant that produces a `.jar` file containing `.class` files that were
-// compiled against the device bootclasspath, along with a `package-res.apk` file containing  Android resources compiled
+// compiled against the device bootclasspath, along with a `package-res.apk` file containing Android resources compiled
 // with aapt2.  This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
 // an android_app module.
 func AndroidLibraryFactory() android.Module {
@@ -619,6 +631,10 @@
 	Libs []string
 	// If set to true, run Jetifier against .aar file. Defaults to false.
 	Jetifier *bool
+	// If true, extract JNI libs from AAR archive. These libs will be accessible to android_app modules and
+	// will be passed transitively through android_libraries to an android_app.
+	//TODO(b/241138093) evaluate whether we can have this flag default to true for Bazel conversion
+	Extract_jni *bool
 }
 
 type AARImport struct {
@@ -643,7 +659,8 @@
 
 	hideApexVariantFromMake bool
 
-	aarPath android.Path
+	aarPath     android.Path
+	jniPackages android.Paths
 
 	sdkVersion    android.SdkSpec
 	minSdkVersion android.SdkSpec
@@ -751,6 +768,28 @@
 	ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
 }
 
+type JniPackageInfo struct {
+	// List of zip files containing JNI libraries
+	// Zip files should have directory structure jni/<arch>/*.so
+	JniPackages android.Paths
+}
+
+var JniPackageProvider = blueprint.NewProvider(JniPackageInfo{})
+
+// Unzip an AAR and extract the JNI libs for $archString.
+var extractJNI = pctx.AndroidStaticRule("extractJNI",
+	blueprint.RuleParams{
+		Command: `rm -rf $out $outDir && touch $out && ` +
+			`unzip -qoDD -d $outDir $in "jni/${archString}/*" && ` +
+			`jni_files=$$(find $outDir/jni -type f) && ` +
+			// print error message if there are no JNI libs for this arch
+			`[ -n "$$jni_files" ] || (echo "ERROR: no JNI libs found for arch ${archString}" && exit 1) && ` +
+			`${config.SoongZipCmd} -o $out -P 'lib/${archString}' ` +
+			`-C $outDir/jni/${archString} $$(echo $$jni_files | xargs -n1 printf " -f %s")`,
+		CommandDeps: []string{"${config.SoongZipCmd}"},
+	},
+	"outDir", "archString")
+
 // Unzip an AAR into its constituent files and directories.  Any files in Outputs that don't exist in the AAR will be
 // touched to create an empty file. The res directory is not extracted, as it will be extracted in its own rule.
 var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
@@ -858,6 +897,31 @@
 		ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
 		ImplementationJars:             android.PathsIfNonNil(a.classpathFile),
 	})
+
+	if proptools.Bool(a.properties.Extract_jni) {
+		for _, t := range ctx.MultiTargets() {
+			arch := t.Arch.Abi[0]
+			path := android.PathForModuleOut(ctx, arch+"_jni.zip")
+			a.jniPackages = append(a.jniPackages, path)
+
+			outDir := android.PathForModuleOut(ctx, "aarForJni")
+			aarPath := android.PathForModuleSrc(ctx, a.properties.Aars[0])
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        extractJNI,
+				Input:       aarPath,
+				Outputs:     android.WritablePaths{path},
+				Description: "extract JNI from AAR",
+				Args: map[string]string{
+					"outDir":     outDir.String(),
+					"archString": arch,
+				},
+			})
+		}
+
+		ctx.SetProvider(JniPackageProvider, JniPackageInfo{
+			JniPackages: a.jniPackages,
+		})
+	}
 }
 
 func (a *AARImport) HeaderJars() android.Paths {
@@ -893,7 +957,7 @@
 	return nil
 }
 
-var _ android.PrebuiltInterface = (*Import)(nil)
+var _ android.PrebuiltInterface = (*AARImport)(nil)
 
 // android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
 //
@@ -906,6 +970,6 @@
 
 	android.InitPrebuiltModule(module, &module.properties.Aars)
 	android.InitApexModule(module)
-	InitJavaModule(module, android.DeviceSupported)
+	InitJavaModuleMultiTargets(module, android.DeviceSupported)
 	return module
 }
diff --git a/java/aar_test.go b/java/aar_test.go
new file mode 100644
index 0000000..8afa039
--- /dev/null
+++ b/java/aar_test.go
@@ -0,0 +1,83 @@
+// 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 java
+
+import (
+	"android/soong/android"
+	"testing"
+)
+
+func TestAarImportProducesJniPackages(t *testing.T) {
+	ctx := android.GroupFixturePreparers(
+		PrepareForTestWithJavaDefaultModules,
+	).RunTestWithBp(t, `
+		android_library_import {
+			name: "aar-no-jni",
+			aars: ["aary.aar"],
+		}
+		android_library_import {
+			name: "aar-jni",
+			aars: ["aary.aar"],
+			extract_jni: true,
+		}`)
+
+	testCases := []struct {
+		name       string
+		hasPackage bool
+	}{
+		{
+			name:       "aar-no-jni",
+			hasPackage: false,
+		},
+		{
+			name:       "aar-jni",
+			hasPackage: true,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			appMod := ctx.Module(tc.name, "android_common")
+			appTestMod := ctx.ModuleForTests(tc.name, "android_common")
+
+			info, ok := ctx.ModuleProvider(appMod, JniPackageProvider).(JniPackageInfo)
+			if !ok {
+				t.Errorf("expected android_library_import to have JniPackageProvider")
+			}
+
+			if !tc.hasPackage {
+				if len(info.JniPackages) != 0 {
+					t.Errorf("expected JniPackages to be empty, but got %v", info.JniPackages)
+				}
+				outputFile := "arm64-v8a_jni.zip"
+				jniOutputLibZip := appTestMod.MaybeOutput(outputFile)
+				if jniOutputLibZip.Rule != nil {
+					t.Errorf("did not expect an output file, but found %v", outputFile)
+				}
+				return
+			}
+
+			if len(info.JniPackages) != 1 {
+				t.Errorf("expected a single JniPackage, but got %v", info.JniPackages)
+			}
+
+			outputFile := info.JniPackages[0].String()
+			jniOutputLibZip := appTestMod.Output(outputFile)
+			if jniOutputLibZip.Rule == nil {
+				t.Errorf("did not find output file %v", outputFile)
+			}
+		})
+	}
+}
diff --git a/java/app.go b/java/app.go
index 23a9816..afef334 100755
--- a/java/app.go
+++ b/java/app.go
@@ -472,14 +472,14 @@
 	return a.dexJarFile.PathOrNil()
 }
 
-func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
+func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath {
 	var jniJarFile android.WritablePath
-	if len(jniLibs) > 0 {
+	if len(jniLibs) > 0 || len(prebuiltJniPackages) > 0 {
 		a.jniLibs = jniLibs
 		if a.shouldEmbedJnis(ctx) {
 			jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
 			a.installPathForJNISymbols = a.installPath(ctx)
-			TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
+			TransformJniLibsToJar(ctx, jniJarFile, jniLibs, prebuiltJniPackages, a.useEmbeddedNativeLibs(ctx))
 			for _, jni := range jniLibs {
 				if jni.coverageFile.Valid() {
 					// Only collect coverage for the first target arch if this is a multilib target.
@@ -623,8 +623,8 @@
 
 	dexJarFile := a.dexBuildActions(ctx)
 
-	jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
-	jniJarFile := a.jniBuildActions(jniLibs, ctx)
+	jniLibs, prebuiltJniPackages, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
+	jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
 
 	if ctx.Failed() {
 		return
@@ -724,9 +724,10 @@
 
 func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
 	shouldCollectRecursiveNativeDeps bool,
-	checkNativeSdkVersion bool) ([]jniLib, []Certificate) {
+	checkNativeSdkVersion bool) ([]jniLib, android.Paths, []Certificate) {
 
 	var jniLibs []jniLib
+	var prebuiltJniPackages android.Paths
 	var certificates []Certificate
 	seenModulePaths := make(map[string]bool)
 
@@ -775,6 +776,10 @@
 			return shouldCollectRecursiveNativeDeps
 		}
 
+		if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+			prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
+		}
+
 		if tag == certificateTag {
 			if dep, ok := module.(*AndroidAppCertificate); ok {
 				certificates = append(certificates, dep.Certificate)
@@ -786,7 +791,7 @@
 		return false
 	})
 
-	return jniLibs, certificates
+	return jniLibs, prebuiltJniPackages, certificates
 }
 
 func (a *AndroidApp) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
diff --git a/java/app_builder.go b/java/app_builder.go
index 4a18dca..4348644 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -218,8 +218,14 @@
 	})
 }
 
-func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.WritablePath,
-	jniLibs []jniLib, uncompressJNI bool) {
+const jniJarOutputPathString = "jniJarOutput.zip"
+
+func TransformJniLibsToJar(
+	ctx android.ModuleContext,
+	outputFile android.WritablePath,
+	jniLibs []jniLib,
+	prebuiltJniPackages android.Paths,
+	uncompressJNI bool) {
 
 	var deps android.Paths
 	jarArgs := []string{
@@ -245,13 +251,20 @@
 		rule = zipRE
 		args["implicits"] = strings.Join(deps.Strings(), ",")
 	}
+	jniJarPath := android.PathForModuleOut(ctx, jniJarOutputPathString)
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        rule,
 		Description: "zip jni libs",
-		Output:      outputFile,
+		Output:      jniJarPath,
 		Implicits:   deps,
 		Args:        args,
 	})
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        mergeAssetsRule,
+		Description: "merge prebuilt JNI packages",
+		Inputs:      append(prebuiltJniPackages, jniJarPath),
+		Output:      outputFile,
+	})
 }
 
 func targetToJniDir(target android.Target) string {
diff --git a/java/app_import.go b/java/app_import.go
index b017eca..9d199d6 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -256,7 +256,7 @@
 		ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
 	}
 
-	_, certificates := collectAppDeps(ctx, a, false, false)
+	_, _, certificates := collectAppDeps(ctx, a, false, false)
 
 	// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
 	// TODO: LOCAL_PACKAGE_SPLITS
diff --git a/java/app_test.go b/java/app_test.go
index c4ac4df..bb44803 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1218,7 +1218,7 @@
 	for _, test := range testCases {
 		t.Run(test.name, func(t *testing.T) {
 			app := ctx.ModuleForTests(test.name, "android_common")
-			jniLibZip := app.Output("jnilibs.zip")
+			jniLibZip := app.Output(jniJarOutputPathString)
 			var abis []string
 			args := strings.Fields(jniLibZip.Args["jarArgs"])
 			for i := 0; i < len(args); i++ {
@@ -1351,7 +1351,7 @@
 	for _, test := range testCases {
 		t.Run(test.name, func(t *testing.T) {
 			app := ctx.ModuleForTests(test.name, "android_common")
-			jniLibZip := app.MaybeOutput("jnilibs.zip")
+			jniLibZip := app.MaybeOutput(jniJarOutputPathString)
 			if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
 				t.Errorf("expected jni packaged %v, got %v", w, g)
 			}
@@ -1442,7 +1442,7 @@
 		t.Run(test.name, func(t *testing.T) {
 			app := ctx.ModuleForTests(test.name, "android_common")
 
-			jniLibZip := app.MaybeOutput("jnilibs.zip")
+			jniLibZip := app.MaybeOutput(jniJarOutputPathString)
 			if len(jniLibZip.Implicits) != 1 {
 				t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
 			}
@@ -2425,7 +2425,7 @@
 	for _, test := range testCases {
 		t.Run(test.name, func(t *testing.T) {
 			app := ctx.ModuleForTests(test.name, "android_common")
-			jniLibZip := app.Output("jnilibs.zip")
+			jniLibZip := app.Output(jniJarOutputPathString)
 			var jnis []string
 			args := strings.Fields(jniLibZip.Args["jarArgs"])
 			for i := 0; i < len(args); i++ {
@@ -3074,3 +3074,89 @@
 	}
 	android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
 }
+
+func TestAppIncludesJniPackages(t *testing.T) {
+	ctx := android.GroupFixturePreparers(
+		PrepareForTestWithJavaDefaultModules,
+	).RunTestWithBp(t, `
+		android_library_import {
+			name: "aary-nodeps",
+			aars: ["aary.aar"],
+			extract_jni: true,
+		}
+
+		android_library {
+			name: "aary-lib",
+			sdk_version: "current",
+			min_sdk_version: "21",
+			static_libs: ["aary-nodeps"],
+		}
+
+		android_app {
+			name: "aary-lib-dep",
+			sdk_version: "current",
+			min_sdk_version: "21",
+			manifest: "AndroidManifest.xml",
+			static_libs: ["aary-lib"],
+			use_embedded_native_libs: true,
+		}
+
+		android_app {
+			name: "aary-import-dep",
+			sdk_version: "current",
+			min_sdk_version: "21",
+			manifest: "AndroidManifest.xml",
+			static_libs: ["aary-nodeps"],
+			use_embedded_native_libs: true,
+		}
+
+		android_app {
+			name: "aary-no-use-embedded",
+			sdk_version: "current",
+			min_sdk_version: "21",
+			manifest: "AndroidManifest.xml",
+			static_libs: ["aary-nodeps"],
+		}`)
+
+	testCases := []struct {
+		name       string
+		hasPackage bool
+	}{
+		{
+			name:       "aary-import-dep",
+			hasPackage: true,
+		},
+		{
+			name:       "aary-lib-dep",
+			hasPackage: true,
+		},
+		{
+			name:       "aary-no-use-embedded",
+			hasPackage: false,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			app := ctx.ModuleForTests(tc.name, "android_common")
+
+			outputFile := "jnilibs.zip"
+			jniOutputLibZip := app.MaybeOutput(outputFile)
+			if jniOutputLibZip.Rule == nil && !tc.hasPackage {
+				return
+			}
+
+			jniPackage := "arm64-v8a_jni.zip"
+			inputs := jniOutputLibZip.Inputs
+			foundPackage := false
+			for i := 0; i < len(inputs); i++ {
+				if strings.Contains(inputs[i].String(), jniPackage) {
+					foundPackage = true
+				}
+			}
+			if foundPackage != tc.hasPackage {
+				t.Errorf("expected to find %v in %v inputs; inputs = %v", jniPackage, outputFile, inputs)
+			}
+		})
+	}
+}
diff --git a/java/rro.go b/java/rro.go
index 7952c2c..9c8c53b 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -142,7 +142,7 @@
 	r.aapt.buildActions(ctx, r, nil, nil, aaptLinkFlags...)
 
 	// Sign the built package
-	_, certificates := collectAppDeps(ctx, r, false, false)
+	_, _, certificates := collectAppDeps(ctx, r, false, false)
 	certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
 	signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
 	var lineageFile android.Path
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 8db001f..133f7f7 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -32,6 +32,15 @@
 }
 
 license_kind {
+    name: "BSD-Like-Binary-Only",
+    conditions: [
+        "notice",
+        "by_exception_only",
+        "proprietary",
+    ],
+}
+
+license_kind {
     name: "SPDX-license-identifier-0BSD",
     conditions: ["unencumbered"],
     url: "https://spdx.org/licenses/0BSD",
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index 003b275..412a23b 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -22,6 +22,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/cc"
 	"android/soong/etc"
 )
@@ -36,7 +37,7 @@
 }
 
 func registerLinkerConfigBuildComponent(ctx android.RegistrationContext) {
-	ctx.RegisterModuleType("linker_config", linkerConfigFactory)
+	ctx.RegisterModuleType("linker_config", LinkerConfigFactory)
 }
 
 type linkerConfigProperties struct {
@@ -52,6 +53,7 @@
 
 type linkerConfig struct {
 	android.ModuleBase
+	android.BazelModuleBase
 	properties linkerConfigProperties
 
 	outputFilePath android.OutputPath
@@ -100,6 +102,28 @@
 	ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath)
 }
 
+type linkerConfigAttributes struct {
+	Src bazel.LabelAttribute
+}
+
+func (l *linkerConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	if l.properties.Src == nil {
+		ctx.PropertyErrorf("src", "empty src is not supported")
+		return
+	}
+	src := android.BazelLabelForModuleSrcSingle(ctx, *l.properties.Src)
+	targetModuleProperties := bazel.BazelTargetModuleProperties{
+		Rule_class:        "linker_config",
+		Bzl_load_location: "//build/bazel/rules:linker_config.bzl",
+	}
+	ctx.CreateBazelTargetModule(
+		targetModuleProperties,
+		android.CommonAttributes{Name: l.Name()},
+		&linkerConfigAttributes{
+			Src: bazel.LabelAttribute{Value: &src},
+		})
+}
+
 func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder,
 	input android.Path, otherModules []android.Module, output android.OutputPath) {
 
@@ -141,10 +165,11 @@
 // linker_config generates protobuf file from json file. This protobuf file will be used from
 // linkerconfig while generating ld.config.txt. Format of this file can be found from
 // https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
-func linkerConfigFactory() android.Module {
+func LinkerConfigFactory() android.Module {
 	m := &linkerConfig{}
 	m.AddProperties(&m.properties)
 	android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibFirst)
+	android.InitBazelModule(m)
 	return m
 }
 
diff --git a/rust/OWNERS b/rust/OWNERS
index ddaebc5..b595511 100644
--- a/rust/OWNERS
+++ b/rust/OWNERS
@@ -1,5 +1,2 @@
 # Additional owner/reviewers for rust rules, including parent directory owners.
 per-file * = chiw@google.com, chriswailes@google.com, ivanlozano@google.com, jeffv@google.com, mmaurer@google.com, srhines@google.com
-
-# Limited owners/reviewers of the allowed list.
-per-file allowed_list.go = chiw@google.com, chriswailes@google.com, ivanlozano@google.com, jeffv@google.com, mmaurer@google.com, srhines@google.com
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index ba40cb0..be73d69 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -16,7 +16,6 @@
         "global.go",
         "lints.go",
         "toolchain.go",
-        "allowed_list.go",
         "darwin_host.go",
         "x86_linux_bionic_host.go",
         "x86_linux_host.go",
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
deleted file mode 100644
index 9129b0e..0000000
--- a/rust/config/allowed_list.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package config
-
-var (
-	// When adding a new path below, add a rustfmt.toml file at the root of
-	// the repository and enable the rustfmt repo hook. See aosp/1458238
-	// for an example.
-	// TODO(b/160223496): enable rustfmt globally.
-	RustAllowedPaths = []string{
-		"device/google/cuttlefish",
-		"external/adhd",
-		"external/boringssl",
-		"external/crosvm",
-		"external/libchromeos-rs",
-		"external/minijail",
-		"external/open-dice",
-		"external/rust",
-		"external/selinux/libselinux",
-		"external/uwb",
-		"external/vm_tools/p9",
-		"frameworks/native/libs/binder/rust",
-		"frameworks/proto_logging/stats",
-		"hardware/interfaces/security",
-		"hardware/interfaces/uwb",
-		"packages/modules/Bluetooth",
-		"packages/modules/DnsResolver",
-		"packages/modules/Uwb",
-		"packages/modules/Virtualization",
-		"platform_testing/tests/codecoverage/native/rust",
-		"prebuilts/rust",
-		"system/core/debuggerd/rust",
-		"system/core/libstats/pull_rust",
-		"system/core/trusty/libtrusty-rs",
-		"system/core/trusty/keymint",
-		"system/extras/profcollectd",
-		"system/extras/simpleperf",
-		"system/hardware/interfaces/keystore2",
-		"system/keymint",
-		"system/librustutils",
-		"system/logging/liblog",
-		"system/logging/rust",
-		"system/nfc",
-		"system/security",
-		"system/tools/aidl",
-		"tools/security/fuzzing/example_rust_fuzzer",
-		"tools/security/fuzzing/orphans",
-		"tools/security/remote_provisioning/cert_validator",
-		"tools/vendor",
-		"vendor/",
-	}
-
-	DownstreamRustAllowedPaths = []string{
-		// Add downstream allowed Rust paths here.
-	}
-
-	RustModuleTypes = []string{
-		// Don't add rust_bindgen or rust_protobuf as these are code generation modules
-		// and can be expected to be in paths without Rust code.
-		"rust_benchmark",
-		"rust_benchmark_host",
-		"rust_binary",
-		"rust_binary_host",
-		"rust_library",
-		"rust_library_dylib",
-		"rust_library_rlib",
-		"rust_ffi",
-		"rust_ffi_shared",
-		"rust_ffi_static",
-		"rust_fuzz",
-		"rust_library_host",
-		"rust_library_host_dylib",
-		"rust_library_host_rlib",
-		"rust_ffi_host",
-		"rust_ffi_host_shared",
-		"rust_ffi_host_static",
-		"rust_proc_macro",
-		"rust_test",
-		"rust_test_host",
-	}
-)
diff --git a/rust/rust.go b/rust/rust.go
index d5d4929..4d9fe4c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -33,13 +33,6 @@
 var pctx = android.NewPackageContext("android/soong/rust")
 
 func init() {
-	// Only allow rust modules to be defined for certain projects
-
-	android.AddNeverAllowRules(
-		android.NeverAllow().
-			NotIn(append(config.RustAllowedPaths, config.DownstreamRustAllowedPaths...)...).
-			ModuleType(config.RustModuleTypes...))
-
 	android.RegisterModuleType("rust_defaults", defaultsFactory)
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
diff --git a/ui/build/build.go b/ui/build/build.go
index ec42b70..5b80b4d 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -183,8 +183,8 @@
 	}
 }
 
-// Build the tree. The 'what' argument can be used to chose which components of
-// the build to run, via checking various bitmasks.
+// Build the tree. Various flags in `config` govern which components of
+// the build to run.
 func Build(ctx Context, config Config) {
 	ctx.Verboseln("Starting build with args:", config.Arguments())
 	ctx.Verboseln("Environment:", config.Environment().Environ())
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 8992b4f..cfcf990 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -544,7 +544,7 @@
 	buf, err := os.ReadFile(soongBuildMetricsFile)
 	if errors.Is(err, fs.ErrNotExist) {
 		// Soong may not have run during this invocation
-          ctx.Verbosef("Failed to read metrics file, %s: %s", soongBuildMetricsFile, err)
+		ctx.Verbosef("Failed to read metrics file, %s: %s", soongBuildMetricsFile, err)
 		return nil
 	} else if err != nil {
 		ctx.Fatalf("Failed to load %s: %s", soongBuildMetricsFile, err)