Merge "Extract proguard rules found in imported JAR archives" into main
diff --git a/Android.bp b/Android.bp
index d78379a..47a195c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -253,3 +253,8 @@
     relative_install_path: "etc/ramdisk", // ramdisk/system/etc/ramdisk/build.prop
     visibility: ["//visibility:private"],
 }
+
+all_apex_certs {
+    name: "all_apex_certs",
+    visibility: ["//cts/tests/tests/security"],
+}
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index 6ad54da..3262493 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -65,15 +65,16 @@
 		})
 
 		var numOffendingPkg = 0
+		offendingPkgsMessage := ""
 		for pkg, cnt := range packages {
 			if cnt > 1 {
-				fmt.Printf("%d aconfig_declarations found for package %s\n", cnt, pkg)
+				offendingPkgsMessage += fmt.Sprintf("%d aconfig_declarations found for package %s\n", cnt, pkg)
 				numOffendingPkg++
 			}
 		}
 
 		if numOffendingPkg > 0 {
-			panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
+			panic("Only one aconfig_declarations allowed for each package.\n" + offendingPkgsMessage)
 		}
 
 		// Generate build action for aconfig (binary proto output)
diff --git a/android/Android.bp b/android/Android.bp
index bb16856..d27a8fa 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -79,6 +79,7 @@
         "namespace.go",
         "neverallow.go",
         "ninja_deps.go",
+        "nothing.go",
         "notices.go",
         "onceper.go",
         "override_module.go",
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 0b876c3..2f11df6 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -236,8 +236,8 @@
 		blueprint.RuleParams{
 			Command: `rm -rf $out && ` +
 				`${sqlite3} $out ".import --csv $in modules" && ` +
-				`${sqlite3} $out ".import --csv ${make_metadata} make_metadata" && ` +
-				`${sqlite3} $out ".import --csv ${make_modules} make_modules"`,
+				`([ -z "${make_metadata}" ] || ${sqlite3} $out ".import --csv ${make_metadata} make_metadata") && ` +
+				`([ -z "${make_modules}" ] || ${sqlite3} $out ".import --csv ${make_modules} make_modules")`,
 			CommandDeps: []string{"${sqlite3}"},
 		}, "make_metadata", "make_modules")
 )
@@ -307,24 +307,29 @@
 	modulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "soong-modules.csv")
 	WriteFileRuleVerbatim(ctx, modulesCsv, buffer.String())
 
-	// Metadata generated in Make
-	makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv")
-	makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv")
+	var implicits []Path
+	args := make(map[string]string)
+
+	if ctx.Config().KatiEnabled() {
+		// Metadata generated in Make
+		makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv")
+		makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv")
+		implicits = append(implicits, makeMetadataCsv, makeModulesCsv)
+		args["make_metadata"] = makeMetadataCsv.String()
+		args["make_modules"] = makeModulesCsv.String()
+	} else {
+		args["make_metadata"] = ""
+		args["make_modules"] = ""
+	}
 
 	// Import metadata from Make and Soong to sqlite3 database
 	complianceMetadataDb := PathForOutput(ctx, "compliance-metadata", deviceProduct, "compliance-metadata.db")
 	ctx.Build(pctx, BuildParams{
-		Rule:  importCsv,
-		Input: modulesCsv,
-		Implicits: []Path{
-			makeMetadataCsv,
-			makeModulesCsv,
-		},
-		Output: complianceMetadataDb,
-		Args: map[string]string{
-			"make_metadata": makeMetadataCsv.String(),
-			"make_modules":  makeModulesCsv.String(),
-		},
+		Rule:      importCsv,
+		Input:     modulesCsv,
+		Implicits: implicits,
+		Output:    complianceMetadataDb,
+		Args:      args,
 	})
 
 	// Phony rule "compliance-metadata.db". "m compliance-metadata.db" to create the compliance metadata database.
diff --git a/android/config.go b/android/config.go
index 00d5e2c..e9cb2cd 100644
--- a/android/config.go
+++ b/android/config.go
@@ -768,11 +768,7 @@
 // BlueprintToolLocation returns the directory containing build system tools
 // from Blueprint, like soong_zip and merge_zips.
 func (c *config) HostToolDir() string {
-	if c.KatiEnabled() {
-		return filepath.Join(c.outDir, "host", c.PrebuiltOS(), "bin")
-	} else {
-		return filepath.Join(c.soongOutDir, "host", c.PrebuiltOS(), "bin")
-	}
+	return filepath.Join(c.outDir, "host", c.PrebuiltOS(), "bin")
 }
 
 func (c *config) HostToolPath(ctx PathContext, tool string) Path {
diff --git a/android/container.go b/android/container.go
index 99e6a30..830d474 100644
--- a/android/container.go
+++ b/android/container.go
@@ -198,9 +198,7 @@
 func determineUnstableModule(mctx ModuleContext) bool {
 	module := mctx.Module()
 
-	// TODO(b/383559945) Remove "framework-minus-apex_jarjar-sharded" once
-	// we remove this module.
-	unstableModule := module.Name() == "framework-minus-apex" || module.Name() == "framework-minus-apex_jarjar-sharded"
+	unstableModule := module.Name() == "framework-minus-apex"
 	if installable, ok := module.(InstallableModule); ok {
 		for _, staticDepTag := range installable.StaticDependencyTags() {
 			mctx.VisitDirectDepsWithTag(staticDepTag, func(dep Module) {
diff --git a/android/module_context.go b/android/module_context.go
index b59e33d..ba31cb2 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -688,7 +688,6 @@
 				Input:       srcPath,
 				Implicits:   implicitDeps,
 				OrderOnly:   orderOnlyDeps,
-				Default:     !m.Config().KatiEnabled(),
 				Args: map[string]string{
 					"extraCmds": extraCmds,
 				},
@@ -735,7 +734,6 @@
 				Description: "install symlink " + fullInstallPath.Base(),
 				Output:      fullInstallPath,
 				Input:       srcPath,
-				Default:     !m.Config().KatiEnabled(),
 				Args: map[string]string{
 					"fromPath": relPath,
 				},
@@ -782,7 +780,6 @@
 				Rule:        Symlink,
 				Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
 				Output:      fullInstallPath,
-				Default:     !m.Config().KatiEnabled(),
 				Args: map[string]string{
 					"fromPath": absPath,
 				},
diff --git a/android/neverallow.go b/android/neverallow.go
index fdcbe1c..d211784 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -322,9 +322,6 @@
 
 func createKotlinPluginRule() []Rule {
 	kotlinPluginProjectsAllowedList := []string{
-		// TODO: Migrate compose plugin to the bundled compiler plugin
-		// Actual path prebuilts/sdk/current/androidx/m2repository/androidx/compose/compiler/compiler-hosted
-		"prebuilts/sdk/current/androidx",
 		"external/kotlinc",
 	}
 
diff --git a/android/nothing.go b/android/nothing.go
new file mode 100644
index 0000000..18bf85b
--- /dev/null
+++ b/android/nothing.go
@@ -0,0 +1,34 @@
+// Copyright 2025 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 android
+
+func init() {
+	RegisterParallelSingletonType("nothing_singleton", nothingSingletonFactory)
+}
+
+func nothingSingletonFactory() Singleton {
+	return &nothingSingleton{}
+}
+
+type nothingSingleton struct{}
+
+func (s *nothingSingleton) GenerateBuildActions(ctx SingletonContext) {
+	rule := NewRuleBuilder(pctx, ctx)
+	rule.SetPhonyOutput()
+	rule.Command().
+		Text("echo Successfully read the makefiles.").
+		ImplicitOutput(PathForPhony(ctx, "nothing"))
+	rule.Build("nothing", "nothing")
+}
diff --git a/android/test_asserts.go b/android/test_asserts.go
index c33ade5..22472c5 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -33,6 +33,23 @@
 	}
 }
 
+// AssertSame checks if the expected and actual values are equal and if they are not then
+// it reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertSameArray[T comparable](t *testing.T, message string, expected []T, actual []T) {
+	t.Helper()
+	if len(actual) != len(expected) {
+		t.Errorf("%s: expected %d (%v), actual (%d) %v", message, len(expected), expected, len(actual), actual)
+		return
+	}
+	for i := range actual {
+		if actual[i] != expected[i] {
+			t.Errorf("%s: expected %d-th, %v (%v), actual %v (%v)",
+				message, i, expected[i], expected, actual[i], actual)
+			return
+		}
+	}
+}
+
 // AssertBoolEquals checks if the expected and actual values are equal and if they are not then it
 // reports an error prefixed with the supplied message and including a reason for why it failed.
 func AssertBoolEquals(t *testing.T, message string, expected bool, actual bool) {
diff --git a/android/util.go b/android/util.go
index 3fc4608..30d8ec6 100644
--- a/android/util.go
+++ b/android/util.go
@@ -308,6 +308,20 @@
 	return
 }
 
+// FilterListByPrefixes performs the same splitting as FilterList does, but treats the passed
+// filters as prefixes
+func FilterListByPrefix(list []string, filter []string) (remainder []string, filtered []string) {
+	for _, l := range list {
+		if HasAnyPrefix(l, filter) {
+			filtered = append(filtered, l)
+		} else {
+			remainder = append(remainder, l)
+		}
+	}
+
+	return
+}
+
 // FilterListPred returns the elements of the given list for which the predicate
 // returns true. Order is kept.
 func FilterListPred(list []string, pred func(s string) bool) (filtered []string) {
diff --git a/android/variable.go b/android/variable.go
index ec84274..6e46e9d 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -162,6 +162,7 @@
 			Optimize struct {
 				Enabled *bool
 			}
+			Aaptflags []string
 		}
 
 		Uml struct {
diff --git a/apex/apex.go b/apex/apex.go
index 375d5af..7734391 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -888,8 +888,20 @@
 	ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
 	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
 	ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
+
+	// Add a reverse dependency to all_apex_certs singleton module.
+	// all_apex_certs will use this dependency to collect the certificate of this apex.
+	ctx.AddReverseDependency(ctx.Module(), allApexCertsDepTag, "all_apex_certs")
 }
 
+type allApexCertsDependencyTag struct {
+	blueprint.DependencyTag
+}
+
+func (_ allApexCertsDependencyTag) ExcludeFromVisibilityEnforcement() {}
+
+var allApexCertsDepTag = allApexCertsDependencyTag{}
+
 // DepsMutator for the overridden properties.
 func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
 	if a.overridableProperties.Allowed_files != nil {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index fa4cf3b..e1a9582 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3585,7 +3585,11 @@
 				name: "myapex.key",
 				public_key: "testkey.avbpubkey",
 				private_key: "testkey.pem",
-			}`)
+			}`,
+			android.MockFS{
+				"vendor/foo/devkeys/testkey.x509.pem": nil,
+			}.AddToFixture(),
+		)
 		rule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk")
 		expected := "vendor/foo/devkeys/testkey.x509.pem vendor/foo/devkeys/testkey.pk8"
 		if actual := rule.Args["certificates"]; actual != expected {
diff --git a/apex/builder.go b/apex/builder.go
index c85d0a0..b74f4de 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -211,10 +211,10 @@
 
 	apexSepolicyTestsRule = pctx.StaticRule("apexSepolicyTestsRule", blueprint.RuleParams{
 		Command: `${deapexer} --debugfs_path ${debugfs_static} list -Z ${in} > ${out}.fc` +
-			` && ${apex_sepolicy_tests} -f ${out}.fc && touch ${out}`,
+			` && ${apex_sepolicy_tests} -f ${out}.fc --partition ${partition_tag} && touch ${out}`,
 		CommandDeps: []string{"${apex_sepolicy_tests}", "${deapexer}", "${debugfs_static}"},
 		Description: "run apex_sepolicy_tests",
-	})
+	}, "partition_tag")
 
 	apexLinkerconfigValidationRule = pctx.StaticRule("apexLinkerconfigValidationRule", blueprint.RuleParams{
 		Command:     `${conv_linker_config} validate --type apex ${image_dir} && touch ${out}`,
@@ -920,7 +920,7 @@
 	validations = append(validations, runApexLinkerconfigValidation(ctx, unsignedOutputFile, imageDir))
 	// TODO(b/279688635) deapexer supports [ext4]
 	if !a.skipValidation(apexSepolicyTests) && suffix == imageApexSuffix && ext4 == a.payloadFsType {
-		validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile))
+		validations = append(validations, runApexSepolicyTests(ctx, a, unsignedOutputFile))
 	}
 	if !a.testApex && len(a.properties.Unwanted_transitive_deps) > 0 {
 		validations = append(validations,
@@ -1206,12 +1206,15 @@
 //
 // $ deapexer list -Z {apex_file} > {file_contexts}
 // $ apex_sepolicy_tests -f {file_contexts}
-func runApexSepolicyTests(ctx android.ModuleContext, apexFile android.Path) android.Path {
+func runApexSepolicyTests(ctx android.ModuleContext, a *apexBundle, apexFile android.Path) android.Path {
 	timestamp := android.PathForModuleOut(ctx, "apex_sepolicy_tests.timestamp")
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   apexSepolicyTestsRule,
 		Input:  apexFile,
 		Output: timestamp,
+		Args: map[string]string{
+			"partition_tag": a.PartitionTag(ctx.DeviceConfig()),
+		},
 	})
 	return timestamp
 }
diff --git a/apex/key.go b/apex/key.go
index e4214f0..9fa9d1e 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -18,6 +18,7 @@
 	"fmt"
 
 	"android/soong/android"
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -29,6 +30,7 @@
 
 func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+	ctx.RegisterParallelSingletonModuleType("all_apex_certs", allApexCertsFactory)
 }
 
 type apexKey struct {
@@ -155,3 +157,59 @@
 	android.WriteFileRuleVerbatim(ctx, path, entry.String())
 	return path
 }
+
+var (
+	pemToDer = pctx.AndroidStaticRule("pem_to_der",
+		blueprint.RuleParams{
+			Command:     `openssl x509 -inform PEM -outform DER -in $in -out $out`,
+			Description: "Convert certificate from PEM to DER format",
+		},
+	)
+)
+
+// all_apex_certs is a singleton module that collects the certs of all apexes in the tree.
+// It provides two types of output files
+// 1. .pem: This is usually the checked-in x509 certificate in PEM format
+// 2. .der: This is DER format of the certificate, and is generated from the PEM certificate using `openssl x509`
+func allApexCertsFactory() android.SingletonModule {
+	m := &allApexCerts{}
+	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+	return m
+}
+
+type allApexCerts struct {
+	android.SingletonModuleBase
+}
+
+func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	var certificatesPem android.Paths
+	ctx.VisitDirectDeps(func(m android.Module) {
+		if apex, ok := m.(*apexBundle); ok {
+			pem, _ := apex.getCertificateAndPrivateKey(ctx)
+			if !android.ExistentPathForSource(ctx, pem.String()).Valid() {
+				if ctx.Config().AllowMissingDependencies() {
+					return
+				} else {
+					ctx.ModuleErrorf("Path %s is not valid\n", pem.String())
+				}
+			}
+			certificatesPem = append(certificatesPem, pem)
+		}
+	})
+	certificatesPem = android.SortedUniquePaths(certificatesPem) // For hermiticity
+	var certificatesDer android.Paths
+	for index, certificatePem := range certificatesPem {
+		certificateDer := android.PathForModuleOut(ctx, fmt.Sprintf("x509.%v.der", index))
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   pemToDer,
+			Input:  certificatePem,
+			Output: certificateDer,
+		})
+		certificatesDer = append(certificatesDer, certificateDer)
+	}
+	ctx.SetOutputFiles(certificatesPem, ".pem")
+	ctx.SetOutputFiles(certificatesDer, ".der")
+}
+
+func (_ *allApexCerts) GenerateSingletonBuildActions(ctx android.SingletonContext) {
+}
diff --git a/apex/testing.go b/apex/testing.go
index 63c5b69..a22f640 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -22,6 +22,9 @@
 	android.FixtureRegisterWithContext(registerApexBuildComponents),
 	android.FixtureRegisterWithContext(registerApexKeyBuildComponents),
 	android.FixtureRegisterWithContext(registerApexDepsInfoComponents),
+	android.FixtureAddTextFile("all_apex_certs/Android.bp", `
+		all_apex_certs { name: "all_apex_certs" }
+	`),
 	// Additional files needed in tests that disallow non-existent source files.
 	// This includes files that are needed by all, or at least most, instances of an apex module type.
 	android.MockFS{
@@ -30,6 +33,8 @@
 		"build/soong/scripts/gen_ndk_backedby_apex.sh":         nil,
 		// Needed by prebuilt_apex.
 		"build/soong/scripts/unpack-prebuilt-apex.sh": nil,
+		// Needed by all_apex_certs
+		"build/make/target/product/security/testkey.x509.pem": nil,
 	}.AddToFixture(),
 	android.PrepareForTestWithBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION", testDefaultUpdatableModuleVersion),
 )
diff --git a/cc/cc.go b/cc/cc.go
index 97d4533..c9d2926 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -92,6 +92,7 @@
 type BinaryDecoratorInfo struct{}
 type LibraryDecoratorInfo struct {
 	ExportIncludeDirs proptools.Configurable[[]string]
+	InjectBsslHash    bool
 }
 
 type LibraryInfo struct {
@@ -2220,7 +2221,9 @@
 		case *binaryDecorator:
 			ccInfo.LinkerInfo.BinaryDecoratorInfo = &BinaryDecoratorInfo{}
 		case *libraryDecorator:
-			ccInfo.LinkerInfo.LibraryDecoratorInfo = &LibraryDecoratorInfo{}
+			ccInfo.LinkerInfo.LibraryDecoratorInfo = &LibraryDecoratorInfo{
+				InjectBsslHash: Bool(c.linker.(*libraryDecorator).Properties.Inject_bssl_hash),
+			}
 		case *testBinary:
 			ccInfo.LinkerInfo.TestBinaryInfo = &TestBinaryInfo{
 				Gtest: decorator.testDecorator.gtest(),
diff --git a/cc/library.go b/cc/library.go
index c9114fd..5c2cb5d 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1195,7 +1195,7 @@
 	library.linkSAbiDumpFiles(ctx, deps, objs, fileName, unstrippedOutputFile)
 
 	var transitiveStaticLibrariesForOrdering depset.DepSet[android.Path]
-	if static := ctx.GetDirectDepsWithTag(staticVariantTag); len(static) > 0 {
+	if static := ctx.GetDirectDepsProxyWithTag(staticVariantTag); len(static) > 0 {
 		s, _ := android.OtherModuleProvider(ctx, static[0], StaticLibraryInfoProvider)
 		transitiveStaticLibrariesForOrdering = s.TransitiveStaticLibrariesForOrdering
 	}
@@ -2409,13 +2409,11 @@
 	inject *bool, fileName string) android.ModuleOutPath {
 	// TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries.
 	injectBoringSSLHash := Bool(inject)
-	ctx.VisitDirectDeps(func(dep android.Module) {
+	ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
 		if tag, ok := ctx.OtherModuleDependencyTag(dep).(libraryDependencyTag); ok && tag.static() {
-			if cc, ok := dep.(*Module); ok {
-				if library, ok := cc.linker.(*libraryDecorator); ok {
-					if Bool(library.Properties.Inject_bssl_hash) {
-						injectBoringSSLHash = true
-					}
+			if ccInfo, ok := android.OtherModuleProvider(ctx, dep, CcInfoProvider); ok && ccInfo.LinkerInfo.LibraryDecoratorInfo != nil {
+				if ccInfo.LinkerInfo.LibraryDecoratorInfo.InjectBsslHash {
+					injectBoringSSLHash = true
 				}
 			}
 		}
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 19e93ae..fd8e915 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -44,6 +44,12 @@
 	Vbmeta_partitions []string
 	// Name of the userdata partition filesystem module
 	Userdata_partition_name *string
+	// Name of the system_dlkm partition filesystem module
+	System_dlkm_partition_name *string
+	// Name of the vendor_dlkm partition filesystem module
+	Vendor_dlkm_partition_name *string
+	// Name of the odm_dlkm partition filesystem module
+	Odm_dlkm_partition_name *string
 }
 
 type androidDevice struct {
@@ -55,7 +61,7 @@
 func AndroidDeviceFactory() android.Module {
 	module := &androidDevice{}
 	module.AddProperties(&module.partitionProps)
-	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
 }
 
@@ -68,7 +74,7 @@
 func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
 	addDependencyIfDefined := func(dep *string) {
 		if dep != nil {
-			ctx.AddFarVariationDependencies(nil, filesystemDepTag, proptools.String(dep))
+			ctx.AddDependency(ctx.Module(), filesystemDepTag, proptools.String(dep))
 		}
 	}
 
@@ -79,6 +85,9 @@
 	addDependencyIfDefined(a.partitionProps.Vendor_partition_name)
 	addDependencyIfDefined(a.partitionProps.Odm_partition_name)
 	addDependencyIfDefined(a.partitionProps.Userdata_partition_name)
+	addDependencyIfDefined(a.partitionProps.System_dlkm_partition_name)
+	addDependencyIfDefined(a.partitionProps.Vendor_dlkm_partition_name)
+	addDependencyIfDefined(a.partitionProps.Odm_dlkm_partition_name)
 	for _, vbmetaPartition := range a.partitionProps.Vbmeta_partitions {
 		ctx.AddDependency(ctx.Module(), filesystemDepTag, vbmetaPartition)
 	}
@@ -95,12 +104,25 @@
 	builder := android.NewRuleBuilder(pctx, ctx)
 	builder.Command().Textf("rm -rf %s", targetFilesDir.String())
 	builder.Command().Textf("mkdir -p %s", targetFilesDir.String())
-	if a.partitionProps.Vendor_partition_name != nil {
-		fsInfo := a.getFilesystemInfo(ctx, *a.partitionProps.Vendor_partition_name)
-		builder.Command().Textf("mkdir -p %s/VENDOR", targetFilesDir.String())
+	partitionToSubdir := map[*string]string{
+		a.partitionProps.System_partition_name:      "SYSTEM",
+		a.partitionProps.System_ext_partition_name:  "SYSTEM_EXT",
+		a.partitionProps.Product_partition_name:     "PRODUCT",
+		a.partitionProps.Vendor_partition_name:      "VENDOR",
+		a.partitionProps.Odm_partition_name:         "ODM",
+		a.partitionProps.System_dlkm_partition_name: "SYSTEM_DLKM",
+		a.partitionProps.Vendor_dlkm_partition_name: "VENDOR_DLKM",
+		a.partitionProps.Odm_dlkm_partition_name:    "ODM_DLKM",
+	}
+	for partition, subdir := range partitionToSubdir {
+		if partition == nil {
+			continue
+		}
+		fsInfo := a.getFilesystemInfo(ctx, *partition)
+		builder.Command().Textf("mkdir -p %s/%s", targetFilesDir.String(), subdir)
 		builder.Command().
 			BuiltTool("acp").
-			Textf("-rd %s/. %s/VENDOR", fsInfo.RootDir, targetFilesDir).
+			Textf("-rd %s/. %s/%s", fsInfo.RootDir, targetFilesDir, subdir).
 			Implicit(fsInfo.Output) // so that the staging dir is built
 	}
 	builder.Command().
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 5845d59..6dfbfd1 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -648,7 +648,6 @@
 		Input(propFile).
 		Implicits(toolDeps).
 		Implicit(fec).
-		FlagWithArg("--build_datetime_file ", ctx.Config().Getenv("BUILD_DATETIME_FILE")).
 		Output(output).
 		Text(rootDir.String()) // directory where to find fs_config_files|dirs
 
@@ -752,7 +751,10 @@
 	}
 	if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" {
 		addStr("timestamp", timestamp)
+	} else if ctx.Config().Getenv("USE_FIXED_TIMESTAMP_IMG_FILES") == "true" {
+		addStr("use_fixed_timestamp", "true")
 	}
+
 	if uuid := proptools.String(f.properties.Uuid); uuid != "" {
 		addStr("uuid", uuid)
 		addStr("hash_seed", uuid)
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 0160159..41faf94 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -214,6 +214,15 @@
 	if android.InList("recovery", f.properties.Generated_partition_types) {
 		partitionProps.Recovery_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "recovery"))
 	}
+	if android.InList("system_dlkm", f.properties.Generated_partition_types) {
+		partitionProps.System_dlkm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_dlkm"))
+	}
+	if android.InList("vendor_dlkm", f.properties.Generated_partition_types) {
+		partitionProps.Vendor_dlkm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_dlkm"))
+	}
+	if android.InList("odm_dlkm", f.properties.Generated_partition_types) {
+		partitionProps.Odm_dlkm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm_dlkm"))
+	}
 	if f.properties.Boot_image != "" {
 		partitionProps.Boot_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "boot"))
 	}
@@ -580,7 +589,7 @@
 	}{
 		Name:             proptools.StringPtr(generatedModuleName(ctx.Config(), "android_info.prop")),
 		Board_info_files: partitionVars.BoardInfoFiles,
-		Stem:             proptools.StringPtr("android_info.txt"),
+		Stem:             proptools.StringPtr("android-info.txt"),
 	}
 	if len(androidInfoProps.Board_info_files) == 0 {
 		androidInfoProps.Bootloader_board_name = proptools.StringPtr(partitionVars.BootLoaderBoardName)
@@ -849,8 +858,8 @@
 
 func (f *filesystemCreator) createFileListDiffTest(ctx android.ModuleContext, partitionType string) android.Path {
 	partitionModuleName := generatedModuleNameForPartition(ctx.Config(), partitionType)
-	systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
-	filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider)
+	partitionImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
+	filesystemInfo, ok := android.OtherModuleProvider(ctx, partitionImage, filesystem.FilesystemProvider)
 	if !ok {
 		ctx.ModuleErrorf("Expected module %s to provide FileysystemInfo", partitionModuleName)
 	}
@@ -905,12 +914,12 @@
 	builder.Build("diff test "+diffTestResultFile.String(), "diff test")
 }
 
-type systemImageDepTagType struct {
+type imageDepTagType struct {
 	blueprint.BaseDependencyTag
 }
 
-var generatedFilesystemDepTag systemImageDepTagType
-var generatedVbmetaPartitionDepTag systemImageDepTagType
+var generatedFilesystemDepTag imageDepTagType
+var generatedVbmetaPartitionDepTag imageDepTagType
 
 func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
 	for _, partitionType := range f.properties.Generated_partition_types {
diff --git a/golang/golang_test.go b/golang/golang_test.go
index 0a4baed..d555d14 100644
--- a/golang/golang_test.go
+++ b/golang/golang_test.go
@@ -47,7 +47,7 @@
 
 	bin := result.ModuleForTests("gobin", result.Config.BuildOSTarget.String())
 
-	expected := "^out/soong/host/" + result.Config.PrebuiltOS() + "/bin/go/gobin/?[^/]*/obj/gobin$"
+	expected := "^out/host/" + result.Config.PrebuiltOS() + "/bin/go/gobin/?[^/]*/obj/gobin$"
 	actual := android.PathsRelativeToTop(bin.OutputFiles(result.TestContext, t, ""))
 	if len(actual) != 1 {
 		t.Fatalf("Expected 1 output file, got %v", actual)
diff --git a/java/aar.go b/java/aar.go
index 3c62441..ed2fb7a 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -391,8 +391,9 @@
 		versionName = proptools.NinjaEscape(versionName)
 		linkFlags = append(linkFlags, "--version-name ", versionName)
 	}
-
-	linkFlags, compileFlags = android.FilterList(linkFlags, []string{"--legacy"})
+	// Split the flags by prefix, as --png-compression-level has the "=value" suffix.
+	linkFlags, compileFlags = android.FilterListByPrefix(linkFlags,
+		[]string{"--legacy", "--png-compression-level"})
 
 	// Always set --pseudo-localize, it will be stripped out later for release
 	// builds that don't want it.
diff --git a/java/app.go b/java/app.go
index b0dcbb0..a4e84e0 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1565,6 +1565,9 @@
 	}
 	a.generateAndroidBuildActions(ctx)
 
+	for _, c := range a.testProperties.Test_options.Tradefed_options {
+		configs = append(configs, c)
+	}
 	for _, module := range a.testProperties.Test_mainline_modules {
 		configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
 	}
@@ -1735,6 +1738,8 @@
 
 	// TODO(b/192032291): Disable by default after auditing downstream usage.
 	module.Module.dexProperties.Optimize.EnabledByDefault = true
+	module.Module.dexProperties.Optimize.Ignore_library_extends_program = proptools.BoolPtr(true)
+	module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false)
 
 	module.Module.properties.Installable = proptools.BoolPtr(true)
 	module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
diff --git a/java/app_import_test.go b/java/app_import_test.go
index ef8f60a..70c487c 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -737,13 +737,13 @@
 	variant := ctx.ModuleForTests("foo", "android_common")
 	jniRule := variant.Output("jnis-uncompressed/foo.apk").BuildParams.Rule.String()
 	if jniRule == android.Cp.String() {
-		t.Errorf("Unexpected JNI uncompress rule command: " + jniRule)
+		t.Errorf("Unexpected JNI uncompress rule command: %s", jniRule)
 	}
 
 	variant = ctx.ModuleForTests("foo_presigned", "android_common")
 	jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String()
 	if jniRule != android.Cp.String() {
-		t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+		t.Errorf("Unexpected JNI uncompress rule: %s", jniRule)
 	}
 	if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil {
 		t.Errorf("Presigned test apk should be aligned")
@@ -764,7 +764,7 @@
 	variant := ctx.ModuleForTests("foo", "android_common")
 	jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
 	if jniRule != android.Cp.String() {
-		t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+		t.Errorf("Unexpected JNI uncompress rule: %s", jniRule)
 	}
 
 	// Make sure signing and aligning were skipped.
@@ -807,7 +807,7 @@
 			variant := result.ModuleForTests("foo", "android_common")
 			outputBuildParams := variant.Output(apkName).BuildParams
 			if outputBuildParams.Rule.String() != android.Cp.String() {
-				t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
+				t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String())
 			}
 
 			// Make sure compression and aligning were validated.
@@ -817,7 +817,7 @@
 
 			validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams
 			if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
-				t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
+				t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String())
 			}
 
 			expectedScriptArgs := "--preprocessed"
@@ -829,7 +829,7 @@
 			variant = result.ModuleForTests("bar", "android_common")
 			outputBuildParams = variant.Output(apkName).BuildParams
 			if outputBuildParams.Rule.String() != android.Cp.String() {
-				t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
+				t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String())
 			}
 
 			// Make sure compression and aligning were validated.
@@ -839,7 +839,7 @@
 
 			validationBuildParams = variant.Output("validated-prebuilt/check.stamp").BuildParams
 			if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
-				t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
+				t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String())
 			}
 
 			expectedScriptArgs = "--privileged"
diff --git a/java/app_test.go b/java/app_test.go
index 4e915d2..bde801b 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"path/filepath"
 	"reflect"
+	"regexp"
 	"sort"
 	"strings"
 	"testing"
@@ -4589,6 +4590,75 @@
 	assertTestOnlyAndTopLevel(t, ctx, expectedTestOnly, expectedTopLevel)
 }
 
+func TestTestConfigTemplate(t *testing.T) {
+	t.Parallel()
+	ctx := android.GroupFixturePreparers(
+		prepareForJavaTest,
+	).RunTestWithBp(t, `
+		android_test {
+			name: "android-test",
+			test_config_template: "AndroidTestTemplate.xml",
+			test_options: {
+				tradefed_options: [
+					{
+						name: "name1",
+						key: "key1",
+						value: "value1",
+					},
+					{
+						name: "name2",
+						key: "key2",
+						value: "value2",
+					},
+				],
+				test_runner_options: [
+					{
+						name: "name3",
+						key: "key3",
+						value: "value3",
+					},
+					{
+						name: "name4",
+						key: "key4",
+						value: "value4",
+					},
+				],
+			},
+		}
+	`)
+	type option struct {
+		name  string
+		key   string
+		value string
+	}
+	re := regexp.MustCompile(`<option name="(.*)" key="(.*)" value="(.*)" />`)
+	parse_options := func(optionsString string) []option {
+		lines := strings.Split(optionsString, `\n`)
+		var ret []option
+		for _, l := range lines {
+			sm := re.FindStringSubmatch(l)
+			if sm == nil {
+				continue
+			}
+			ret = append(ret, option{sm[1], sm[2], sm[3]})
+		}
+		return ret
+	}
+	rule := ctx.ModuleForTests("android-test", "android_common").Rule("autogenInstrumentationTest")
+	android.AssertSameArray(t, "extraConfigs mismatch",
+		[]option{
+			{"name1", "key1", "value1"},
+			{"name2", "key2", "value2"},
+		},
+		parse_options(rule.Args["extraConfigs"]))
+	android.AssertSameArray(t, "extraTestRunnerConfigs mismatch",
+		[]option{
+			{"name3", "key3", "value3"},
+			{"name4", "key4", "value4"},
+		},
+		parse_options(rule.Args["extraTestRunnerConfigs"]))
+}
+
 func TestAppStem(t *testing.T) {
 	ctx := testApp(t, `
 				android_app {
diff --git a/java/base.go b/java/base.go
index 5c1ef85..1aef37c 100644
--- a/java/base.go
+++ b/java/base.go
@@ -2643,18 +2643,11 @@
 	RenameUseExclude
 )
 
-type RenameUseElement struct {
-	DepName   string
-	RenameUse DependencyUse
-	Why       string // token for determining where in the logic the decision was made.
-}
-
 type JarJarProviderData struct {
 	// Mapping of class names: original --> renamed.  If the value is "", the class will be
 	// renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has
 	// attribute). Rdeps of that module will inherit the renaming.
-	Rename    map[string]string
-	RenameUse []RenameUseElement
+	Rename map[string]string
 }
 
 func (this JarJarProviderData) GetDebugString() string {
@@ -2733,33 +2726,33 @@
 		//
 		// Note well: there are probably cases that are getting to the unconditional return
 		// and are therefore wrong.
-		shouldIncludeRenames := func() (DependencyUse, string) {
+		shouldIncludeRenames := func() DependencyUse {
 			if moduleName == m.Name() {
-				return RenameUseInclude, "name" // If we have the same module name, include the renames.
+				return RenameUseInclude // If we have the same module name, include the renames.
 			}
 			if sc, ok := module.(android.SdkContext); ok {
 				if ctx.Device() {
 					sdkDep := decodeSdkDep(ctx, sc)
 					if !sdkDep.invalidVersion && sdkDep.useFiles {
-						return RenameUseExclude, "useFiles"
+						return RenameUseExclude
 					}
 				}
 			}
 			if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag {
-				return RenameUseExclude, "tags"
+				return RenameUseExclude
 			}
 			if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
 				switch tag {
 				case sdkLibTag, libTag:
-					return RenameUseExclude, "sdklibdep" // matches collectDeps()
+					return RenameUseExclude // matches collectDeps()
 				}
-				return RenameUseInvalid, "sdklibdep" // dep is not used in collectDeps()
+				return RenameUseInvalid // dep is not used in collectDeps()
 			} else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
 				switch ji.StubsLinkType {
 				case Stubs:
-					return RenameUseExclude, "info"
+					return RenameUseExclude
 				case Implementation:
-					return RenameUseInclude, "info"
+					return RenameUseInclude
 				default:
 					//fmt.Printf("collectDirectDepsProviders: %v -> %v StubsLinkType unknown\n", module, m)
 					// Fall through to the heuristic logic.
@@ -2768,58 +2761,56 @@
 				case "*java.GeneratedJavaLibraryModule":
 					// Probably a java_aconfig_library module.
 					// TODO: make this check better.
-					return RenameUseInclude, "reflect"
+					return RenameUseInclude
 				}
 				switch tag {
 				case bootClasspathTag:
-					return RenameUseExclude, "tagswitch"
+					return RenameUseExclude
 				case sdkLibTag, libTag, instrumentationForTag:
-					return RenameUseInclude, "tagswitch"
+					return RenameUseInclude
 				case java9LibTag:
-					return RenameUseExclude, "tagswitch"
+					return RenameUseExclude
 				case staticLibTag:
-					return RenameUseInclude, "tagswitch"
+					return RenameUseInclude
 				case pluginTag:
-					return RenameUseInclude, "tagswitch"
+					return RenameUseInclude
 				case errorpronePluginTag:
-					return RenameUseInclude, "tagswitch"
+					return RenameUseInclude
 				case exportedPluginTag:
-					return RenameUseInclude, "tagswitch"
+					return RenameUseInclude
 				case kotlinPluginTag:
-					return RenameUseInclude, "tagswitch"
+					return RenameUseInclude
 				default:
-					return RenameUseExclude, "tagswitch"
+					return RenameUseExclude
 				}
 			} else if _, ok := m.(android.SourceFileProducer); ok {
 				switch tag {
 				case sdkLibTag, libTag, staticLibTag:
-					return RenameUseInclude, "srcfile"
+					return RenameUseInclude
 				default:
-					return RenameUseExclude, "srcfile"
+					return RenameUseExclude
 				}
 			} else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
-				return RenameUseInclude, "aconfig_declarations_group"
+				return RenameUseInclude
 			} else {
 				switch tag {
 				case bootClasspathTag:
-					return RenameUseExclude, "else"
+					return RenameUseExclude
 				case systemModulesTag:
-					return RenameUseInclude, "else"
+					return RenameUseInclude
 				}
 			}
 			// If we got here, choose the safer option, which may lead to a build failure, rather
 			// than runtime failures on the device.
-			return RenameUseExclude, "end"
+			return RenameUseExclude
 		}
 
 		if result == nil {
 			result = &JarJarProviderData{
-				Rename:    make(map[string]string),
-				RenameUse: make([]RenameUseElement, 0),
+				Rename: make(map[string]string),
 			}
 		}
-		how, why := shouldIncludeRenames()
-		result.RenameUse = append(result.RenameUse, RenameUseElement{DepName: m.Name(), RenameUse: how, Why: why})
+		how := shouldIncludeRenames()
 		if how != RenameUseInclude {
 			// Nothing to merge.
 			return
diff --git a/java/builder.go b/java/builder.go
index 72f4e14..30de61d 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -56,7 +56,7 @@
 				`$zipTemplate${config.SoongZipCmd} -jar -o $out.tmp -C $outDir -D $outDir && ` +
 				`if ! cmp -s "$out.tmp" "$out"; then mv "$out.tmp" "$out"; fi && ` +
 				`if ! cmp -s "$annoSrcJar.tmp" "$annoSrcJar"; then mv "$annoSrcJar.tmp" "$annoSrcJar"; fi && ` +
-				`if [[ -f "$out.pc_state.new" ]]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
+				`if [ -f "$out.pc_state.new" ]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
 				`rm -rf "$srcJarDir" "$outDir"`,
 			CommandDeps: []string{
 				"${config.FindInputDeltaCmd}",
diff --git a/java/config/config.go b/java/config/config.go
index 2ed2953..71025de 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -42,9 +42,6 @@
 	InstrumentFrameworkModules = []string{
 		"framework",
 		"framework-minus-apex",
-		// TODO(b/383559945) Remove "framework-minus-apex_jarjar-sharded" once
-		// we remove this module.
-		"framework-minus-apex_jarjar-sharded",
 		"ims-common",
 		"telephony-common",
 		"services",
diff --git a/java/dex.go b/java/dex.go
index 168a231..7b99549 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -42,11 +42,15 @@
 		// True if the module containing this has it set by default.
 		EnabledByDefault bool `blueprint:"mutated"`
 
+		// Whether to allow that library classes inherit from program classes.
+		// Defaults to false.
+		Ignore_library_extends_program *bool
+
 		// Whether to continue building even if warnings are emitted.  Defaults to true.
 		Ignore_warnings *bool
 
 		// If true, runs R8 in Proguard compatibility mode, otherwise runs R8 in full mode.
-		// Defaults to false for apps, true for libraries and tests.
+		// Defaults to false for apps and tests, true for libraries.
 		Proguard_compatibility *bool
 
 		// If true, optimize for size by removing unused code.  Defaults to true for apps,
@@ -356,6 +360,10 @@
 
 	r8Flags = append(r8Flags, opt.Proguard_flags...)
 
+	if BoolDefault(opt.Ignore_library_extends_program, false) {
+		r8Flags = append(r8Flags, "--ignore-library-extends-program")
+	}
+
 	if BoolDefault(opt.Proguard_compatibility, true) {
 		r8Flags = append(r8Flags, "--force-proguard-compatibility")
 	}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index e955949..fa1fb86 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -629,8 +629,8 @@
 					cmd.Implicit(dep)
 				} else if filename != "android.jar" && depBase == "android.jar" {
 					// Metalava implicitly searches these patterns:
-					//  prebuilts/tools/common/api-versions/android-%/android.jar
-					//  prebuilts/sdk/%/public/android.jar
+					//  prebuilts/tools/common/api-versions/android-{version:level}/android.jar
+					//  prebuilts/sdk/{version:level}/public/android.jar
 					// Add android.jar files from the api_levels_annotations_dirs directories to try
 					// to satisfy these patterns.  If Metalava can't find a match for an API level
 					// between 1 and 28 in at least one pattern it will fail.
@@ -646,11 +646,11 @@
 	})
 
 	// Generate the list of --android-jar-pattern options. The order matters so the first one which
-	// matches will be the one that is used for a specific api level..
+	// matches will be the one that is used for a specific api level.
 	for _, sdkDir := range sdkDirs {
 		for _, dir := range dirs {
 			addPattern := func(jarFilename string) {
-				cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename))
+				cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:level}/%s/%s", dir, sdkDir, jarFilename))
 			}
 
 			if sdkDir == "module-lib" || sdkDir == "system-server" {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 1e8362c..37740ae 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -88,7 +88,7 @@
 		cmdline := String(sboxProto.Commands[0].Command)
 		android.AssertStringContainsEquals(t, "api-versions generation flag", cmdline, "--generate-api-levels", c.generate_xml)
 		if c.expectedJarFilename != "" {
-			expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename
+			expected := "--android-jar-pattern ./{version:level}/public/" + c.expectedJarFilename
 			if !strings.Contains(cmdline, expected) {
 				t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, cmdline)
 			}
@@ -142,8 +142,8 @@
 	patterns := getAndroidJarPatternsForDroidstubs(t, "public")
 
 	android.AssertArrayString(t, "order of patterns", []string{
-		"--android-jar-pattern somedir/%/public/android.jar",
-		"--android-jar-pattern someotherdir/%/public/android.jar",
+		"--android-jar-pattern somedir/{version:level}/public/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/public/android.jar",
 	}, patterns)
 }
 
@@ -151,10 +151,10 @@
 	patterns := getAndroidJarPatternsForDroidstubs(t, "system")
 
 	android.AssertArrayString(t, "order of patterns", []string{
-		"--android-jar-pattern somedir/%/system/android.jar",
-		"--android-jar-pattern someotherdir/%/system/android.jar",
-		"--android-jar-pattern somedir/%/public/android.jar",
-		"--android-jar-pattern someotherdir/%/public/android.jar",
+		"--android-jar-pattern somedir/{version:level}/system/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/system/android.jar",
+		"--android-jar-pattern somedir/{version:level}/public/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/public/android.jar",
 	}, patterns)
 }
 
@@ -162,12 +162,12 @@
 	patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib")
 
 	android.AssertArrayString(t, "order of patterns", []string{
-		"--android-jar-pattern somedir/%/module-lib/android.jar",
-		"--android-jar-pattern someotherdir/%/module-lib/android.jar",
-		"--android-jar-pattern somedir/%/system/android.jar",
-		"--android-jar-pattern someotherdir/%/system/android.jar",
-		"--android-jar-pattern somedir/%/public/android.jar",
-		"--android-jar-pattern someotherdir/%/public/android.jar",
+		"--android-jar-pattern somedir/{version:level}/module-lib/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/module-lib/android.jar",
+		"--android-jar-pattern somedir/{version:level}/system/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/system/android.jar",
+		"--android-jar-pattern somedir/{version:level}/public/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/public/android.jar",
 	}, patterns)
 }
 
@@ -175,14 +175,14 @@
 	patterns := getAndroidJarPatternsForDroidstubs(t, "system-server")
 
 	android.AssertArrayString(t, "order of patterns", []string{
-		"--android-jar-pattern somedir/%/system-server/android.jar",
-		"--android-jar-pattern someotherdir/%/system-server/android.jar",
-		"--android-jar-pattern somedir/%/module-lib/android.jar",
-		"--android-jar-pattern someotherdir/%/module-lib/android.jar",
-		"--android-jar-pattern somedir/%/system/android.jar",
-		"--android-jar-pattern someotherdir/%/system/android.jar",
-		"--android-jar-pattern somedir/%/public/android.jar",
-		"--android-jar-pattern someotherdir/%/public/android.jar",
+		"--android-jar-pattern somedir/{version:level}/system-server/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/system-server/android.jar",
+		"--android-jar-pattern somedir/{version:level}/module-lib/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/module-lib/android.jar",
+		"--android-jar-pattern somedir/{version:level}/system/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/system/android.jar",
+		"--android-jar-pattern somedir/{version:level}/public/android.jar",
+		"--android-jar-pattern someotherdir/{version:level}/public/android.jar",
 	}, patterns)
 }
 
diff --git a/java/kotlin.go b/java/kotlin.go
index e1a3f71..308bb03 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -198,7 +198,7 @@
 			`$kaptProcessor ` +
 			`-Xbuild-file=$kotlinBuildFile && ` +
 			`${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
-			`if [[ -f "$out.pc_state.new" ]]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
+			`if [ -f "$out.pc_state.new" ]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
 			`rm -rf "$srcJarDir"`,
 		CommandDeps: []string{
 			"${config.FindInputDeltaCmd}",
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 6128ce3..4be7d04 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -28,9 +28,6 @@
 	"FloralClocks",
 	"framework-jobscheduler",
 	"framework-minus-apex",
-	// TODO(b/383559945) Remove "framework-minus-apex_jarjar-sharded" once
-	// we remove this module.
-	"framework-minus-apex_jarjar-sharded",
 	"framework-minus-apex-headers",
 	"framework-minus-apex-intdefs",
 	"FrameworksCoreTests",
diff --git a/java/lint.go b/java/lint.go
index ac90e19..9c6b93b 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -470,7 +470,7 @@
 
 	cmd := rule.Command()
 
-	cmd.Flag(`JAVA_OPTS="-Xmx3072m --add-opens java.base/java.util=ALL-UNNAMED"`).
+	cmd.Flag(`JAVA_OPTS="-Xmx4096m --add-opens java.base/java.util=ALL-UNNAMED"`).
 		FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()).
 		FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
 		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
diff --git a/java/robolectric.go b/java/robolectric.go
index 3b2c656..6c137ba 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -20,7 +20,7 @@
 	"android/soong/android"
 	"android/soong/java/config"
 	"android/soong/tradefed"
-
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -28,6 +28,17 @@
 	RegisterRobolectricBuildComponents(android.InitRegistrationContext)
 }
 
+type roboRuntimeOnlyDependencyTag struct {
+	blueprint.BaseDependencyTag
+}
+
+var roboRuntimeOnlyDepTag roboRuntimeOnlyDependencyTag
+
+// Mark this tag so dependencies that use it are excluded from visibility enforcement.
+func (t roboRuntimeOnlyDependencyTag) ExcludeFromVisibilityEnforcement() {}
+
+var _ android.ExcludeFromVisibilityEnforcementTag = roboRuntimeOnlyDepTag
+
 func RegisterRobolectricBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("android_robolectric_test", RobolectricTestFactory)
 	ctx.RegisterModuleType("android_robolectric_runtimes", robolectricRuntimesFactory)
@@ -47,7 +58,6 @@
 var (
 	roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
 	roboRuntimesTag     = dependencyTag{name: "roboRuntimes"}
-	roboRuntimeOnlyTag  = dependencyTag{name: "roboRuntimeOnlyTag"}
 )
 
 type robolectricProperties struct {
@@ -65,10 +75,6 @@
 		Shards *int64
 	}
 
-	// The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric
-	// instead of the one built from source in external/robolectric-shadows.
-	Robolectric_prebuilt_version *string
-
 	// Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectric
 	// to use.  /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows
 	Upstream *bool
@@ -98,6 +104,8 @@
 
 var _ android.TestSuiteModule = (*robolectricTest)(nil)
 
+
+
 func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
 	r.Library.DepsMutator(ctx)
 
@@ -107,21 +115,12 @@
 		ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
 	}
 
-	ctx.AddVariationDependencies(nil, staticLibTag, clearcutJunitLib)
-
-	if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
-		ctx.AddVariationDependencies(nil, staticLibTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
-	} else if !proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
-		if proptools.Bool(r.robolectricProperties.Upstream) {
-			ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib+"_upstream")
-		} else {
-			ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib)
-		}
-	}
+	ctx.AddVariationDependencies(nil, roboRuntimeOnlyDepTag, clearcutJunitLib)
 
 	if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
-		ctx.AddVariationDependencies(nil, roboRuntimeOnlyTag, robolectricCurrentLib+"_upstream")
+		ctx.AddVariationDependencies(nil, roboRuntimeOnlyDepTag, robolectricCurrentLib)
 	} else {
+		ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib)
 		// opting out from strict mode, robolectric_non_strict_mode_permission lib should be added
 		ctx.AddVariationDependencies(nil, staticLibTag, "robolectric_non_strict_mode_permission")
 	}
@@ -197,7 +196,7 @@
 		handleLibDeps(dep)
 	}
 	// handle the runtimeOnly tag for strict_mode
-	for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyTag) {
+	for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyDepTag) {
 		handleLibDeps(dep)
 	}
 
diff --git a/java/robolectric_test.go b/java/robolectric_test.go
index a2474e8..78326ab 100644
--- a/java/robolectric_test.go
+++ b/java/robolectric_test.go
@@ -32,6 +32,11 @@
 	}
 
 	java_library {
+		name: "Robolectric_all-target",
+		srcs: ["Robo.java"]
+	}
+
+	java_library {
 		name: "mockito-robolectric-prebuilt",
 		srcs: ["Mockito.java"]
 	}
diff --git a/python/python.go b/python/python.go
index be9411b..914b77e 100644
--- a/python/python.go
+++ b/python/python.go
@@ -95,6 +95,11 @@
 	// device.
 	Device_common_data []string `android:"path_device_common"`
 
+	// Same as data, but will add dependencies on modules via a device os variation and the
+	// device's first supported arch's variation. Useful for a host test that wants to embed a
+	// module built for device.
+	Device_first_data []string `android:"path_device_first"`
+
 	// list of java modules that provide data that should be installed alongside the test.
 	Java_data []string
 
@@ -456,6 +461,7 @@
 	// expand data files from "data" property.
 	expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)
 	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, p.properties.Device_common_data)...)
+	expandedData = append(expandedData, android.PathsForModuleSrc(ctx, p.properties.Device_first_data)...)
 
 	// Emulate the data property for java_data dependencies.
 	for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) {
diff --git a/python/test.go b/python/test.go
index 9f57bea..37947dd 100644
--- a/python/test.go
+++ b/python/test.go
@@ -68,6 +68,11 @@
 	// device.
 	Device_common_data []string `android:"path_device_common"`
 
+	// Same as data, but will add dependencies on modules via a device os variation and the
+	// device's first supported arch's variation. Useful for a host test that wants to embed a
+	// module built for device.
+	Device_first_data []string `android:"path_device_first"`
+
 	// list of java modules that provide data that should be installed alongside the test.
 	Java_data []string
 
@@ -189,6 +194,9 @@
 	for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Device_common_data) {
 		p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath})
 	}
+	for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Device_first_data) {
+		p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath})
+	}
 
 	if p.isTestHost() && len(p.testProperties.Data_device_bins_both) > 0 {
 		ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) {
diff --git a/rust/builder.go b/rust/builder.go
index e5434ef..8a869aa 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -264,7 +264,7 @@
 		libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
 	}
 	for _, lib := range deps.DyLibs {
-		libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
+		libFlags = append(libFlags, "--extern force:"+lib.CrateName+"="+lib.Path.String())
 	}
 	for _, proc_macro := range deps.ProcMacros {
 		libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
diff --git a/rust/config/global.go b/rust/config/global.go
index 66ffc0b..0a4b314 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -42,6 +42,8 @@
 	}
 
 	GlobalRustFlags = []string{
+		// Allow `--extern force:foo` for dylib support
+		"-Z unstable-options",
 		"-Z stack-protector=strong",
 		"-Z remap-cwd-prefix=.",
 		"-C debuginfo=2",
diff --git a/rust/library.go b/rust/library.go
index 14a2b65..2d62dcf 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -457,13 +457,6 @@
 
 	cfgs := library.baseCompiler.Properties.Cfgs.GetOrDefault(ctx, nil)
 
-	if library.dylib() {
-		// We need to add a dependency on std in order to link crates as dylibs.
-		// The hack to add this dependency is guarded by the following cfg so
-		// that we don't force a dependency when it isn't needed.
-		cfgs = append(cfgs, "android_dylib")
-	}
-
 	cfgFlags := cfgsToFlags(cfgs)
 
 	flags.RustFlags = append(flags.RustFlags, cfgFlags...)
diff --git a/rust/library_test.go b/rust/library_test.go
index 256cb35..e5fd5e0 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -89,22 +89,6 @@
 	}
 }
 
-// Check that we are passing the android_dylib config flag
-func TestAndroidDylib(t *testing.T) {
-	ctx := testRust(t, `
-		rust_library_host_dylib {
-			name: "libfoo",
-			srcs: ["foo.rs"],
-			crate_name: "foo",
-		}`)
-
-	libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
-
-	if !strings.Contains(libfooDylib.Args["rustcFlags"], "--cfg 'android_dylib'") {
-		t.Errorf("missing android_dylib cfg flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
-	}
-}
-
 func TestValidateLibraryStem(t *testing.T) {
 	testRustError(t, "crate_name must be defined.", `
 			rust_library_host {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 90c1f61..9f65dec 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -424,11 +424,11 @@
 		}`)
 
 	fooRustc := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
-	if !strings.Contains(fooRustc.Args["libFlags"], "--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so") {
-		t.Errorf("--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
+	if !strings.Contains(fooRustc.Args["libFlags"], "--extern force:bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so") {
+		t.Errorf("--extern force:bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
 	}
-	if !strings.Contains(fooRustc.Args["libFlags"], "--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so") {
-		t.Errorf("--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
+	if !strings.Contains(fooRustc.Args["libFlags"], "--extern force:baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so") {
+		t.Errorf("--extern force:baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
 	}
 }
 
diff --git a/ui/build/build.go b/ui/build/build.go
index 110ee95..1dc6dbd 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -87,6 +87,17 @@
 	// without changing the command line every time.  Avoids rebuilds
 	// when using ninja.
 	writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_number.txt", buildNumber)
+
+	hostname, ok := config.environ.Get("BUILD_HOSTNAME")
+	if !ok {
+		var err error
+		hostname, err = os.Hostname()
+		if err != nil {
+			ctx.Println("Failed to read hostname:", err)
+			hostname = "unknown"
+		}
+	}
+	writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname)
 }
 
 var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 4dfb710..acd5254 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -200,18 +200,10 @@
 	//     fi
 	cmd.Environment.Unset("SOONG_USE_PARTIAL_COMPILE")
 
-	hostname, ok := cmd.Environment.Get("BUILD_HOSTNAME")
 	// Unset BUILD_HOSTNAME during kati run to avoid kati rerun, kati will use BUILD_HOSTNAME from a file.
 	cmd.Environment.Unset("BUILD_HOSTNAME")
-	if !ok {
-		hostname, err = os.Hostname()
-		if err != nil {
-			ctx.Println("Failed to read hostname:", err)
-			hostname = "unknown"
-		}
-	}
-	writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname)
-	_, ok = cmd.Environment.Get("BUILD_NUMBER")
+
+	_, ok := cmd.Environment.Get("BUILD_NUMBER")
 	// Unset BUILD_NUMBER during kati run to avoid kati rerun, kati will use BUILD_NUMBER from a file.
 	cmd.Environment.Unset("BUILD_NUMBER")
 	if ok {
diff --git a/ui/metrics/proc/status_linux_test.go b/ui/metrics/proc/status_linux_test.go
index 6709850..0edc400 100644
--- a/ui/metrics/proc/status_linux_test.go
+++ b/ui/metrics/proc/status_linux_test.go
@@ -1,7 +1,6 @@
 package proc
 
 import (
-	"fmt"
 	"path/filepath"
 	"reflect"
 	"strconv"
@@ -29,7 +28,6 @@
 		t.Fatalf("got %v, want nil for error", err)
 	}
 
-	fmt.Printf("%d %d\b", status.VmPeak, expectedStatus.VmPeak)
 	if !reflect.DeepEqual(status, expectedStatus) {
 		t.Errorf("got %v, expecting %v for ProcStatus", status, expectedStatus)
 	}