Merge "Remove Wno-deprecated-dynamic-exception-spec" into main
diff --git a/android/config.go b/android/config.go
index ec79a7d..87aacd5 100644
--- a/android/config.go
+++ b/android/config.go
@@ -2286,6 +2286,10 @@
 	return PathsForSource(ctx, c.productVariables.VendorPropFiles)
 }
 
+func (c *config) ExtraAllowedDepsTxt() string {
+	return String(c.productVariables.ExtraAllowedDepsTxt)
+}
+
 func (c *config) EnableUffdGc() string {
 	return String(c.productVariables.EnableUffdGc)
 }
diff --git a/android/variable.go b/android/variable.go
index 1de8796..4b61827 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -543,6 +543,8 @@
 
 	PartitionVarsForSoongMigrationOnlyDoNotUse PartitionVariables
 
+	ExtraAllowedDepsTxt *string `json:",omitempty"`
+
 	AdbKeys *string `json:",omitempty"`
 
 	DeviceMatrixFile       []string `json:",omitempty"`
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 263e0a5..d46104e 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -59,9 +59,9 @@
 
 	// Diff two given lists while ignoring comments in the allowed deps file.
 	diffAllowedApexDepsInfoRule = pctx.AndroidStaticRule("diffAllowedApexDepsInfoRule", blueprint.RuleParams{
-		Description: "Diff ${allowed_deps} and ${new_allowed_deps}",
+		Description: "Diff ${allowed_deps_list} and ${new_allowed_deps}",
 		Command: `
-			if grep -v '^#' ${allowed_deps} | diff -B - ${new_allowed_deps}; then
+			if grep -v -h '^#' ${allowed_deps_list} | sort -u -f| diff -B -u - ${new_allowed_deps}; then
 			   touch ${out};
 			else
 				echo;
@@ -85,54 +85,62 @@
 				exit 1;
 			fi;
 		`,
-	}, "allowed_deps", "new_allowed_deps")
+	}, "allowed_deps_list", "new_allowed_deps")
 )
 
 func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	allowedDepsSources := []android.OptionalPath{android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt")}
+	extraAllowedDepsPath := ctx.Config().ExtraAllowedDepsTxt()
+	if extraAllowedDepsPath != "" {
+		allowedDepsSources = append(allowedDepsSources, android.ExistentPathForSource(ctx, extraAllowedDepsPath))
+	}
 	updatableFlatLists := android.Paths{}
 	ctx.VisitAllModules(func(module android.Module) {
 		if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok {
 			apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
 			if path := binaryInfo.FlatListPath(); path != nil {
 				if binaryInfo.Updatable() || apexInfo.Updatable {
-					if strings.HasPrefix(module.String(), "com.android.") {
-						updatableFlatLists = append(updatableFlatLists, path)
-					}
+					updatableFlatLists = append(updatableFlatLists, path)
 				}
 			}
 		}
 	})
-
-	allowedDepsSource := android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt")
 	newAllowedDeps := android.PathForOutput(ctx, "apex", "depsinfo", "new-allowed-deps.txt")
 	s.allowedApexDepsInfoCheckResult = android.PathForOutput(ctx, newAllowedDeps.Rel()+".check")
-
-	if !allowedDepsSource.Valid() {
+	hasOneValidDepsPath := false
+	for _, allowedDepsSource := range allowedDepsSources {
+		if allowedDepsSource.Valid() {
+			hasOneValidDepsPath = true
+			updatableFlatLists = append(updatableFlatLists, allowedDepsSource.Path())
+		}
+	}
+	allowedDepsStrList := make([]string, len(allowedDepsSources))
+	for _, value := range allowedDepsSources {
+		allowedDepsStrList = append(allowedDepsStrList, value.String())
+	}
+	allowedDepsListString := strings.Join(allowedDepsStrList, " ")
+	if !hasOneValidDepsPath {
 		// Unbundled projects may not have packages/modules/common/ checked out; ignore those.
 		ctx.Build(pctx, android.BuildParams{
 			Rule:   android.Touch,
 			Output: s.allowedApexDepsInfoCheckResult,
 		})
 	} else {
-		allowedDeps := allowedDepsSource.Path()
-
 		ctx.Build(pctx, android.BuildParams{
 			Rule:   generateApexDepsInfoFilesRule,
-			Inputs: append(updatableFlatLists, allowedDeps),
+			Inputs: updatableFlatLists,
 			Output: newAllowedDeps,
 		})
-
 		ctx.Build(pctx, android.BuildParams{
 			Rule:   diffAllowedApexDepsInfoRule,
 			Input:  newAllowedDeps,
 			Output: s.allowedApexDepsInfoCheckResult,
 			Args: map[string]string{
-				"allowed_deps":     allowedDeps.String(),
-				"new_allowed_deps": newAllowedDeps.String(),
+				"allowed_deps_list": allowedDepsListString,
+				"new_allowed_deps":  newAllowedDeps.String(),
 			},
 		})
 	}
-
 	ctx.Phony("apex-allowed-deps-check", s.allowedApexDepsInfoCheckResult)
 }
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 465789c..e1a9582 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2129,79 +2129,7 @@
 	android.AssertStringDoesContain(t, "cflags", cflags, "-target aarch64-linux-android29")
 }
 
-func TestTrackAllowedDepsForAndroidApex(t *testing.T) {
-	t.Parallel()
-	ctx := testApex(t, `
-		apex {
-			name: "com.android.myapex",
-			key: "myapex.key",
-			updatable: true,
-			native_shared_libs: [
-				"mylib",
-				"yourlib",
-			],
-			min_sdk_version: "29",
-		}
-
-		apex {
-			name: "myapex2",
-			key: "myapex.key",
-			updatable: false,
-			native_shared_libs: ["yourlib"],
-		}
-
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "mylib",
-			srcs: ["mylib.cpp"],
-			shared_libs: ["libbar"],
-			min_sdk_version: "29",
-			apex_available: ["com.android.myapex"],
-		}
-
-		cc_library {
-			name: "libbar",
-			stubs: { versions: ["29", "30"] },
-		}
-
-		cc_library {
-			name: "yourlib",
-			srcs: ["mylib.cpp"],
-			min_sdk_version: "29",
-			apex_available: ["com.android.myapex", "myapex2", "//apex_available:platform"],
-		}
-	`, withFiles(android.MockFS{
-		"packages/modules/common/build/allowed_deps.txt": nil,
-	}),
-		android.FixtureMergeMockFs(android.MockFS{
-			"system/sepolicy/apex/com.android.myapex-file_contexts": nil,
-		}))
-
-	depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
-	inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
-
-	android.AssertStringListContains(t, "updatable com.android.myapex should generate depsinfo file", inputs,
-		"out/soong/.intermediates/com.android.myapex/android_common_com.android.myapex/depsinfo/flatlist.txt")
-	android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
-		"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
-
-	myapex := ctx.ModuleForTests("com.android.myapex", "android_common_com.android.myapex")
-	flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
-		myapex.Output("depsinfo/flatlist.txt")), "\n")
-	android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
-		flatlist, "libbar(minSdkVersion:(no version)) (external)")
-	android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
-		flatlist, "mylib:(minSdkVersion:29)")
-	android.AssertStringListContains(t, "track platform-available lib",
-		flatlist, "yourlib(minSdkVersion:29)")
-}
-
-func TestNotTrackAllowedDepsForNonAndroidApex(t *testing.T) {
+func TestTrackAllowedDeps(t *testing.T) {
 	t.Parallel()
 	ctx := testApex(t, `
 		apex {
@@ -2253,17 +2181,174 @@
 
 	depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
 	inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
-	android.AssertStringListDoesNotContain(t, "updatable myapex should generate depsinfo file", inputs,
+	android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
 		"out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
 	android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
 		"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
+
+	myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
+	flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+		myapex.Output("depsinfo/flatlist.txt")), "\n")
+	android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+		flatlist, "libbar(minSdkVersion:(no version)) (external)")
+	android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
+		flatlist, "mylib:(minSdkVersion:29)")
+	android.AssertStringListContains(t, "track platform-available lib",
+		flatlist, "yourlib(minSdkVersion:29)")
+}
+
+func TestTrackCustomAllowedDepsInvalidDefaultTxt(t *testing.T) {
+	t.Parallel()
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			updatable: true,
+			native_shared_libs: [
+				"mylib",
+				"yourlib",
+			],
+			min_sdk_version: "29",
+		}
+
+		apex {
+			name: "myapex2",
+			key: "myapex.key",
+			updatable: false,
+			native_shared_libs: ["yourlib"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["libbar"],
+			min_sdk_version: "29",
+			apex_available: ["myapex"],
+		}
+
+		cc_library {
+			name: "libbar",
+			stubs: { versions: ["29", "30"] },
+		}
+
+		cc_library {
+			name: "yourlib",
+			srcs: ["mylib.cpp"],
+			min_sdk_version: "29",
+			apex_available: ["myapex", "myapex2", "//apex_available:platform"],
+		}
+	`, withFiles(android.MockFS{
+		"packages/modules/common/build/custom_allowed_deps.txt": nil,
+	}),
+		android.FixtureModifyProductVariables(
+			func(variables android.FixtureProductVariables) {
+				variables.ExtraAllowedDepsTxt = proptools.StringPtr("packages/modules/common/build/custom_allowed_deps.txt")
+			},
+		))
+
+	depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+	inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
+	android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
+		"out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
+	android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
+		"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
+
+	myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
+	flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+		myapex.Output("depsinfo/flatlist.txt")), "\n")
+	android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+		flatlist, "libbar(minSdkVersion:(no version)) (external)")
+	android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
+		flatlist, "mylib:(minSdkVersion:29)")
+	android.AssertStringListContains(t, "track platform-available lib",
+		flatlist, "yourlib(minSdkVersion:29)")
+}
+
+func TestTrackCustomAllowedDepsWithDefaultTxt(t *testing.T) {
+	t.Parallel()
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			updatable: true,
+			native_shared_libs: [
+				"mylib",
+				"yourlib",
+			],
+			min_sdk_version: "29",
+		}
+
+		apex {
+			name: "myapex2",
+			key: "myapex.key",
+			updatable: false,
+			native_shared_libs: ["yourlib"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["libbar"],
+			min_sdk_version: "29",
+			apex_available: ["myapex"],
+		}
+
+		cc_library {
+			name: "libbar",
+			stubs: { versions: ["29", "30"] },
+		}
+
+		cc_library {
+			name: "yourlib",
+			srcs: ["mylib.cpp"],
+			min_sdk_version: "29",
+			apex_available: ["myapex", "myapex2", "//apex_available:platform"],
+		}
+	`, withFiles(android.MockFS{
+		"packages/modules/common/build/custom_allowed_deps.txt": nil,
+		"packages/modules/common/build/allowed_deps.txt":        nil,
+	}),
+		android.FixtureModifyProductVariables(
+			func(variables android.FixtureProductVariables) {
+				variables.ExtraAllowedDepsTxt = proptools.StringPtr("packages/modules/common/build/custom_allowed_deps.txt")
+			},
+		))
+
+	depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+	inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
+	android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
+		"out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
+	android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
+		"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
+
+	myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
+	flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+		myapex.Output("depsinfo/flatlist.txt")), "\n")
+	android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+		flatlist, "libbar(minSdkVersion:(no version)) (external)")
+	android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
+		flatlist, "mylib:(minSdkVersion:29)")
+	android.AssertStringListContains(t, "track platform-available lib",
+		flatlist, "yourlib(minSdkVersion:29)")
 }
 
 func TestTrackAllowedDeps_SkipWithoutAllowedDepsTxt(t *testing.T) {
 	t.Parallel()
 	ctx := testApex(t, `
 		apex {
-			name: "com.android.myapex",
+			name: "myapex",
 			key: "myapex.key",
 			updatable: true,
 			min_sdk_version: "29",
@@ -2274,10 +2359,7 @@
 			public_key: "testkey.avbpubkey",
 			private_key: "testkey.pem",
 		}
-	`,
-		android.FixtureMergeMockFs(android.MockFS{
-			"system/sepolicy/apex/com.android.myapex-file_contexts": nil,
-		}))
+	`)
 	depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
 	if nil != depsinfo.MaybeRule("generateApexDepsInfoFilesRule").Output {
 		t.Error("apex_depsinfo_singleton shouldn't run when allowed_deps.txt doesn't exist")
diff --git a/cc/config/OWNERS b/cc/config/OWNERS
index c78b6d5..2668fdd 100644
--- a/cc/config/OWNERS
+++ b/cc/config/OWNERS
@@ -1,3 +1,2 @@
 per-file vndk.go = smoreland@google.com, victoryang@google.com
-per-file clang.go,global.go,tidy.go = appujee@google.com, pirama@google.com, srhines@google.com, yabinc@google.com, yikong@google.com, zijunzhao@google.com
-
+per-file clang.go,global.go,tidy.go = appujee@google.com, pirama@google.com, srhines@google.com, yabinc@google.com, yikong@google.com, rprichard@google.com, sharjeelkhan@google.com
\ No newline at end of file
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 6a939e8..98a56d7 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -25,6 +25,8 @@
 )
 
 type PartitionNameProperties struct {
+	// Name of the super partition filesystem module
+	Super_partition_name *string
 	// Name of the boot partition filesystem module
 	Boot_partition_name *string
 	// Name of the vendor boot partition filesystem module
@@ -86,6 +88,11 @@
 	blueprint.BaseDependencyTag
 }
 
+type superPartitionDepTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+var superPartitionDepTag superPartitionDepTagType
 var filesystemDepTag partitionDepTagType
 
 func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -95,6 +102,9 @@
 		}
 	}
 
+	if a.partitionProps.Super_partition_name != nil {
+		ctx.AddDependency(ctx.Module(), superPartitionDepTag, *a.partitionProps.Super_partition_name)
+	}
 	addDependencyIfDefined(a.partitionProps.Boot_partition_name)
 	addDependencyIfDefined(a.partitionProps.Init_boot_partition_name)
 	addDependencyIfDefined(a.partitionProps.Vendor_boot_partition_name)
@@ -134,6 +144,44 @@
 func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	a.buildTargetFilesZip(ctx)
 	var deps []android.Path
+	if proptools.String(a.partitionProps.Super_partition_name) != "" {
+		superImage := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+		if info, ok := android.OtherModuleProvider(ctx, superImage, SuperImageProvider); ok {
+			assertUnset := func(prop *string, propName string) {
+				if prop != nil && *prop != "" {
+					ctx.PropertyErrorf(propName, "Cannot be set because it's already part of the super image")
+				}
+			}
+			for _, subPartitionType := range android.SortedKeys(info.SubImageInfo) {
+				switch subPartitionType {
+				case "system":
+					assertUnset(a.partitionProps.System_partition_name, "system_partition_name")
+				case "system_ext":
+					assertUnset(a.partitionProps.System_ext_partition_name, "system_ext_partition_name")
+				case "system_dlkm":
+					assertUnset(a.partitionProps.System_dlkm_partition_name, "system_dlkm_partition_name")
+				case "system_other":
+					// TODO
+				case "product":
+					assertUnset(a.partitionProps.Product_partition_name, "product_partition_name")
+				case "vendor":
+					assertUnset(a.partitionProps.Vendor_partition_name, "vendor_partition_name")
+				case "vendor_dlkm":
+					assertUnset(a.partitionProps.Vendor_dlkm_partition_name, "vendor_dlkm_partition_name")
+				case "odm":
+					assertUnset(a.partitionProps.Odm_partition_name, "odm_partition_name")
+				case "odm_dlkm":
+					assertUnset(a.partitionProps.Odm_dlkm_partition_name, "odm_dlkm_partition_name")
+				default:
+					ctx.ModuleErrorf("Unsupported sub-partition of super partition: %q", subPartitionType)
+				}
+			}
+
+			deps = append(deps, info.SuperImage)
+		} else {
+			ctx.ModuleErrorf("Expected super image dep to provide SuperImageProvider")
+		}
+	}
 	ctx.VisitDirectDepsWithTag(filesystemDepTag, func(m android.Module) {
 		imageOutput, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider)
 		if !ok {
@@ -208,12 +256,6 @@
 		toCopy = append(toCopy, targetFilesZipCopy{a.partitionProps.Recovery_partition_name, "VENDOR_BOOT/RAMDISK"})
 	}
 
-	// Create an IMAGES/ subdirectory
-	builder.Command().Textf("mkdir -p %s/IMAGES/", targetFilesDir.String())
-	if a.deviceProps.Bootloader != nil {
-		builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader))).Textf(" %s/IMAGES/bootloader", targetFilesDir.String())
-	}
-
 	for _, zipCopy := range toCopy {
 		if zipCopy.srcModule == nil {
 			continue
@@ -234,7 +276,6 @@
 			// Create the ROOT partition in target_files.zip
 			builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", fsInfo.RootDir, targetFilesDir.String())
 		}
-		builder.Command().Textf("cp %s %s/IMAGES/", fsInfo.Output, targetFilesDir.String())
 	}
 	// Copy cmdline, kernel etc. files of boot images
 	if a.partitionProps.Vendor_boot_partition_name != nil {
@@ -243,10 +284,10 @@
 		builder.Command().Textf("echo %s > %s/VENDOR_BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
 		builder.Command().Textf("echo %s > %s/VENDOR_BOOT/vendor_cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
 		if bootImgInfo.Dtb != nil {
-			builder.Command().Textf("cp %s %s/VENDOR_BOOT/dtb", bootImgInfo.Dtb, targetFilesDir)
+			builder.Command().Textf("cp ").Input(bootImgInfo.Dtb).Textf(" %s/VENDOR_BOOT/dtb", targetFilesDir)
 		}
 		if bootImgInfo.Bootconfig != nil {
-			builder.Command().Textf("cp %s %s/VENDOR_BOOT/vendor_bootconfig", bootImgInfo.Bootconfig, targetFilesDir)
+			builder.Command().Textf("cp ").Input(bootImgInfo.Bootconfig).Textf(" %s/VENDOR_BOOT/vendor_bootconfig", targetFilesDir)
 		}
 	}
 	if a.partitionProps.Boot_partition_name != nil {
@@ -254,23 +295,25 @@
 		bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
 		builder.Command().Textf("echo %s > %s/BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
 		if bootImgInfo.Dtb != nil {
-			builder.Command().Textf("cp %s %s/BOOT/dtb", bootImgInfo.Dtb, targetFilesDir)
+			builder.Command().Textf("cp ").Input(bootImgInfo.Dtb).Textf(" %s/BOOT/dtb", targetFilesDir)
 		}
 		if bootImgInfo.Kernel != nil {
-			builder.Command().Textf("cp %s %s/BOOT/kernel", bootImgInfo.Kernel, targetFilesDir)
+			builder.Command().Textf("cp ").Input(bootImgInfo.Kernel).Textf(" %s/BOOT/kernel", targetFilesDir)
 			// Even though kernel is not used to build vendor_boot, copy the kernel to VENDOR_BOOT to match the behavior of make packaging.
-			builder.Command().Textf("cp %s %s/VENDOR_BOOT/kernel", bootImgInfo.Kernel, targetFilesDir)
+			builder.Command().Textf("cp ").Input(bootImgInfo.Kernel).Textf(" %s/VENDOR_BOOT/kernel", targetFilesDir)
 		}
 		if bootImgInfo.Bootconfig != nil {
-			builder.Command().Textf("cp %s %s/BOOT/bootconfig", bootImgInfo.Bootconfig, targetFilesDir)
+			builder.Command().Textf("cp ").Input(bootImgInfo.Bootconfig).Textf(" %s/BOOT/bootconfig", targetFilesDir)
 		}
 	}
 
 	if a.deviceProps.Android_info != nil {
 		builder.Command().Textf("mkdir -p %s/OTA", targetFilesDir)
-		builder.Command().Textf("cp %s %s/OTA/android-info.txt", android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Android_info)), targetFilesDir)
+		builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Android_info))).Textf(" %s/OTA/android-info.txt", targetFilesDir)
 	}
 
+	a.copyImagesToTargetZip(ctx, builder, targetFilesDir)
+
 	builder.Command().
 		BuiltTool("soong_zip").
 		Text("-d").
@@ -281,6 +324,26 @@
 	builder.Build("target_files_"+ctx.ModuleName(), "Build target_files.zip")
 }
 
+func (a *androidDevice) copyImagesToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.WritablePath) {
+	// Create an IMAGES/ subdirectory
+	builder.Command().Textf("mkdir -p %s/IMAGES", targetFilesDir.String())
+	if a.deviceProps.Bootloader != nil {
+		builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader))).Textf(" %s/IMAGES/bootloader", targetFilesDir.String())
+	}
+	// Copy the filesystem ,boot and vbmeta img files to IMAGES/
+	ctx.VisitDirectDepsProxyWithTag(filesystemDepTag, func(child android.ModuleProxy) {
+		if info, ok := android.OtherModuleProvider(ctx, child, FilesystemProvider); ok {
+			builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
+		} else if info, ok := android.OtherModuleProvider(ctx, child, BootimgInfoProvider); ok {
+			builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
+		} else if info, ok := android.OtherModuleProvider(ctx, child, vbmetaPartitionProvider); ok {
+			builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
+		} else {
+			ctx.ModuleErrorf("Module %s does not provide an .img file output for target_files.zip", child.Name())
+		}
+	})
+}
+
 func (a *androidDevice) getFilesystemInfo(ctx android.ModuleContext, depName string) FilesystemInfo {
 	fsMod := ctx.GetDirectDepWithTag(depName, filesystemDepTag)
 	fsInfo, ok := android.OtherModuleProvider(ctx, fsMod, FilesystemProvider)
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 0a3a177..803e981 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -235,6 +235,7 @@
 		Kernel:     b.getKernelPath(ctx),
 		Dtb:        b.getDtbPath(ctx),
 		Bootconfig: b.getBootconfigPath(ctx),
+		Output:     output,
 	})
 }
 
@@ -245,6 +246,7 @@
 	Kernel     android.Path
 	Dtb        android.Path
 	Bootconfig android.Path
+	Output     android.Path
 }
 
 func (b *bootimg) getKernelPath(ctx android.ModuleContext) android.Path {
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
index 0f8f614..d8c7345 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -21,6 +21,7 @@
 	"strings"
 
 	"android/soong/android"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -88,6 +89,17 @@
 	Odm_dlkm_partition *string
 }
 
+type SuperImageInfo struct {
+	// The built super.img file, which contains the sub-partitions
+	SuperImage android.Path
+
+	// Mapping from the sub-partition type to its re-exported FileSystemInfo providers from the
+	// sub-partitions.
+	SubImageInfo map[string]FilesystemInfo
+}
+
+var SuperImageProvider = blueprint.NewProvider[SuperImageInfo]()
+
 func SuperImageFactory() android.Module {
 	module := &superImage{}
 	module.AddProperties(&module.properties, &module.partitionProps)
@@ -99,12 +111,12 @@
 	blueprint.BaseDependencyTag
 }
 
-var superImageDepTag superImageDepTagType
+var subImageDepTag superImageDepTagType
 
 func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) {
 	addDependencyIfDefined := func(dep *string) {
 		if dep != nil {
-			ctx.AddDependency(ctx.Module(), superImageDepTag, proptools.String(dep))
+			ctx.AddDependency(ctx.Module(), subImageDepTag, proptools.String(dep))
 		}
 	}
 
@@ -120,7 +132,7 @@
 }
 
 func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	miscInfo, deps := s.buildMiscInfo(ctx)
+	miscInfo, deps, subImageInfos := s.buildMiscInfo(ctx)
 	builder := android.NewRuleBuilder(pctx, ctx)
 	output := android.PathForModuleOut(ctx, s.installFileName())
 	lpMake := ctx.Config().HostToolPath(ctx, "lpmake")
@@ -133,14 +145,19 @@
 		Implicits(deps).
 		Output(output)
 	builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName()))
+	android.SetProvider(ctx, SuperImageProvider, SuperImageInfo{
+		SuperImage:   output,
+		SubImageInfo: subImageInfos,
+	})
 	ctx.SetOutputFiles([]android.Path{output}, "")
+	ctx.CheckbuildFile(output)
 }
 
 func (s *superImage) installFileName() string {
 	return s.BaseModuleName() + ".img"
 }
 
-func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths) {
+func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths, map[string]FilesystemInfo) {
 	var miscInfoString strings.Builder
 	addStr := func(name string, value string) {
 		miscInfoString.WriteString(name)
@@ -164,6 +181,11 @@
 		addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize)
 		addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " "))
 	}
+	initialPartitionListLen := len(partitionList)
+	partitionList = android.SortedUniqueStrings(partitionList)
+	if len(partitionList) != initialPartitionListLen {
+		ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property")
+	}
 	addStr("super_partition_groups", strings.Join(groups, " "))
 	addStr("dynamic_partition_list", strings.Join(partitionList, " "))
 
@@ -172,65 +194,80 @@
 	addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update)))
 	addStr("build_non_sparse_super_partition", strconv.FormatBool(!proptools.Bool(s.properties.Sparse)))
 
-	partitionToImagePath := make(map[string]string)
-	nameToPartition := make(map[string]string)
-	var systemOtherPartitionNameNeeded string
-	addEntryToPartitionToName := func(p string, s *string) {
-		if proptools.String(s) != "" {
-			nameToPartition[*s] = p
+	subImageInfo := make(map[string]FilesystemInfo)
+	var deps android.Paths
+
+	missingPartitionErrorMessage := ""
+	handleSubPartition := func(partitionType string, name *string) {
+		if proptools.String(name) == "" {
+			missingPartitionErrorMessage += fmt.Sprintf("%s image listed in partition groups, but its module was not specified. ", partitionType)
+			return
 		}
+		mod := ctx.GetDirectDepWithTag(*name, subImageDepTag)
+		if mod == nil {
+			ctx.ModuleErrorf("Could not get dep %q", *name)
+			return
+		}
+		info, ok := android.OtherModuleProvider(ctx, mod, FilesystemProvider)
+		if !ok {
+			ctx.ModuleErrorf("Expected dep %q to provide FilesystemInfo", *name)
+			return
+		}
+		addStr(partitionType+"_image", info.Output.String())
+		deps = append(deps, info.Output)
+		if _, ok := subImageInfo[partitionType]; ok {
+			ctx.ModuleErrorf("Already set subimageInfo for %q", partitionType)
+		}
+		subImageInfo[partitionType] = info
 	}
 
 	// Build partitionToImagePath, because system partition may need system_other
 	// partition image path
 	for _, p := range partitionList {
-		if _, ok := nameToPartition[p]; ok {
-			continue
-		}
 		switch p {
 		case "system":
-			addEntryToPartitionToName(p, s.partitionProps.System_partition)
-			systemOtherPartitionNameNeeded = proptools.String(s.partitionProps.System_other_partition)
+			handleSubPartition("system", s.partitionProps.System_partition)
+			// TODO: add system_other to deps after it can be generated
+			//getFsInfo("system_other", s.partitionProps.System_other_partition, &subImageInfo.System_other)
 		case "system_dlkm":
-			addEntryToPartitionToName(p, s.partitionProps.System_dlkm_partition)
+			handleSubPartition("system_dlkm", s.partitionProps.System_dlkm_partition)
 		case "system_ext":
-			addEntryToPartitionToName(p, s.partitionProps.System_ext_partition)
+			handleSubPartition("system_ext", s.partitionProps.System_ext_partition)
 		case "product":
-			addEntryToPartitionToName(p, s.partitionProps.Product_partition)
+			handleSubPartition("product", s.partitionProps.Product_partition)
 		case "vendor":
-			addEntryToPartitionToName(p, s.partitionProps.Vendor_partition)
+			handleSubPartition("vendor", s.partitionProps.Vendor_partition)
 		case "vendor_dlkm":
-			addEntryToPartitionToName(p, s.partitionProps.Vendor_dlkm_partition)
+			handleSubPartition("vendor_dlkm", s.partitionProps.Vendor_dlkm_partition)
 		case "odm":
-			addEntryToPartitionToName(p, s.partitionProps.Odm_partition)
+			handleSubPartition("odm", s.partitionProps.Odm_partition)
 		case "odm_dlkm":
-			addEntryToPartitionToName(p, s.partitionProps.Odm_dlkm_partition)
+			handleSubPartition("odm_dlkm", s.partitionProps.Odm_dlkm_partition)
 		default:
-			ctx.ModuleErrorf("current partition %s not a super image supported partition", p)
+			ctx.ModuleErrorf("partition %q is not a super image supported partition", p)
 		}
 	}
 
-	var deps android.Paths
-	ctx.VisitDirectDeps(func(m android.Module) {
-		if p, ok := nameToPartition[m.Name()]; ok {
-			if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
-				partitionToImagePath[p] = output.DefaultOutputFiles[0].String()
-				deps = append(deps, output.DefaultOutputFiles[0])
-			}
-		} else if systemOtherPartitionNameNeeded != "" && m.Name() == systemOtherPartitionNameNeeded {
-			if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
-				partitionToImagePath["system_other"] = output.DefaultOutputFiles[0].String()
-				// TODO: add system_other to deps after it can be generated
-				// deps = append(deps, output.DefaultOutputFiles[0])
-			}
-		}
-	})
-
-	for _, p := range android.SortedKeys(partitionToImagePath) {
-		addStr(p+"_image", partitionToImagePath[p])
+	// Delay the error message until execution time because on aosp-main-future-without-vendor,
+	// BUILDING_VENDOR_IMAGE is false so we don't get the vendor image, but it's still listed in
+	// BOARD_GOOGLE_DYNAMIC_PARTITIONS_PARTITION_LIST.
+	missingPartitionErrorMessageFile := android.PathForModuleOut(ctx, "missing_partition_error.txt")
+	if missingPartitionErrorMessage != "" {
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   android.ErrorRule,
+			Output: missingPartitionErrorMessageFile,
+			Args: map[string]string{
+				"error": missingPartitionErrorMessage,
+			},
+		})
+	} else {
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   android.Touch,
+			Output: missingPartitionErrorMessageFile,
+		})
 	}
 
 	miscInfo := android.PathForModuleOut(ctx, "misc_info.txt")
-	android.WriteFileRule(ctx, miscInfo, miscInfoString.String())
-	return miscInfo, deps
+	android.WriteFileRule(ctx, miscInfo, miscInfoString.String(), missingPartitionErrorMessageFile)
+	return miscInfo, deps, subImageInfo
 }
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index c8b4675..d468186 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -121,6 +121,9 @@
 	// The path to the public key of the private key used to sign this partition. Derived from
 	// the private key.
 	PublicKey android.Path
+
+	// The output of the vbmeta module
+	Output android.Path
 }
 
 var vbmetaPartitionProvider = blueprint.NewProvider[vbmetaPartitionInfo]()
@@ -301,6 +304,7 @@
 		Name:                  v.partitionName(),
 		RollbackIndexLocation: ril,
 		PublicKey:             extractedPublicKey,
+		Output:                output,
 	})
 
 	ctx.SetOutputFiles([]android.Path{output}, "")
diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go
index 914d35b..889a4c2 100644
--- a/fsgen/boot_imgs.go
+++ b/fsgen/boot_imgs.go
@@ -80,6 +80,7 @@
 			Security_patch:     securityPatch,
 			Dtb_prebuilt:       dtbPrebuilt,
 			Cmdline:            cmdline,
+			Stem:               proptools.StringPtr("boot.img"),
 		},
 		&struct {
 			Name *string
@@ -133,6 +134,7 @@
 			Dtb_prebuilt:       dtbPrebuilt,
 			Cmdline:            cmdline,
 			Bootconfig:         vendorBootConfigImg,
+			Stem:               proptools.StringPtr("vendor_boot.img"),
 		},
 		&struct {
 			Name *string
@@ -180,6 +182,7 @@
 			Avb_private_key:    avbInfo.avbkeyFilegroup,
 			Avb_rollback_index: avbInfo.avbRollbackIndex,
 			Avb_algorithm:      avbInfo.avbAlgorithm,
+			Stem:               proptools.StringPtr("init_boot.img"),
 		},
 		&struct {
 			Name *string
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index a070e01..9d61a60 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -161,13 +161,14 @@
 		f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName)
 	}
 
+	var superImageSubpartitions []string
 	if buildingSuperImage(partitionVars) {
-		createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars)
+		superImageSubpartitions = createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars)
 		f.properties.Super_image = ":" + generatedModuleNameForPartition(ctx.Config(), "super")
 	}
 
 	ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions
-	f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names)
+	f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names, superImageSubpartitions)
 }
 
 func generatedModuleName(cfg android.Config, suffix string) string {
@@ -206,6 +207,7 @@
 	ctx android.LoadHookContext,
 	generatedPartitionTypes []string,
 	vbmetaPartitions []string,
+	superImageSubPartitions []string,
 ) {
 	baseProps := &struct {
 		Name         *string
@@ -217,19 +219,22 @@
 
 	// Currently, only the system and system_ext partition module is created.
 	partitionProps := &filesystem.PartitionNameProperties{}
-	if android.InList("system", generatedPartitionTypes) {
+	if f.properties.Super_image != "" {
+		partitionProps.Super_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "super"))
+	}
+	if android.InList("system", generatedPartitionTypes) && !android.InList("system", superImageSubPartitions) {
 		partitionProps.System_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
 	}
-	if android.InList("system_ext", generatedPartitionTypes) {
+	if android.InList("system_ext", generatedPartitionTypes) && !android.InList("system_ext", superImageSubPartitions) {
 		partitionProps.System_ext_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
 	}
-	if android.InList("vendor", generatedPartitionTypes) {
+	if android.InList("vendor", generatedPartitionTypes) && !android.InList("vendor", superImageSubPartitions) {
 		partitionProps.Vendor_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
 	}
-	if android.InList("product", generatedPartitionTypes) {
+	if android.InList("product", generatedPartitionTypes) && !android.InList("product", superImageSubPartitions) {
 		partitionProps.Product_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
 	}
-	if android.InList("odm", generatedPartitionTypes) {
+	if android.InList("odm", generatedPartitionTypes) && !android.InList("odm", superImageSubPartitions) {
 		partitionProps.Odm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm"))
 	}
 	if android.InList("userdata", f.properties.Generated_partition_types) {
@@ -238,13 +243,13 @@
 	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) {
+	if android.InList("system_dlkm", f.properties.Generated_partition_types) && !android.InList("system_dlkm", superImageSubPartitions) {
 		partitionProps.System_dlkm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_dlkm"))
 	}
-	if android.InList("vendor_dlkm", f.properties.Generated_partition_types) {
+	if android.InList("vendor_dlkm", f.properties.Generated_partition_types) && !android.InList("vendor_dlkm", superImageSubPartitions) {
 		partitionProps.Vendor_dlkm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_dlkm"))
 	}
-	if android.InList("odm_dlkm", f.properties.Generated_partition_types) {
+	if android.InList("odm_dlkm", f.properties.Generated_partition_types) && !android.InList("odm_dlkm", superImageSubPartitions) {
 		partitionProps.Odm_dlkm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm_dlkm"))
 	}
 	if f.properties.Boot_image != "" {
diff --git a/fsgen/super_img.go b/fsgen/super_img.go
index a36f614..5994fb6 100644
--- a/fsgen/super_img.go
+++ b/fsgen/super_img.go
@@ -27,7 +27,7 @@
 	return partitionVars.ProductBuildSuperPartition
 }
 
-func createSuperImage(ctx android.LoadHookContext, partitions []string, partitionVars android.PartitionVariables) {
+func createSuperImage(ctx android.LoadHookContext, partitions []string, partitionVars android.PartitionVariables) []string {
 	baseProps := &struct {
 		Name *string
 	}{
@@ -59,34 +59,45 @@
 	}
 	superImageProps.Partition_groups = partitionGroupsInfo
 
+	var superImageSubpartitions []string
 	partitionNameProps := &filesystem.SuperImagePartitionNameProperties{}
 	if android.InList("system", partitions) {
 		partitionNameProps.System_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+		superImageSubpartitions = append(superImageSubpartitions, "system")
 	}
 	if android.InList("system_ext", partitions) {
 		partitionNameProps.System_ext_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+		superImageSubpartitions = append(superImageSubpartitions, "system_ext")
 	}
 	if android.InList("system_dlkm", partitions) {
 		partitionNameProps.System_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_dlkm"))
+		superImageSubpartitions = append(superImageSubpartitions, "system_dlkm")
 	}
 	if android.InList("system_other", partitions) {
 		partitionNameProps.System_other_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_other"))
+		superImageSubpartitions = append(superImageSubpartitions, "system_other")
 	}
 	if android.InList("product", partitions) {
 		partitionNameProps.Product_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
+		superImageSubpartitions = append(superImageSubpartitions, "product")
 	}
 	if android.InList("vendor", partitions) {
 		partitionNameProps.Vendor_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
+		superImageSubpartitions = append(superImageSubpartitions, "vendor")
 	}
 	if android.InList("vendor_dlkm", partitions) {
 		partitionNameProps.Vendor_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_dlkm"))
+		superImageSubpartitions = append(superImageSubpartitions, "vendor_dlkm")
 	}
 	if android.InList("odm", partitions) {
 		partitionNameProps.Odm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm"))
+		superImageSubpartitions = append(superImageSubpartitions, "odm")
 	}
 	if android.InList("odm_dlkm", partitions) {
 		partitionNameProps.Odm_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm_dlkm"))
+		superImageSubpartitions = append(superImageSubpartitions, "odm_dlkm")
 	}
 
 	ctx.CreateModule(filesystem.SuperImageFactory, baseProps, superImageProps, partitionNameProps)
+	return superImageSubpartitions
 }
diff --git a/java/aar.go b/java/aar.go
index 7c63a29..0db195c 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -939,6 +939,12 @@
 	return staticResourcesNodes, sharedResourcesNodes, staticRRODirs, staticManifests, sharedLibs, flags
 }
 
+type AndroidLibraryInfo struct {
+	// Empty for now
+}
+
+var AndroidLibraryInfoProvider = blueprint.NewProvider[AndroidLibraryInfo]()
+
 type AndroidLibrary struct {
 	Library
 	aapt
@@ -1586,8 +1592,6 @@
 		JniPackages: a.jniPackages,
 	})
 
-	android.SetProvider(ctx, AndroidLibraryInfoProvider, AndroidLibraryInfo{})
-
 	ctx.SetOutputFiles([]android.Path{a.implementationAndResourcesJarFile}, "")
 	ctx.SetOutputFiles([]android.Path{a.aarPath}, ".aar")
 }
diff --git a/java/app.go b/java/app.go
index 31c338f..c6fad60 100644
--- a/java/app.go
+++ b/java/app.go
@@ -52,12 +52,6 @@
 
 var FlagsPackagesProvider = blueprint.NewProvider[FlagsPackages]()
 
-type AndroidLibraryInfo struct {
-	// Empty for now
-}
-
-var AndroidLibraryInfoProvider = blueprint.NewProvider[AndroidLibraryInfo]()
-
 func RegisterAppBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("android_app", AndroidAppFactory)
 	ctx.RegisterModuleType("android_test", AndroidTestFactory)
@@ -430,8 +424,6 @@
 		EmbeddedJNILibs: embeddedJniLibs,
 	})
 
-	android.SetProvider(ctx, AndroidLibraryInfoProvider, AndroidLibraryInfo{})
-
 	a.requiredModuleNames = a.getRequiredModuleNames(ctx)
 }
 
@@ -1138,12 +1130,12 @@
 
 	var directImplementationDeps android.Paths
 	var transitiveImplementationDeps []depset.DepSet[android.Path]
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
 		if tag == certificateTag {
-			if dep, ok := module.(*AndroidAppCertificate); ok {
+			if dep, ok := android.OtherModuleProvider(ctx, module, AndroidAppCertificateInfoProvider); ok {
 				certificates = append(certificates, dep.Certificate)
 			} else {
 				ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
@@ -1783,6 +1775,12 @@
 	Certificate *string
 }
 
+type AndroidAppCertificateInfo struct {
+	Certificate Certificate
+}
+
+var AndroidAppCertificateInfoProvider = blueprint.NewProvider[AndroidAppCertificateInfo]()
+
 // android_app_certificate modules can be referenced by the certificates property of android_app modules to select
 // the signing key.
 func AndroidAppCertificateFactory() android.Module {
@@ -1798,6 +1796,10 @@
 		Pem: android.PathForModuleSrc(ctx, cert+".x509.pem"),
 		Key: android.PathForModuleSrc(ctx, cert+".pk8"),
 	}
+
+	android.SetProvider(ctx, AndroidAppCertificateInfoProvider, AndroidAppCertificateInfo{
+		Certificate: c.Certificate,
+	})
 }
 
 type OverrideAndroidApp struct {
@@ -1952,7 +1954,7 @@
 		return clcMap
 	}
 
-	ctx.VisitDirectDeps(func(m android.Module) {
+	ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
 		tag, isUsesLibTag := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag)
 		if !isUsesLibTag {
 			return
@@ -1960,31 +1962,35 @@
 
 		dep := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(m))
 
+		javaInfo, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
+		if !ok {
+			return
+		}
 		// Skip stub libraries. A dependency on the implementation library has been added earlier,
 		// so it will be added to CLC, but the stub shouldn't be. Stub libraries can be distingushed
 		// from implementation libraries by their name, which is different as it has a suffix.
-		if comp, ok := m.(SdkLibraryComponentDependency); ok {
-			if impl := comp.OptionalSdkLibraryImplementation(); impl != nil && *impl != dep {
+		if comp := javaInfo.SdkLibraryComponentDependencyInfo; comp != nil {
+			if impl := comp.OptionalSdkLibraryImplementation; impl != nil && *impl != dep {
 				return
 			}
 		}
 
-		if lib, ok := m.(UsesLibraryDependency); ok {
+		if lib := javaInfo.UsesLibraryDependencyInfo; lib != nil {
 			if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
 				// Skip java_sdk_library dependencies that provide stubs, but not an implementation.
 				// This will be restricted to optional_uses_libs
-				if tag == usesLibOptTag && lib.DexJarBuildPath(ctx).PathOrNil() == nil {
+				if tag == usesLibOptTag && lib.DexJarBuildPath.PathOrNil() == nil {
 					u.shouldDisableDexpreopt = true
 					return
 				}
 			}
 			libName := dep
-			if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
-				libName = *ulib.ProvidesUsesLib()
+			if ulib := javaInfo.ProvidesUsesLibInfo; ulib != nil && ulib.ProvidesUsesLib != nil {
+				libName = *ulib.ProvidesUsesLib
 			}
 			clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
-				lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(),
-				lib.ClassLoaderContexts())
+				lib.DexJarBuildPath.PathOrNil(), lib.DexJarInstallPath,
+				lib.ClassLoaderContexts)
 		} else if ctx.Config().AllowMissingDependencies() {
 			ctx.AddMissingDependencies([]string{dep})
 		} else {
diff --git a/java/base.go b/java/base.go
index f8050de..1e0d4bf 100644
--- a/java/base.go
+++ b/java/base.go
@@ -656,14 +656,17 @@
 
 	// Make sure this module doesn't statically link to modules with lower-ranked SDK link type.
 	// See rank() for details.
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		tag := ctx.OtherModuleDependencyTag(module)
-		switch module.(type) {
-		// TODO(satayev): cover other types as well, e.g. imports
-		case *Library, *AndroidLibrary:
+		_, isJavaLibrary := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider)
+		_, isAndroidLibrary := android.OtherModuleProvider(ctx, module, AndroidLibraryInfoProvider)
+		_, isJavaAconfigLibrary := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider)
+		// Exclude java_aconfig_library modules to maintain consistency with existing behavior.
+		if (isJavaLibrary && !isJavaAconfigLibrary) || isAndroidLibrary {
+			// TODO(satayev): cover other types as well, e.g. imports
 			switch tag {
 			case bootClasspathTag, sdkLibTag, libTag, staticLibTag, java9LibTag:
-				j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag))
+				j.checkSdkLinkType(ctx, module)
 			}
 		}
 	})
@@ -2391,7 +2394,7 @@
 // checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than
 // this module's. See the comment on rank() for details and an example.
 func (j *Module) checkSdkLinkType(
-	ctx android.ModuleContext, dep moduleWithSdkDep, tag dependencyTag) {
+	ctx android.ModuleContext, dep android.ModuleProxy) {
 	if ctx.Host() {
 		return
 	}
@@ -2400,7 +2403,12 @@
 	if stubs {
 		return
 	}
-	depLinkType, _ := dep.getSdkLinkType(ctx, ctx.OtherModuleName(dep))
+	info, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
+	if !ok || info.ModuleWithSdkDepInfo == nil {
+		panic(fmt.Errorf("dependency doesn't have ModuleWithSdkDepInfo: %v", dep))
+	}
+
+	depLinkType := info.ModuleWithSdkDepInfo.SdkLinkType
 
 	if myLinkType.rank() < depLinkType.rank() {
 		ctx.ModuleErrorf("compiles against %v, but dependency %q is compiling against %v. "+
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 44ba80a..efca913 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -346,7 +346,11 @@
 	d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/"))
 	// generate the rules for creating the .odex and .vdex files for this system server jar
 	dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName))
-
+	if dexJarFile == nil {
+		ctx.ModuleErrorf(
+			`Could not find library %s in prebuilt apex %s.
+Please make sure that the value of PRODUCT_APEX_(SYSTEM_SERVER|STANDALONE_SYSTEM_SERVER)_JARS is correct`, libraryName, ctx.ModuleName())
+	}
 	d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless
 	if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) {
 		// Set the profile path to guide optimization
diff --git a/java/java.go b/java/java.go
index 48ba8de..3a1bc33 100644
--- a/java/java.go
+++ b/java/java.go
@@ -276,6 +276,11 @@
 	UsesLibrary *usesLibrary
 }
 
+type ModuleWithSdkDepInfo struct {
+	SdkLinkType sdkLinkType
+	Stubs       bool
+}
+
 // JavaInfo contains information about a java module for use by modules that depend on it.
 type JavaInfo struct {
 	// HeaderJars is a list of jars that can be passed as the javac classpath in order to link
@@ -364,10 +369,16 @@
 	ProvidesUsesLibInfo *ProvidesUsesLibInfo
 
 	ModuleWithUsesLibraryInfo *ModuleWithUsesLibraryInfo
+
+	ModuleWithSdkDepInfo *ModuleWithSdkDepInfo
 }
 
 var JavaInfoProvider = blueprint.NewProvider[*JavaInfo]()
 
+type JavaLibraryInfo struct{}
+
+var JavaLibraryInfoProvider = blueprint.NewProvider[JavaLibraryInfo]()
+
 // SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
 // the sysprop implementation library.
 type SyspropPublicStubInfo struct {
@@ -1047,6 +1058,8 @@
 		TopLevelTarget: j.sourceProperties.Top_level_test_target,
 	})
 
+	android.SetProvider(ctx, JavaLibraryInfoProvider, JavaLibraryInfo{})
+
 	if javaInfo != nil {
 		setExtraJavaInfo(ctx, j, javaInfo)
 		android.SetProvider(ctx, JavaInfoProvider, javaInfo)
@@ -3542,4 +3555,12 @@
 			UsesLibrary: mwul.UsesLibrary(),
 		}
 	}
+
+	if mwsd, ok := module.(moduleWithSdkDep); ok {
+		linkType, stubs := mwsd.getSdkLinkType(ctx, ctx.ModuleName())
+		javaInfo.ModuleWithSdkDepInfo = &ModuleWithSdkDepInfo{
+			SdkLinkType: linkType,
+			Stubs:       stubs,
+		}
+	}
 }
diff --git a/java/robolectric.go b/java/robolectric.go
index 29aa2f0..6c74d08 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -138,10 +138,17 @@
 	r.forceOSType = ctx.Config().BuildOS
 	r.forceArchType = ctx.Config().BuildArch
 
+	var options []tradefed.Option
+	options = append(options, tradefed.Option{Name: "java-flags", Value: "-Drobolectric=true"})
+	if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
+	    options = append(options, tradefed.Option{Name: "java-flags", Value: "-Drobolectric.strict.mode=true"})
+	}
+
 	r.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
 		TestConfigProp:         r.testProperties.Test_config,
 		TestConfigTemplateProp: r.testProperties.Test_config_template,
 		TestSuites:             r.testProperties.Test_suites,
+		TestRunnerOptions:      options,
 		AutoGenConfig:          r.testProperties.Auto_gen_config,
 		DeviceTemplate:         "${RobolectricTestConfigTemplate}",
 		HostTemplate:           "${RobolectricTestConfigTemplate}",