Merge "Compare generated cache file with existing cache file" into main
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index ee63bb4..69bcd2e 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -434,7 +434,6 @@
 		"external/bazelbuild-rules_java":/* recursive = */ true,
 		"external/bazelbuild-rules_license":/* recursive = */ true,
 		"external/bazelbuild-rules_go":/* recursive = */ true,
-		"external/bazelbuild-rules_python":/* recursive = */ true,
 		"external/bazelbuild-kotlin-rules":/* recursive = */ true,
 		"external/bazel-skylib":/* recursive = */ true,
 		"external/protobuf":/* recursive = */ false,
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 8956a18..7568543 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -124,6 +124,7 @@
 		labels.Includes = []bazel.Label{}
 		return labels
 	}
+	modules = FirstUniqueStrings(modules)
 	for _, module := range modules {
 		bpText := module
 		if m := SrcIsModule(module); m == "" {
diff --git a/android/config.go b/android/config.go
index 30be7d6..72ff224 100644
--- a/android/config.go
+++ b/android/config.go
@@ -170,6 +170,19 @@
 	return c.config.TestProductVariables != nil
 }
 
+// DisableHiddenApiChecks returns true if hiddenapi checks have been disabled.
+// For 'eng' target variant hiddenapi checks are disabled by default for performance optimisation,
+// but can be enabled by setting environment variable ENABLE_HIDDENAPI_FLAGS=true.
+// For other target variants hiddenapi check are enabled by default but can be disabled by
+// setting environment variable UNSAFE_DISABLE_HIDDENAPI_FLAGS=true.
+// If both ENABLE_HIDDENAPI_FLAGS=true and UNSAFE_DISABLE_HIDDENAPI_FLAGS=true, then
+// ENABLE_HIDDENAPI_FLAGS=true will be triggered and hiddenapi checks will be considered enabled.
+func (c Config) DisableHiddenApiChecks() bool {
+	return !c.IsEnvTrue("ENABLE_HIDDENAPI_FLAGS") &&
+		(c.IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") ||
+			Bool(c.productVariables.Eng))
+}
+
 // MaxPageSizeSupported returns the max page size supported by the device. This
 // value will define the ELF segment alignment for binaries (executables and
 // shared libraries).
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ed78033..9dba08e 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6794,6 +6794,10 @@
 			public_key: "testkey.avbpubkey",
 			private_key: "testkey.pem",
 		}
+		override_apex {
+			name: "myoverrideapex",
+			base: "bar",
+		}
 	`)
 
 	fooManifestRule := result.ModuleForTests("foo", "android_common_foo_image").Rule("apexManifestRule")
@@ -6810,6 +6814,12 @@
 	if barActualDefaultVersion != barExpectedDefaultVersion {
 		t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
 	}
+
+	overrideBarManifestRule := result.ModuleForTests("bar", "android_common_myoverrideapex_bar_image").Rule("apexManifestRule")
+	overrideBarActualDefaultVersion := overrideBarManifestRule.Args["default_version"]
+	if overrideBarActualDefaultVersion != barExpectedDefaultVersion {
+		t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
+	}
 }
 
 func TestApexAvailable_ApexAvailableName(t *testing.T) {
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 8084a5d..03e9cd0 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1003,6 +1003,38 @@
 	})
 }
 
+func TestCcLibraryStaticGeneratedHeadersMultipleExports(t *testing.T) {
+	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+		Blueprint: soongCcLibraryStaticPreamble + `
+genrule {
+    name: "generated_hdr",
+    cmd: "nothing to see here",
+    export_include_dirs: ["foo", "bar"],
+    bazel_module: { bp2build_available: false },
+}
+
+genrule {
+    name: "export_generated_hdr",
+    cmd: "nothing to see here",
+    export_include_dirs: ["a", "b"],
+    bazel_module: { bp2build_available: false },
+}
+
+cc_library_static {
+    name: "foo_static",
+    generated_headers: ["generated_hdr", "export_generated_hdr"],
+    export_generated_headers: ["export_generated_hdr"],
+    include_build_directory: false,
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
+				"deps":                `[":export_generated_hdr__header_library"]`,
+				"implementation_deps": `[":generated_hdr__header_library"]`,
+			}),
+		},
+	})
+}
+
 // generated_headers has "variant_prepend" tag. In bp2build output,
 // variant info(select) should go before general info.
 func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) {
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 5cf4fb2..5a73969 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"path/filepath"
 	"testing"
 
 	"android/soong/android"
@@ -695,3 +696,79 @@
 			})
 	})
 }
+
+func TestGenruleWithExportIncludeDirs(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+		hod        android.HostOrDeviceSupported
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
+		},
+		{
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
+			hod:        android.DeviceSupported,
+		},
+		{
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
+			hod:        android.DeviceSupported,
+		},
+		{
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+			hod:        android.HostSupported,
+		},
+	}
+
+	dir := "baz"
+
+	bp := `%s {
+    name: "foo",
+    out: ["foo.out.h"],
+    srcs: ["foo.in"],
+    cmd: "cp $(in) $(out)",
+    export_include_dirs: ["foo", "bar", "."],
+    bazel_module: { bp2build_available: true },
+}`
+
+	for _, tc := range testCases {
+		moduleAttrs := AttrNameToString{
+			"cmd":  `"cp $(SRCS) $(OUTS)"`,
+			"outs": `["foo.out.h"]`,
+			"srcs": `["foo.in"]`,
+		}
+
+		expectedBazelTargets := []string{
+			makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
+			makeBazelTargetHostOrDevice("cc_library_headers", "foo__header_library", AttrNameToString{
+				"hdrs": `[":foo"]`,
+				"export_includes": `[
+        "foo",
+        "baz/foo",
+        "bar",
+        "baz/bar",
+        ".",
+        "baz",
+    ]`,
+			},
+				tc.hod),
+		}
+
+		t.Run(tc.moduleType, func(t *testing.T) {
+			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				Bp2buildTestCase{
+					ModuleTypeUnderTest:        tc.moduleType,
+					ModuleTypeUnderTestFactory: tc.factory,
+					Filesystem: map[string]string{
+						filepath.Join(dir, "Android.bp"): fmt.Sprintf(bp, tc.moduleType),
+					},
+					Dir:                  dir,
+					ExpectedBazelTargets: expectedBazelTargets,
+				})
+		})
+	}
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 9895a20..9e485d6 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -22,6 +22,7 @@
 	"android/soong/android"
 	"android/soong/bazel"
 	"android/soong/cc/config"
+	"android/soong/genrule"
 
 	"github.com/google/blueprint"
 
@@ -45,6 +46,8 @@
 
 	xsdSrcPartition = "xsd"
 
+	genrulePartition = "genrule"
+
 	hdrPartition = "hdr"
 
 	stubsSuffix = "_stub_libs_current"
@@ -172,8 +175,9 @@
 
 func partitionHeaders(ctx android.BazelConversionPathContext, hdrs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
 	labels := bazel.LabelPartitions{
-		xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(xsdConfigCppTarget)},
-		hdrPartition:    bazel.LabelPartition{Keep_remainder: true},
+		xsdSrcPartition:  bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(xsdConfigCppTarget)},
+		genrulePartition: bazel.LabelPartition{LabelMapper: genrule.GenruleCcHeaderLabelMapper},
+		hdrPartition:     bazel.LabelPartition{Keep_remainder: true},
 	}
 	return bazel.PartitionLabelListAttribute(ctx, &hdrs, labels)
 }
@@ -419,6 +423,10 @@
 	xsdSrcs       bazel.LabelListAttribute
 	exportXsdSrcs bazel.LabelListAttribute
 
+	// genrule headers
+	genruleHeaders       bazel.LabelListAttribute
+	exportGenruleHeaders bazel.LabelListAttribute
+
 	// Lex sources and options
 	lSrcs   bazel.LabelListAttribute
 	llSrcs  bazel.LabelListAttribute
@@ -606,6 +614,9 @@
 	ca.exportXsdSrcs = partitionedHdrs[xsdSrcPartition]
 	ca.xsdSrcs = bazel.FirstUniqueBazelLabelListAttribute(xsdSrcs)
 
+	ca.genruleHeaders = partitionedImplHdrs[genrulePartition]
+	ca.exportGenruleHeaders = partitionedHdrs[genrulePartition]
+
 	ca.srcs = partitionedSrcs[cppSrcPartition]
 	ca.cSrcs = partitionedSrcs[cSrcPartition]
 	ca.asSrcs = partitionedSrcs[asSrcPartition]
@@ -900,6 +911,9 @@
 
 	(&compilerAttrs.srcs).Add(bp2BuildYasm(ctx, module, compilerAttrs))
 
+	(&linkerAttrs).deps.Append(compilerAttrs.exportGenruleHeaders)
+	(&linkerAttrs).implementationDeps.Append(compilerAttrs.genruleHeaders)
+
 	(&linkerAttrs).wholeArchiveDeps.Append(compilerAttrs.exportXsdSrcs)
 	(&linkerAttrs).implementationWholeArchiveDeps.Append(compilerAttrs.xsdSrcs)
 
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index dd612ce..f9b3eac 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -21,6 +21,7 @@
 var VndkMustUseVendorVariantList = []string{
 	"android.hardware.nfc@1.2",
 	"libbinder",
+	"libdumpstateutil",
 	"libcrypto",
 	"libexpat",
 	"libgatekeeper",
diff --git a/cc/coverage.go b/cc/coverage.go
index c0f6973..cbd8a6f 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -48,6 +48,7 @@
 func getGcovProfileLibraryName(ctx ModuleContextIntf) string {
 	// This function should only ever be called for a cc.Module, so the
 	// following statement should always succeed.
+	// LINT.IfChange
 	if ctx.useSdk() {
 		return "libprofile-extras_ndk"
 	} else {
@@ -63,6 +64,7 @@
 	} else {
 		return "libprofile-clang-extras"
 	}
+	// LINT.ThenChange(library.go)
 }
 
 func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps {
diff --git a/cc/library.go b/cc/library.go
index 266fa75..df1dbc5 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -32,6 +32,20 @@
 	"github.com/google/blueprint/proptools"
 )
 
+var (
+	alwaysLinkLibraries = map[string]bool{
+		// Coverage libraries are _always_ added as a whole_static_dep. By converting as these as
+		// alwayslink = True, we can add these as to deps (e.g. as a regular static dep) in Bazel
+		// without any extra complications in cc_shared_library roots to prevent linking the same
+		// library repeatedly.
+		"libprofile-extras_ndk":               true,
+		"libprofile-extras":                   true,
+		"libprofile-clang-extras_ndk":         true,
+		"libprofile-clang-extras_cfi_support": true,
+		"libprofile-clang-extras":             true,
+	}
+)
+
 // LibraryProperties is a collection of properties shared by cc library rules/cc.
 type LibraryProperties struct {
 	// local file name to pass to the linker as -unexported_symbols_list
@@ -435,6 +449,10 @@
 		Bzl_load_location: "//build/bazel/rules/cc:cc_library_shared.bzl",
 	}
 
+	if _, ok := alwaysLinkLibraries[m.Name()]; ok {
+		staticTargetAttrs.Alwayslink = proptools.BoolPtr(true)
+	}
+
 	var tagsForStaticVariant bazel.StringListAttribute
 	if compilerAttrs.stubsSymbolFile == nil && len(compilerAttrs.stubsVersions.Value) == 0 {
 		tagsForStaticVariant = android.ApexAvailableTagsWithoutTestApexes(ctx, m)
@@ -2951,6 +2969,10 @@
 	var attrs interface{}
 	if isStatic {
 		commonAttrs.Deps.Add(baseAttributes.protoDependency)
+		var alwayslink *bool
+		if _, ok := alwaysLinkLibraries[module.Name()]; ok && isStatic {
+			alwayslink = proptools.BoolPtr(true)
+		}
 		attrs = &bazelCcLibraryStaticAttributes{
 			staticOrSharedAttributes: commonAttrs,
 			Rtti:                     compilerAttrs.rtti,
@@ -2964,8 +2986,10 @@
 			Conlyflags: compilerAttrs.conlyFlags,
 			Asflags:    asFlags,
 
-			Features: *features,
+			Alwayslink: alwayslink,
+			Features:   *features,
 		}
+
 	} else {
 		commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
 
@@ -3047,7 +3071,8 @@
 	Conlyflags bazel.StringListAttribute
 	Asflags    bazel.StringListAttribute
 
-	Features bazel.StringListAttribute
+	Alwayslink *bool
+	Features   bazel.StringListAttribute
 }
 
 // TODO(b/199902614): Can this be factored to share with the other Attributes?
diff --git a/cc/rs.go b/cc/rs.go
index 6507259..93acdc7 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -101,11 +101,12 @@
 func rsFlags(ctx ModuleContext, flags Flags, properties *BaseCompilerProperties) Flags {
 	targetApi := String(properties.Renderscript.Target_api)
 	if targetApi == "" && ctx.useSdk() {
-		switch ctx.sdkVersion() {
-		case "current", "system_current", "test_current":
-			// Nothing
-		default:
-			targetApi = android.GetNumericSdkVersion(ctx.sdkVersion())
+		targetApiLevel := android.ApiLevelOrPanic(ctx, ctx.sdkVersion())
+		if targetApiLevel.IsCurrent() || targetApiLevel.IsPreview() {
+			// If the target level is current or preview, leave the 'target-api' unset.
+			// This signals to llvm-rs-cc that the development API should be used.
+		} else {
+			targetApi = targetApiLevel.String()
 		}
 	}
 
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 6c38355..c1ef970 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -56,10 +56,6 @@
 		// higher number of "optimized out" stack variables.
 		// b/112437883.
 		"-instcombine-lower-dbg-declare=0",
-		// TODO(b/159343917): HWASan and GlobalISel don't play nicely, and
-		// GlobalISel is the default at -O0 on aarch64.
-		"--aarch64-enable-global-isel-at-O=-1",
-		"-fast-isel=false",
 		"-hwasan-use-after-scope=1",
 		"-dom-tree-reachability-max-bbs-to-explore=128",
 	}
@@ -675,6 +671,12 @@
 		s.Integer_overflow = nil
 	}
 
+	// TODO(b/254713216): CFI doesn't work for riscv64 yet because LTO doesn't work.
+	if ctx.Arch().ArchType == android.Riscv64 {
+		s.Cfi = nil
+		s.Diag.Cfi = nil
+	}
+
 	// Disable CFI for musl
 	if ctx.toolchain().Musl() {
 		s.Cfi = nil
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 6306c27..69ba1e9 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -994,6 +994,7 @@
 
 	tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
 
+	bazelName := m.Name()
 	if ctx.ModuleType() == "gensrcs" {
 		props := bazel.BazelTargetModuleProperties{
 			Rule_class:        "gensrcs",
@@ -1021,7 +1022,6 @@
 				break
 			}
 		}
-		bazelName := m.Name()
 		for _, out := range outs {
 			if out == bazelName {
 				// This is a workaround to circumvent a Bazel warning where a genrule's
@@ -1046,6 +1046,54 @@
 			Tags: tags,
 		}, attrs)
 	}
+
+	if m.needsCcLibraryHeadersBp2build() {
+		includeDirs := make([]string, len(m.properties.Export_include_dirs)*2)
+		for i, dir := range m.properties.Export_include_dirs {
+			includeDirs[i*2] = dir
+			includeDirs[i*2+1] = filepath.Clean(filepath.Join(ctx.ModuleDir(), dir))
+		}
+		attrs := &ccHeaderLibraryAttrs{
+			Hdrs:            []string{":" + bazelName},
+			Export_includes: includeDirs,
+		}
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "cc_library_headers",
+			Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
+		}
+		ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+			Name: m.Name() + genruleHeaderLibrarySuffix,
+			Tags: tags,
+		}, attrs)
+
+	}
+}
+
+const genruleHeaderLibrarySuffix = "__header_library"
+
+func (m *Module) needsCcLibraryHeadersBp2build() bool {
+	return len(m.properties.Export_include_dirs) > 0
+}
+
+// GenruleCcHeaderMapper is a bazel.LabelMapper function to map genrules to a cc_library_headers
+// target when they export multiple include directories.
+func GenruleCcHeaderLabelMapper(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+	mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
+	if !exists {
+		return label.Label, false
+	}
+	if m, ok := mod.(*Module); ok {
+		if m.needsCcLibraryHeadersBp2build() {
+			return label.Label + genruleHeaderLibrarySuffix, true
+		}
+	}
+	return label.Label, false
+}
+
+type ccHeaderLibraryAttrs struct {
+	Hdrs []string
+
+	Export_includes []string
 }
 
 var Bool = proptools.Bool
@@ -1099,6 +1147,7 @@
 		}
 	}).(*sandboxingAllowlistSets)
 }
+
 func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
 	if !ctx.DeviceConfig().GenruleSandboxing() {
 		return r.SandboxTools()
diff --git a/java/app_builder.go b/java/app_builder.go
index e241adb..d397ff7 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -268,12 +268,24 @@
 		Args:        args,
 	})
 	if len(prebuiltJniPackages) > 0 {
+		var mergeJniJarPath android.WritablePath = android.PathForModuleOut(ctx, "mergeJniJarOutput.zip")
+		if !uncompressJNI {
+			mergeJniJarPath = outputFile
+		}
 		ctx.Build(pctx, android.BuildParams{
 			Rule:        mergeAssetsRule,
 			Description: "merge prebuilt JNI packages",
 			Inputs:      append(prebuiltJniPackages, jniJarPath),
-			Output:      outputFile,
+			Output:      mergeJniJarPath,
 		})
+
+		if uncompressJNI {
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   uncompressEmbeddedJniLibsRule,
+				Input:  mergeJniJarPath,
+				Output: outputFile,
+			})
+		}
 	}
 }
 
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index eadd9c6..de9a82d 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -146,12 +146,43 @@
     ],
 }
 
+java_defaults {
+    name: "core.module_lib.stubs.defaults",
+    visibility: ["//visibility:private"],
+    sdk_version: "none",
+    system_modules: "none",
+}
+
+
 // A stubs target containing the parts of the public SDK & @SystemApi(MODULE_LIBRARIES) API
 // provided by the core libraries.
 //
 // Don't use this directly, use "sdk_version: module_current".
 java_library {
     name: "core.module_lib.stubs",
+    defaults: [
+        "core.module_lib.stubs.defaults",
+    ],
+    static_libs: [
+        "core.module_lib.stubs.from-source",
+    ],
+    product_variables: {
+        build_from_text_stub: {
+            static_libs: [
+                "core.module_lib.stubs.from-text",
+            ],
+            exclude_static_libs: [
+                "core.module_lib.stubs.from-source",
+            ],
+        },
+    },
+}
+
+java_library {
+    name: "core.module_lib.stubs.from-source",
+    defaults: [
+        "core.module_lib.stubs.defaults",
+    ],
     static_libs: [
         "art.module.public.api.stubs.module_lib",
 
@@ -161,9 +192,6 @@
         "conscrypt.module.public.api.stubs",
         "i18n.module.public.api.stubs",
     ],
-    sdk_version: "none",
-    system_modules: "none",
-    visibility: ["//visibility:private"],
 }
 
 // Produces a dist file that is used by the
@@ -249,10 +277,10 @@
     product_variables: {
         build_from_text_stub: {
             static_libs: [
-                "stable.core.platform.api.stubs.from-text",
+                "legacy.core.platform.api.stubs.from-text",
             ],
             exclude_static_libs: [
-                "stable.core.platform.api.stubs.from-source",
+                "legacy.core.platform.api.stubs.from-source",
             ],
         },
     },
diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp
index 0cf0f36..c46f8b8 100644
--- a/java/core-libraries/TxtStubLibraries.bp
+++ b/java/core-libraries/TxtStubLibraries.bp
@@ -57,19 +57,23 @@
     ],
 }
 
-java_library {
+java_api_library {
     name: "core.module_lib.stubs.from-text",
-    static_libs: [
-        "art.module.public.api.stubs.module_lib.from-text",
+    api_surface: "module-lib",
+    api_contributions: [
+        "art.module.public.api.stubs.source.api.contribution",
+        "art.module.public.api.stubs.source.system.api.contribution",
+        "art.module.public.api.stubs.source.module_lib.api.contribution",
 
-        // Replace the following with the module-lib correspondence when Conscrypt or i18N module
+        // Add the module-lib correspondence when Conscrypt or i18N module
         // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
         // @SystemApi(MODULE_LIBRARIES).
-        "conscrypt.module.public.api.stubs.from-text",
-        "i18n.module.public.api.stubs.from-text",
+        "conscrypt.module.public.api.stubs.source.api.contribution",
+        "i18n.module.public.api.stubs.source.api.contribution",
     ],
-    sdk_version: "none",
-    system_modules: "none",
+    libs: [
+        "stub-annotations",
+    ],
     visibility: ["//visibility:private"],
 }
 
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index d25096b..4d08b83 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -106,7 +106,7 @@
 	h.uncompressDexState = uncompressedDexState
 
 	// If hiddenapi processing is disabled treat this as inactive.
-	if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+	if ctx.Config().DisableHiddenApiChecks() {
 		return
 	}
 
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 714634f..8ec1797 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -121,8 +121,8 @@
 
 // hiddenAPI singleton rules
 func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) {
-	// Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true
-	if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+	// Don't run any hiddenapi rules if hiddenapi checks are disabled
+	if ctx.Config().DisableHiddenApiChecks() {
 		return
 	}
 
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index a4bba48..ade7395 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -113,7 +113,7 @@
 }
 
 func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
-	if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+	if ctx.Config().DisableHiddenApiChecks() {
 		return
 	}
 
@@ -275,10 +275,10 @@
 
 	bootDexJarByModule := extractBootDexJarsFromModules(ctx, modules)
 
-	// Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true. This is a performance
+	// Don't run any hiddenapi rules if hidden api checks are disabled. This is a performance
 	// optimization that can be used to reduce the incremental build time but as its name suggests it
 	// can be unsafe to use, e.g. when the changes affect anything that goes on the bootclasspath.
-	if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+	if ctx.Config().DisableHiddenApiChecks() {
 		paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
 		for _, path := range paths {
 			ctx.Build(pctx, android.BuildParams{
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 59585aa..c2bf6af 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -61,15 +61,18 @@
 		"${cc_config.ClangBase}/${bindgenHostPrebuiltTag}/${bindgenClangVersion}/${bindgenClangLibdir}")
 
 	//TODO(ivanlozano) Switch this to RuleBuilder
+	//
+	//TODO Pass the flag files directly to bindgen e.g. with @file when it supports that.
+	//See https://github.com/rust-lang/rust-bindgen/issues/2508.
 	bindgen = pctx.AndroidStaticRule("bindgen",
 		blueprint.RuleParams{
 			Command: "CLANG_PATH=$bindgenClang LIBCLANG_PATH=$bindgenLibClang RUSTFMT=${config.RustBin}/rustfmt " +
-				"$cmd $flags $in -o $out -- -MD -MF $out.d $cflags",
+				"$cmd $flags $$(cat $flagfiles) $in -o $out -- -MD -MF $out.d $cflags",
 			CommandDeps: []string{"$cmd"},
 			Deps:        blueprint.DepsGCC,
 			Depfile:     "$out.d",
 		},
-		"cmd", "flags", "cflags")
+		"cmd", "flags", "flagfiles", "cflags")
 )
 
 func init() {
@@ -90,6 +93,9 @@
 	// list of bindgen-specific flags and options
 	Bindgen_flags []string `android:"arch_variant"`
 
+	// list of files containing extra bindgen flags
+	Bindgen_flag_files []string `android:"arch_variant"`
+
 	// module name of a custom binary/script which should be used instead of the 'bindgen' binary. This custom
 	// binary must expect arguments in a similar fashion to bindgen, e.g.
 	//
@@ -216,6 +222,14 @@
 	bindgenFlags := defaultBindgenFlags
 	bindgenFlags = append(bindgenFlags, esc(b.Properties.Bindgen_flags)...)
 
+	// cat reads from stdin if its command line is empty,
+	// so we pass in /dev/null if there are no other flag files
+	bindgenFlagFiles := []string{"/dev/null"}
+	for _, flagFile := range b.Properties.Bindgen_flag_files {
+		bindgenFlagFiles = append(bindgenFlagFiles, android.PathForModuleSrc(ctx, flagFile).String())
+		implicits = append(implicits, android.PathForModuleSrc(ctx, flagFile))
+	}
+
 	wrapperFile := android.OptionalPathForModuleSrc(ctx, b.Properties.Wrapper_src)
 	if !wrapperFile.Valid() {
 		ctx.PropertyErrorf("wrapper_src", "invalid path to wrapper source")
@@ -261,9 +275,10 @@
 		Input:       wrapperFile.Path(),
 		Implicits:   implicits,
 		Args: map[string]string{
-			"cmd":    cmd,
-			"flags":  strings.Join(bindgenFlags, " "),
-			"cflags": strings.Join(cflags, " "),
+			"cmd":       cmd,
+			"flags":     strings.Join(bindgenFlags, " "),
+			"flagfiles": strings.Join(bindgenFlagFiles, " "),
+			"cflags":    strings.Join(cflags, " "),
 		},
 	})
 
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index af04cfc..12cdb3c 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -168,3 +168,28 @@
 		}
 	`)
 }
+
+func TestBindgenFlagFile(t *testing.T) {
+	ctx := testRust(t, `
+		rust_bindgen {
+			name: "libbindgen",
+			wrapper_src: "src/any.h",
+			crate_name: "bindgen",
+			stem: "libbindgen",
+			source_stem: "bindings",
+			bindgen_flag_files: [
+				"flag_file.txt",
+			],
+		}
+	`)
+	libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+
+	if !strings.Contains(libbindgen.Args["flagfiles"], "/dev/null") {
+		t.Errorf("missing /dev/null in rust_bindgen rule: flags %#v", libbindgen.Args["flagfiles"])
+	}
+	if !strings.Contains(libbindgen.Args["flagfiles"], "flag_file.txt") {
+		t.Errorf("missing bindgen flags file in rust_bindgen rule: flags %#v", libbindgen.Args["flagfiles"])
+	}
+	// TODO: The best we can do right now is check $flagfiles. Once bindgen.go switches to RuleBuilder,
+	// we may be able to check libbinder.RuleParams.Command to see if it contains $(cat /dev/null flag_file.txt)
+}
diff --git a/rust/builder.go b/rust/builder.go
index c31bc88..fbceecc 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -228,6 +228,17 @@
 		pkgVersion := ctx.RustModule().compiler.CargoPkgVersion()
 		if pkgVersion != "" {
 			envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
+
+			// Ensure the version is in the form of "x.y.z" (approximately semver compliant).
+			//
+			// For our purposes, we don't care to enforce that these are integers since they may
+			// include other characters at times (e.g. sometimes the patch version is more than an integer).
+			if strings.Count(pkgVersion, ".") == 2 {
+				var semver_parts = strings.Split(pkgVersion, ".")
+				envVars = append(envVars, "CARGO_PKG_VERSION_MAJOR="+semver_parts[0])
+				envVars = append(envVars, "CARGO_PKG_VERSION_MINOR="+semver_parts[1])
+				envVars = append(envVars, "CARGO_PKG_VERSION_PATCH="+semver_parts[2])
+			}
 		}
 	}
 
diff --git a/rust/rust.go b/rust/rust.go
index 05fceee..dab3532 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1306,12 +1306,17 @@
 				}
 			}
 			linkObject := ccDep.OutputFile()
-			linkPath := linkPathFromFilePath(linkObject.Path())
-
 			if !linkObject.Valid() {
-				ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
+				if !ctx.Config().AllowMissingDependencies() {
+					ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
+				} else {
+					ctx.AddMissingDependencies([]string{depName})
+				}
+				return
 			}
 
+			linkPath := linkPathFromFilePath(linkObject.Path())
+
 			exportDep := false
 			switch {
 			case cc.IsStaticDepTag(depTag):
@@ -1356,6 +1361,14 @@
 				// Re-get linkObject as ChooseStubOrImpl actually tells us which
 				// object (either from stub or non-stub) to use.
 				linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
+				if !linkObject.Valid() {
+					if !ctx.Config().AllowMissingDependencies() {
+						ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
+					} else {
+						ctx.AddMissingDependencies([]string{depName})
+					}
+					return
+				}
 				linkPath = linkPathFromFilePath(linkObject.Path())
 
 				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 0f7cf6e..862baf7 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -223,11 +223,16 @@
 	if !sanitize.Properties.SanitizerEnabled {
 		return flags, deps
 	}
+
 	if Bool(sanitize.Properties.Sanitize.Fuzzer) {
 		flags.RustFlags = append(flags.RustFlags, fuzzerFlags...)
-	} else if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+	}
+
+	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
 		flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
-	} else if Bool(sanitize.Properties.Sanitize.Address) {
+	}
+
+	if Bool(sanitize.Properties.Sanitize.Address) {
 		flags.RustFlags = append(flags.RustFlags, asanFlags...)
 	}
 	return flags, deps
@@ -267,14 +272,12 @@
 		var depTag blueprint.DependencyTag
 		var deps []string
 
-		if mod.IsSanitizerEnabled(cc.Asan) ||
-			(mod.IsSanitizerEnabled(cc.Fuzzer) && (mctx.Arch().ArchType != android.Arm64 || !mctx.Os().Bionic())) {
+		if mod.IsSanitizerEnabled(cc.Asan) {
 			variations = append(variations,
 				blueprint.Variation{Mutator: "link", Variation: "shared"})
 			depTag = cc.SharedDepTag()
 			deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
-		} else if mod.IsSanitizerEnabled(cc.Hwasan) ||
-			(mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType == android.Arm64 && mctx.Os().Bionic()) {
+		} else if mod.IsSanitizerEnabled(cc.Hwasan) {
 			// TODO(b/204776996): HWASan for static Rust binaries isn't supported yet.
 			if binary, ok := mod.compiler.(binaryInterface); ok {
 				if binary.staticallyLinked() {