Merge "Use test ([) instead of extended test ([[) in if statements" 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/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/variable.go b/android/variable.go
index a60cad5..ec84274 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -625,24 +625,25 @@
 	OdmDlkmSecurityPatch    string `json:",omitempty"`
 
 	// Boot image stuff
-	BuildingRamdiskImage            bool     `json:",omitempty"`
-	ProductBuildBootImage           bool     `json:",omitempty"`
-	ProductBuildVendorBootImage     string   `json:",omitempty"`
-	ProductBuildInitBootImage       bool     `json:",omitempty"`
-	BoardUsesRecoveryAsBoot         bool     `json:",omitempty"`
-	BoardPrebuiltBootimage          string   `json:",omitempty"`
-	BoardPrebuiltInitBootimage      string   `json:",omitempty"`
-	BoardBootimagePartitionSize     string   `json:",omitempty"`
-	BoardInitBootimagePartitionSize string   `json:",omitempty"`
-	BoardBootHeaderVersion          string   `json:",omitempty"`
-	TargetKernelPath                string   `json:",omitempty"`
-	BoardUsesGenericKernelImage     bool     `json:",omitempty"`
-	BootSecurityPatch               string   `json:",omitempty"`
-	InitBootSecurityPatch           string   `json:",omitempty"`
-	BoardIncludeDtbInBootimg        bool     `json:",omitempty"`
-	InternalKernelCmdline           []string `json:",omitempty"`
-	InternalBootconfig              []string `json:",omitempty"`
-	InternalBootconfigFile          string   `json:",omitempty"`
+	BuildingRamdiskImage              bool     `json:",omitempty"`
+	ProductBuildBootImage             bool     `json:",omitempty"`
+	ProductBuildVendorBootImage       string   `json:",omitempty"`
+	ProductBuildInitBootImage         bool     `json:",omitempty"`
+	BoardUsesRecoveryAsBoot           bool     `json:",omitempty"`
+	BoardPrebuiltBootimage            string   `json:",omitempty"`
+	BoardPrebuiltInitBootimage        string   `json:",omitempty"`
+	BoardBootimagePartitionSize       string   `json:",omitempty"`
+	BoardVendorBootimagePartitionSize string   `json:",omitempty"`
+	BoardInitBootimagePartitionSize   string   `json:",omitempty"`
+	BoardBootHeaderVersion            string   `json:",omitempty"`
+	TargetKernelPath                  string   `json:",omitempty"`
+	BoardUsesGenericKernelImage       bool     `json:",omitempty"`
+	BootSecurityPatch                 string   `json:",omitempty"`
+	InitBootSecurityPatch             string   `json:",omitempty"`
+	BoardIncludeDtbInBootimg          bool     `json:",omitempty"`
+	InternalKernelCmdline             []string `json:",omitempty"`
+	InternalBootconfig                []string `json:",omitempty"`
+	InternalBootconfigFile            string   `json:",omitempty"`
 
 	// Super image stuff
 	ProductUseDynamicPartitions       bool                                     `json:",omitempty"`
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/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/filesystem/android_device.go b/filesystem/android_device.go
index ea46556..19e93ae 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -22,21 +22,27 @@
 )
 
 type PartitionNameProperties struct {
-	// Name of the Boot_partition_name partition filesystem module
+	// Name of the boot partition filesystem module
 	Boot_partition_name *string
-	// Name of the System partition filesystem module
+	// Name of the vendor boot partition filesystem module
+	Vendor_boot_partition_name *string
+	// Name of the init boot partition filesystem module
+	Init_boot_partition_name *string
+	// Name of the system partition filesystem module
 	System_partition_name *string
-	// Name of the System_ext partition filesystem module
+	// Name of the system_ext partition filesystem module
 	System_ext_partition_name *string
-	// Name of the Product partition filesystem module
+	// Name of the product partition filesystem module
 	Product_partition_name *string
-	// Name of the Vendor partition filesystem module
+	// Name of the vendor partition filesystem module
 	Vendor_partition_name *string
-	// Name of the Odm partition filesystem module
+	// Name of the odm partition filesystem module
 	Odm_partition_name *string
+	// Name of the recovery partition filesystem module
+	Recovery_partition_name *string
 	// The vbmeta partition and its "chained" partitions
 	Vbmeta_partitions []string
-	// Name of the Userdata partition filesystem module
+	// Name of the userdata partition filesystem module
 	Userdata_partition_name *string
 }
 
@@ -62,7 +68,7 @@
 func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
 	addDependencyIfDefined := func(dep *string) {
 		if dep != nil {
-			ctx.AddDependency(ctx.Module(), filesystemDepTag, proptools.String(dep))
+			ctx.AddFarVariationDependencies(nil, filesystemDepTag, proptools.String(dep))
 		}
 	}
 
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 5845d59..43fd390 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
 
diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go
index 4e80720..914d35b 100644
--- a/fsgen/boot_imgs.go
+++ b/fsgen/boot_imgs.go
@@ -109,17 +109,27 @@
 		vendorBootConfigImg = proptools.StringPtr(":" + name)
 	}
 
+	var partitionSize *int64
+	if partitionVariables.BoardVendorBootimagePartitionSize != "" {
+		// Base of zero will allow base 10 or base 16 if starting with 0x
+		parsed, err := strconv.ParseInt(partitionVariables.BoardVendorBootimagePartitionSize, 0, 64)
+		if err != nil {
+			ctx.ModuleErrorf("BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardVendorBootimagePartitionSize)
+		}
+		partitionSize = &parsed
+	}
+
 	ctx.CreateModule(
 		filesystem.BootimgFactory,
 		&filesystem.BootimgProperties{
 			Boot_image_type:    proptools.StringPtr("vendor_boot"),
 			Ramdisk_module:     proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_ramdisk")),
 			Header_version:     proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
+			Partition_size:     partitionSize,
 			Use_avb:            avbInfo.avbEnable,
 			Avb_mode:           avbInfo.avbMode,
 			Avb_private_key:    avbInfo.avbkeyFilegroup,
 			Avb_rollback_index: avbInfo.avbRollbackIndex,
-			Avb_algorithm:      avbInfo.avbAlgorithm,
 			Dtb_prebuilt:       dtbPrebuilt,
 			Cmdline:            cmdline,
 			Bootconfig:         vendorBootConfigImg,
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 6474397..0160159 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -211,6 +211,18 @@
 	if android.InList("userdata", f.properties.Generated_partition_types) {
 		partitionProps.Userdata_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "userdata"))
 	}
+	if android.InList("recovery", f.properties.Generated_partition_types) {
+		partitionProps.Recovery_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "recovery"))
+	}
+	if f.properties.Boot_image != "" {
+		partitionProps.Boot_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "boot"))
+	}
+	if f.properties.Vendor_boot_image != "" {
+		partitionProps.Vendor_boot_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_boot"))
+	}
+	if f.properties.Init_boot_image != "" {
+		partitionProps.Init_boot_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "init_boot"))
+	}
 	partitionProps.Vbmeta_partitions = vbmetaPartitions
 
 	ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
@@ -339,22 +351,7 @@
 		}
 	case "recovery":
 		dirs := append(commonPartitionDirs, []string{
-			"odm_file_contexts",
-			"odm_property_contexts",
-			"plat_file_contexts",
-			"plat_property_contexts",
-			"plat_service_contexts",
-			"product_file_contexts",
-			"product_property_contexts",
-			"product_service_contexts",
 			"sdcard",
-			"sepolicy",
-			"system_ext_file_contexts",
-			"system_ext_property_contexts",
-			"system_ext_service_contexts",
-			"vendor_file_contexts",
-			"vendor_property_contexts",
-			"vendor_service_contexts",
 		}...)
 
 		dirsWithRoot := make([]string, len(dirs))
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index de0a1cb..9327669 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -150,7 +150,23 @@
 				},
 				"ramdisk":        {},
 				"vendor_ramdisk": {},
-				"recovery":       {},
+				"recovery": {
+					"sepolicy.recovery":                     defaultDepCandidateProps(ctx.Config()),
+					"plat_file_contexts.recovery":           defaultDepCandidateProps(ctx.Config()),
+					"plat_service_contexts.recovery":        defaultDepCandidateProps(ctx.Config()),
+					"plat_property_contexts.recovery":       defaultDepCandidateProps(ctx.Config()),
+					"system_ext_file_contexts.recovery":     defaultDepCandidateProps(ctx.Config()),
+					"system_ext_service_contexts.recovery":  defaultDepCandidateProps(ctx.Config()),
+					"system_ext_property_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+					"vendor_file_contexts.recovery":         defaultDepCandidateProps(ctx.Config()),
+					"vendor_service_contexts.recovery":      defaultDepCandidateProps(ctx.Config()),
+					"vendor_property_contexts.recovery":     defaultDepCandidateProps(ctx.Config()),
+					"odm_file_contexts.recovery":            defaultDepCandidateProps(ctx.Config()),
+					"odm_property_contexts.recovery":        defaultDepCandidateProps(ctx.Config()),
+					"product_file_contexts.recovery":        defaultDepCandidateProps(ctx.Config()),
+					"product_service_contexts.recovery":     defaultDepCandidateProps(ctx.Config()),
+					"product_property_contexts.recovery":    defaultDepCandidateProps(ctx.Config()),
+				},
 			},
 			fsDepsMutex:                     sync.Mutex{},
 			moduleToInstallationProps:       map[string]installationProperties{},
diff --git a/java/aar.go b/java/aar.go
index c09ed9e..3c62441 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1644,5 +1644,5 @@
 }
 
 func (a *AARImport) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
-	dpInfo.Jars = append(dpInfo.Jars, a.headerJarFile.String(), a.rJar.String())
+	dpInfo.Jars = append(dpInfo.Jars, a.implementationJarFile.String(), a.rJar.String())
 }
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/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/config/config.go b/java/config/config.go
index 19d6952..7c29722 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/java.go b/java/java.go
index 64bc959..a975ca6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -3020,7 +3020,7 @@
 // Collect information for opening IDE project files in java/jdeps.go.
 
 func (j *Import) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
-	dpInfo.Jars = append(dpInfo.Jars, j.combinedHeaderFile.String())
+	dpInfo.Jars = append(dpInfo.Jars, j.combinedImplementationFile.String())
 }
 
 func (j *Import) IDECustomizedModuleName() string {
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/robolectric.go b/java/robolectric.go
index 5f46267..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)
@@ -41,12 +52,12 @@
 }
 
 const robolectricCurrentLib = "Robolectric_all-target"
+const clearcutJunitLib = "ClearcutJunitListenerAar"
 const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt"
 
 var (
 	roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
 	roboRuntimesTag     = dependencyTag{name: "roboRuntimes"}
-	roboRuntimeOnlyTag  = dependencyTag{name: "roboRuntimeOnlyTag"}
 )
 
 type robolectricProperties struct {
@@ -64,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
@@ -97,6 +104,8 @@
 
 var _ android.TestSuiteModule = (*robolectricTest)(nil)
 
+
+
 func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
 	r.Library.DepsMutator(ctx)
 
@@ -106,19 +115,12 @@
 		ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
 	}
 
-	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")
 	}
@@ -194,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 4775bac..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"]
 	}
@@ -44,6 +49,12 @@
 	java_library {
 		name: "junitxml",
 		srcs: ["JUnitXml.java"]
+
+	}
+
+	java_library {
+		name: "ClearcutJunitListenerAar",
+		srcs: ["Runtime.java"]
 	}
 
 	java_library_host {
diff --git a/systemfeatures/system_features.go b/systemfeatures/system_features.go
index 0c1a566..b8dacfb 100644
--- a/systemfeatures/system_features.go
+++ b/systemfeatures/system_features.go
@@ -20,6 +20,8 @@
 
 	"android/soong/android"
 	"android/soong/genrule"
+
+	"github.com/google/blueprint/proptools"
 )
 
 var (
@@ -39,6 +41,11 @@
 	properties struct {
 		// The fully qualified class name for the generated code, e.g., com.android.Foo
 		Full_class_name string
+		// Whether to generate only a simple metadata class with details about the full API surface.
+		// This is useful for tools that rely on the mapping from feature names to their generated
+		// method names, but don't want the fully generated API class (e.g., for linting).
+
+		Metadata_only *bool
 	}
 	outputFiles android.WritablePaths
 }
@@ -72,6 +79,7 @@
 		Flag(m.properties.Full_class_name).
 		FlagForEachArg("--feature=", features).
 		FlagWithArg("--readonly=", fmt.Sprint(ctx.Config().ReleaseUseSystemFeatureBuildFlags())).
+		FlagWithArg("--metadata-only=", fmt.Sprint(proptools.Bool(m.properties.Metadata_only))).
 		FlagWithOutput(" > ", outputFile)
 	rule.Build(ctx.ModuleName(), "Generating systemfeatures srcs filegroup")
 
@@ -97,6 +105,7 @@
 func JavaSystemFeaturesSrcsFactory() android.Module {
 	module := &javaSystemFeaturesSrcs{}
 	module.AddProperties(&module.properties)
+	module.properties.Metadata_only = proptools.BoolPtr(false)
 	android.InitAndroidModule(module)
 	return module
 }