Merge "Remove apexFilesForAndroidMk from prebuilt apex module types" into main
diff --git a/android/Android.bp b/android/Android.bp
index 841a6af..96e8133 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -106,6 +106,7 @@
         "updatable_modules.go",
         "util.go",
         "variable.go",
+        "vintf_fragment.go",
         "visibility.go",
     ],
     testSrcs: [
@@ -148,6 +149,7 @@
         "test_suites_test.go",
         "util_test.go",
         "variable_test.go",
+        "vintf_fragment_test.go",
         "visibility_test.go",
     ],
 }
diff --git a/android/all_teams.go b/android/all_teams.go
index e3c2e70..01be396 100644
--- a/android/all_teams.go
+++ b/android/all_teams.go
@@ -1,6 +1,7 @@
 package android
 
 import (
+	"path"
 	"path/filepath"
 
 	"android/soong/android/team_proto"
@@ -153,6 +154,11 @@
 		} else {
 			teamProperties, found = t.lookupDefaultTeam(m.bpFile)
 		}
+		// Deal with one blueprint file including another by looking up the default
+		// in the main Android.bp rather than one listed with "build = [My.bp]"
+		if !found {
+			teamProperties, found = t.lookupDefaultTeam(path.Join(path.Dir(m.bpFile), "Android.bp"))
+		}
 
 		trendy_team_id := ""
 		if found {
diff --git a/android/all_teams_test.go b/android/all_teams_test.go
index 96ed92f..fa8c048 100644
--- a/android/all_teams_test.go
+++ b/android/all_teams_test.go
@@ -264,6 +264,84 @@
 	AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
 }
 
+func TestPackageLookupForIncludedBlueprintFiles(t *testing.T) {
+	t.Parallel()
+	rootBp := `
+                package { default_team: "team_top"}
+		team {
+			name: "team_top",
+			trendy_team_id: "trendy://team_top",
+		}
+                build = ["include.bp"]
+ `
+	includeBp := `
+		fake {
+			name: "IncludedModule",
+		} `
+
+	ctx := GroupFixturePreparers(
+		prepareForTestWithTeamAndFakes,
+		PrepareForTestWithPackageModule,
+		FixtureRegisterWithContext(func(ctx RegistrationContext) {
+			ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
+		}),
+		FixtureAddTextFile("Android.bp", rootBp),
+		FixtureAddTextFile("include.bp", includeBp),
+	).RunTest(t)
+
+	var teams *team_proto.AllTeams
+	teams = getTeamProtoOutput(t, ctx)
+
+	// map of module name -> trendy team name.
+	actualTeams := make(map[string]*string)
+	for _, teamProto := range teams.Teams {
+		actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+	}
+	expectedTeams := map[string]*string{
+		"IncludedModule": proto.String("trendy://team_top"),
+	}
+	AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
+
+func TestPackageLookupForIncludedBlueprintFilesWithPackageInChildBlueprint(t *testing.T) {
+	t.Parallel()
+	rootBp := `
+		team {
+			name: "team_top",
+			trendy_team_id: "trendy://team_top",
+		}
+                build = ["include.bp"]
+ `
+	includeBp := `
+                package { default_team: "team_top"}
+		fake {
+			name: "IncludedModule",
+		} `
+
+	ctx := GroupFixturePreparers(
+		prepareForTestWithTeamAndFakes,
+		PrepareForTestWithPackageModule,
+		FixtureRegisterWithContext(func(ctx RegistrationContext) {
+			ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
+		}),
+		FixtureAddTextFile("Android.bp", rootBp),
+		FixtureAddTextFile("include.bp", includeBp),
+	).RunTest(t)
+
+	var teams *team_proto.AllTeams
+	teams = getTeamProtoOutput(t, ctx)
+
+	// map of module name -> trendy team name.
+	actualTeams := make(map[string]*string)
+	for _, teamProto := range teams.Teams {
+		actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+	}
+	expectedTeams := map[string]*string{
+		"IncludedModule": proto.String("trendy://team_top"),
+	}
+	AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
+
 type fakeForTests struct {
 	ModuleBase
 
diff --git a/android/androidmk.go b/android/androidmk.go
index e9df752..081bca9 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -536,13 +536,14 @@
 	a.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod))
 
 	// If the install rule was generated by Soong tell Make about it.
-	if len(base.katiInstalls) > 0 {
+	info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
+	if len(info.KatiInstalls) > 0 {
 		// Assume the primary install file is last since it probably needs to depend on any other
 		// installed files.  If that is not the case we can add a method to specify the primary
 		// installed file.
-		a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to)
-		a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled())
-		a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
+		a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to)
+		a.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled())
+		a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths())
 	} else {
 		// Soong may not have generated the install rule also when `no_full_install: true`.
 		// Mark this module as uninstallable in order to prevent Make from creating an
@@ -550,8 +551,8 @@
 		a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install))
 	}
 
-	if len(base.testData) > 0 {
-		a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(base.testData)...)
+	if len(info.TestData) > 0 {
+		a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
 	}
 
 	if am, ok := mod.(ApexModule); ok {
@@ -861,6 +862,7 @@
 	}
 
 	data := provider.AndroidMk()
+
 	if data.Include == "" {
 		data.Include = "$(BUILD_PREBUILT)"
 	}
@@ -907,6 +909,7 @@
 		case "*phony.PhonyRule": // writes phony deps and acts like `.PHONY`
 		case "*selinux.selinuxContextsModule": // license properties written
 		case "*sysprop.syspropLibrary": // license properties written
+		case "*vintf.vintfCompatibilityMatrixRule": // use case like phony
 		default:
 			if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") {
 				return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod))
diff --git a/android/apex.go b/android/apex.go
index ecab8e3..028be57 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -280,7 +280,7 @@
 	//
 	// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
 	// "//apex_available:platform" refers to non-APEX partitions like "system.img".
-	// "com.android.gki.*" matches any APEX module name with the prefix "com.android.gki.".
+	// Prefix pattern (com.foo.*) can be used to match with any APEX name with the prefix(com.foo.).
 	// Default is ["//apex_available:platform"].
 	Apex_available []string
 
@@ -473,14 +473,12 @@
 const (
 	AvailableToPlatform = "//apex_available:platform"
 	AvailableToAnyApex  = "//apex_available:anyapex"
-	AvailableToGkiApex  = "com.android.gki.*"
 )
 
 var (
 	AvailableToRecognziedWildcards = []string{
 		AvailableToPlatform,
 		AvailableToAnyApex,
-		AvailableToGkiApex,
 	}
 )
 
@@ -494,11 +492,27 @@
 	if len(apex_available) == 0 {
 		return what == AvailableToPlatform
 	}
-	return InList(what, apex_available) ||
-		(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
-		(strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available)) ||
-		(what == "com.google.mainline.primary.libs") || // TODO b/248601389
-		(what == "com.google.mainline.go.primary.libs") // TODO b/248601389
+
+	// TODO b/248601389
+	if what == "com.google.mainline.primary.libs" || what == "com.google.mainline.go.primary.libs" {
+		return true
+	}
+
+	for _, apex_name := range apex_available {
+		// exact match.
+		if apex_name == what {
+			return true
+		}
+		// //apex_available:anyapex matches with any apex name, but not //apex_available:platform
+		if apex_name == AvailableToAnyApex && what != AvailableToPlatform {
+			return true
+		}
+		// prefix match.
+		if strings.HasSuffix(apex_name, ".*") && strings.HasPrefix(what, strings.TrimSuffix(apex_name, "*")) {
+			return true
+		}
+	}
+	return false
 }
 
 // Implements ApexModule
@@ -524,7 +538,20 @@
 // This function makes sure that the apex_available property is valid
 func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
 	for _, n := range m.ApexProperties.Apex_available {
-		if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex {
+		if n == AvailableToPlatform || n == AvailableToAnyApex {
+			continue
+		}
+		// Prefix pattern should end with .* and has at least two components.
+		if strings.Contains(n, "*") {
+			if !strings.HasSuffix(n, ".*") {
+				mctx.PropertyErrorf("apex_available", "Wildcard should end with .* like com.foo.*")
+			}
+			if strings.Count(n, ".") < 2 {
+				mctx.PropertyErrorf("apex_available", "Wildcard requires two or more components like com.foo.*")
+			}
+			if strings.Count(n, "*") != 1 {
+				mctx.PropertyErrorf("apex_available", "Wildcard is not allowed in the middle.")
+			}
 			continue
 		}
 		if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
diff --git a/android/build_prop.go b/android/build_prop.go
index b127755..13d59f9 100644
--- a/android/build_prop.go
+++ b/android/build_prop.go
@@ -56,7 +56,7 @@
 }
 
 func (p *buildPropModule) propFiles(ctx ModuleContext) Paths {
-	partition := p.PartitionTag(ctx.DeviceConfig())
+	partition := p.partition(ctx.DeviceConfig())
 	if partition == "system" {
 		return ctx.Config().SystemPropFiles(ctx)
 	} else if partition == "system_ext" {
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 0080b9a..4c92f71 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -160,7 +160,7 @@
 // buildComplianceMetadataProvider starts with the ModuleContext.ComplianceMetadataInfo() and fills in more common metadata
 // for different module types without accessing their private fields but through android.Module interface
 // and public/private fields of package android. The final metadata is stored to a module's ComplianceMetadataProvider.
-func buildComplianceMetadataProvider(ctx ModuleContext, m *ModuleBase) {
+func buildComplianceMetadataProvider(ctx *moduleContext, m *ModuleBase) {
 	complianceMetadataInfo := ctx.ComplianceMetadataInfo()
 	complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.NAME, m.Name())
 	complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.PACKAGE, ctx.ModuleDir())
@@ -186,9 +186,9 @@
 		}
 
 		var installed InstallPaths
-		installed = append(installed, m.module.FilesToInstall()...)
-		installed = append(installed, m.katiInstalls.InstallPaths()...)
-		installed = append(installed, m.katiSymlinks.InstallPaths()...)
+		installed = append(installed, ctx.installFiles...)
+		installed = append(installed, ctx.katiInstalls.InstallPaths()...)
+		installed = append(installed, ctx.katiSymlinks.InstallPaths()...)
 		installed = append(installed, m.katiInitRcInstalls.InstallPaths()...)
 		installed = append(installed, m.katiVintfInstalls.InstallPaths()...)
 		complianceMetadataInfo.SetListValue(ComplianceMetadataProp.INSTALLED_FILES, FirstUniqueStrings(installed.Strings()))
diff --git a/android/config.go b/android/config.go
index d13e5ab..d6d76a4 100644
--- a/android/config.go
+++ b/android/config.go
@@ -2053,3 +2053,19 @@
 func (c *config) EnableUffdGc() string {
 	return String(c.productVariables.EnableUffdGc)
 }
+
+func (c *config) DeviceFrameworkCompatibilityMatrixFile() []string {
+	return c.productVariables.DeviceFrameworkCompatibilityMatrixFile
+}
+
+func (c *config) DeviceProductCompatibilityMatrixFile() []string {
+	return c.productVariables.DeviceProductCompatibilityMatrixFile
+}
+
+func (c *config) BoardAvbEnable() bool {
+	return Bool(c.productVariables.BoardAvbEnable)
+}
+
+func (c *config) BoardAvbSystemAddHashtreeFooterArgs() []string {
+	return c.productVariables.BoardAvbSystemAddHashtreeFooterArgs
+}
diff --git a/android/container.go b/android/container.go
index 05897dd..10aff4d 100644
--- a/android/container.go
+++ b/android/container.go
@@ -43,16 +43,86 @@
 	return false
 }
 
+// Returns true if the dependency module belongs to any of the apexes.
+var depIsApexModule exceptionHandleFunc = func(mctx ModuleContext, _, dep Module) bool {
+	depContainersInfo, _ := getContainerModuleInfo(mctx, dep)
+	return InList(ApexContainer, depContainersInfo.belongingContainers)
+}
+
+// Returns true if the module and the dependent module belongs to common apexes.
+var belongsToCommonApexes exceptionHandleFunc = func(mctx ModuleContext, m, dep Module) bool {
+	mContainersInfo, _ := getContainerModuleInfo(mctx, m)
+	depContainersInfo, _ := getContainerModuleInfo(mctx, dep)
+
+	return HasIntersection(mContainersInfo.ApexNames(), depContainersInfo.ApexNames())
+}
+
+// Returns true when all apexes that the module belongs to are non updatable.
+// For an apex module to be allowed to depend on a non-apex partition module,
+// all apexes that the module belong to must be non updatable.
+var belongsToNonUpdatableApex exceptionHandleFunc = func(mctx ModuleContext, m, _ Module) bool {
+	mContainersInfo, _ := getContainerModuleInfo(mctx, m)
+
+	return !mContainersInfo.UpdatableApex()
+}
+
+// Returns true if the dependency is added via dependency tags that are not used to tag dynamic
+// dependency tags.
+var depIsNotDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool {
+	mInstallable, _ := m.(InstallableModule)
+	depTag := ctx.OtherModuleDependencyTag(dep)
+	return !InList(depTag, mInstallable.DynamicDependencyTags())
+}
+
+// Returns true if the dependency is added via dependency tags that are not used to tag static
+// or dynamic dependency tags. These dependencies do not affect the module in compile time or in
+// runtime, thus are not significant enough to raise an error.
+var depIsNotStaticOrDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool {
+	mInstallable, _ := m.(InstallableModule)
+	depTag := ctx.OtherModuleDependencyTag(dep)
+	return !InList(depTag, append(mInstallable.StaticDependencyTags(), mInstallable.DynamicDependencyTags()...))
+}
+
+var globallyAllowlistedDependencies = []string{
+	// Modules that provide annotations used within the platform and apexes.
+	"aconfig-annotations-lib",
+	"framework-annotations-lib",
+	"unsupportedappusage",
+
+	// framework-res provides core resources essential for building apps and system UI.
+	// This module is implicitly added as a dependency for java modules even when the
+	// dependency specifies sdk_version.
+	"framework-res",
+}
+
+// Returns true when the dependency is globally allowlisted for inter-container dependency
+var depIsGloballyAllowlisted exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool {
+	return InList(dep.Name(), globallyAllowlistedDependencies)
+}
+
 // Labels of exception functions, which are used to determine special dependencies that allow
 // otherwise restricted inter-container dependencies
 type exceptionHandleFuncLabel int
 
 const (
 	checkStubs exceptionHandleFuncLabel = iota
+	checkApexModule
+	checkInCommonApexes
+	checkApexIsNonUpdatable
+	checkNotDynamicDepTag
+	checkNotStaticOrDynamicDepTag
+	checkGlobalAllowlistedDep
 )
 
+// Map of [exceptionHandleFuncLabel] to the [exceptionHandleFunc]
 var exceptionHandleFunctionsTable = map[exceptionHandleFuncLabel]exceptionHandleFunc{
-	checkStubs: depIsStubsModule,
+	checkStubs:                    depIsStubsModule,
+	checkApexModule:               depIsApexModule,
+	checkInCommonApexes:           belongsToCommonApexes,
+	checkApexIsNonUpdatable:       belongsToNonUpdatableApex,
+	checkNotDynamicDepTag:         depIsNotDynamicDepTag,
+	checkNotStaticOrDynamicDepTag: depIsNotStaticOrDynamicDepTag,
+	checkGlobalAllowlistedDep:     depIsGloballyAllowlisted,
 }
 
 // ----------------------------------------------------------------------------
@@ -108,13 +178,40 @@
 	return false
 }
 
+type unstableInfo struct {
+	// Determines if the module contains the private APIs of the platform.
+	ContainsPlatformPrivateApis bool
+}
+
+var unstableInfoProvider = blueprint.NewProvider[unstableInfo]()
+
+func determineUnstableModule(mctx ModuleContext) bool {
+	module := mctx.Module()
+	unstableModule := module.Name() == "framework-minus-apex"
+	if installable, ok := module.(InstallableModule); ok {
+		for _, staticDepTag := range installable.StaticDependencyTags() {
+			mctx.VisitDirectDepsWithTag(staticDepTag, func(dep Module) {
+				if unstableInfo, ok := OtherModuleProvider(mctx, dep, unstableInfoProvider); ok {
+					unstableModule = unstableModule || unstableInfo.ContainsPlatformPrivateApis
+				}
+			})
+		}
+	}
+	return unstableModule
+}
+
+var unstableContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
+	return determineUnstableModule(mctx)
+}
+
 // Map of [*container] to the [containerBoundaryFunc]
 var containerBoundaryFunctionsTable = map[*container]containerBoundaryFunc{
-	VendorContainer:  vendorContainerBoundaryFunc,
-	SystemContainer:  systemContainerBoundaryFunc,
-	ProductContainer: productContainerBoundaryFunc,
-	ApexContainer:    apexContainerBoundaryFunc,
-	CtsContainer:     ctsContainerBoundaryFunc,
+	VendorContainer:   vendorContainerBoundaryFunc,
+	SystemContainer:   systemContainerBoundaryFunc,
+	ProductContainer:  productContainerBoundaryFunc,
+	ApexContainer:     apexContainerBoundaryFunc,
+	CtsContainer:      ctsContainerBoundaryFunc,
+	UnstableContainer: unstableContainerBoundaryFunc,
 }
 
 // ----------------------------------------------------------------------------
@@ -122,7 +219,9 @@
 // ----------------------------------------------------------------------------
 
 type InstallableModule interface {
-	EnforceApiContainerChecks() bool
+	ContainersInfo() ContainersInfo
+	StaticDependencyTags() []blueprint.DependencyTag
+	DynamicDependencyTags() []blueprint.DependencyTag
 }
 
 type restriction struct {
@@ -160,7 +259,11 @@
 					"not allowed to depend on the vendor partition module, in order to support " +
 					"independent development/update cycles and to support the Generic System " +
 					"Image. Try depending on HALs, VNDK or AIDL instead.",
-				allowedExceptions: []exceptionHandleFuncLabel{},
+				allowedExceptions: []exceptionHandleFuncLabel{
+					checkStubs,
+					checkNotDynamicDepTag,
+					checkGlobalAllowlistedDep,
+				},
 			},
 		},
 	}
@@ -173,7 +276,11 @@
 				errorMessage: "Module belonging to the product partition is not allowed to " +
 					"depend on the vendor partition module, as this may lead to security " +
 					"vulnerabilities. Try depending on the HALs or utilize AIDL instead.",
-				allowedExceptions: []exceptionHandleFuncLabel{},
+				allowedExceptions: []exceptionHandleFuncLabel{
+					checkStubs,
+					checkNotDynamicDepTag,
+					checkGlobalAllowlistedDep,
+				},
 			},
 		},
 	}
@@ -184,22 +291,34 @@
 		name: "cts",
 		restricted: []restriction{
 			{
-				dependency: SystemContainer,
-				errorMessage: "CTS module should not depend on the modules belonging to the " +
-					"system partition, including \"framework\". Depending on the system " +
-					"partition may lead to disclosure of implementation details and regression " +
-					"due to API changes across platform versions. Try depending on the stubs instead.",
-				allowedExceptions: []exceptionHandleFuncLabel{checkStubs},
+				dependency: UnstableContainer,
+				errorMessage: "CTS module should not depend on the modules that contain the " +
+					"platform implementation details, including \"framework\". Depending on these " +
+					"modules may lead to disclosure of implementation details and regression " +
+					"due to API changes across platform versions. Try depending on the stubs instead " +
+					"and ensure that the module sets an appropriate 'sdk_version'.",
+				allowedExceptions: []exceptionHandleFuncLabel{
+					checkStubs,
+					checkNotStaticOrDynamicDepTag,
+					checkGlobalAllowlistedDep,
+				},
 			},
 		},
 	}
 
+	// Container signifying that the module contains unstable platform private APIs
+	UnstableContainer = &container{
+		name:       "unstable",
+		restricted: nil,
+	}
+
 	allContainers = []*container{
 		VendorContainer,
 		SystemContainer,
 		ProductContainer,
 		ApexContainer,
 		CtsContainer,
+		UnstableContainer,
 	}
 )
 
@@ -213,7 +332,14 @@
 					"modules belonging to the system partition. Either statically depend on the " +
 					"module or convert the depending module to java_sdk_library and depend on " +
 					"the stubs.",
-				allowedExceptions: []exceptionHandleFuncLabel{checkStubs},
+				allowedExceptions: []exceptionHandleFuncLabel{
+					checkStubs,
+					checkApexModule,
+					checkInCommonApexes,
+					checkApexIsNonUpdatable,
+					checkNotStaticOrDynamicDepTag,
+					checkGlobalAllowlistedDep,
+				},
 			},
 		},
 	}
@@ -224,7 +350,12 @@
 			"modules belonging to other Apex(es). Either include the depending " +
 			"module in the Apex or convert the depending module to java_sdk_library " +
 			"and depend on its stubs.",
-		allowedExceptions: []exceptionHandleFuncLabel{checkStubs},
+		allowedExceptions: []exceptionHandleFuncLabel{
+			checkStubs,
+			checkInCommonApexes,
+			checkNotStaticOrDynamicDepTag,
+			checkGlobalAllowlistedDep,
+		},
 	})
 
 	return apexContainer
@@ -280,9 +411,24 @@
 	}
 }
 
+func getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, bool) {
+	if ctx.Module() == module {
+		return module.ContainersInfo(), true
+	}
+
+	return OtherModuleProvider(ctx, module, ContainersInfoProvider)
+}
+
 func setContainerInfo(ctx ModuleContext) {
+	// Required to determine the unstable container. This provider is set here instead of the
+	// unstableContainerBoundaryFunc in order to prevent setting the provider multiple times.
+	SetProvider(ctx, unstableInfoProvider, unstableInfo{
+		ContainsPlatformPrivateApis: determineUnstableModule(ctx),
+	})
+
 	if _, ok := ctx.Module().(InstallableModule); ok {
 		containersInfo := generateContainerInfo(ctx)
+		ctx.Module().base().containersInfo = containersInfo
 		SetProvider(ctx, ContainersInfoProvider, containersInfo)
 	}
 }
diff --git a/android/deapexer.go b/android/deapexer.go
index 61ae64e..dcae3e4 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -181,7 +181,11 @@
 			// An err has been found. Do not visit further.
 			return
 		}
-		c, _ := OtherModuleProvider(ctx, m, DeapexerProvider)
+		c, ok := OtherModuleProvider(ctx, m, DeapexerProvider)
+		if !ok {
+			ctx.ModuleErrorf("Expected all deps with DeapexerTag to have a DeapexerProvider, but module %q did not", m.Name())
+			return
+		}
 		p := &c
 		if di != nil {
 			// If two DeapexerInfo providers have been found then check if they are
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 8056189..cd69749 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -33,7 +33,7 @@
 	}, "args")
 )
 
-func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
+func buildLicenseMetadata(ctx *moduleContext, licenseMetadataFile WritablePath) {
 	base := ctx.Module().base()
 
 	if !base.Enabled(ctx) {
@@ -52,8 +52,8 @@
 	// Only pass the last installed file to isContainerFromFileExtensions so a *.zip file in test data
 	// doesn't mark the whole module as a container.
 	var installFiles InstallPaths
-	if len(base.installFiles) > 0 {
-		installFiles = InstallPaths{base.installFiles[len(base.installFiles)-1]}
+	if len(ctx.installFiles) > 0 {
+		installFiles = InstallPaths{ctx.installFiles[len(ctx.installFiles)-1]}
 	}
 
 	isContainer := isContainerFromFileExtensions(installFiles, outputFiles)
@@ -92,7 +92,7 @@
 
 			allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
 
-			if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
+			if depInstallFiles := OtherModuleProviderOrDefault(ctx, dep, InstallFilesProvider).InstallFiles; len(depInstallFiles) > 0 {
 				allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
 			} else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
 				depOutputFiles = PathsIfNonNil(depOutputFiles...)
@@ -162,7 +162,7 @@
 
 	// Installed files
 	args = append(args,
-		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
+		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(ctx.installFiles.Strings()), "-i "))
 
 	if isContainer {
 		args = append(args, "--is_container")
diff --git a/android/makevars.go b/android/makevars.go
index ff43cc5..810eb38 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -279,10 +279,11 @@
 		}
 
 		if m.ExportedToMake() {
-			katiInstalls = append(katiInstalls, m.base().katiInstalls...)
+			info := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider)
+			katiInstalls = append(katiInstalls, info.KatiInstalls...)
 			katiInitRcInstalls = append(katiInitRcInstalls, m.base().katiInitRcInstalls...)
 			katiVintfManifestInstalls = append(katiVintfManifestInstalls, m.base().katiVintfInstalls...)
-			katiSymlinks = append(katiSymlinks, m.base().katiSymlinks...)
+			katiSymlinks = append(katiSymlinks, info.KatiSymlinks...)
 		}
 	})
 
diff --git a/android/module.go b/android/module.go
index 63df6f7..95908f8 100644
--- a/android/module.go
+++ b/android/module.go
@@ -111,15 +111,16 @@
 	RequiredModuleNames(ctx ConfigAndErrorContext) []string
 	HostRequiredModuleNames() []string
 	TargetRequiredModuleNames() []string
-
-	FilesToInstall() InstallPaths
-	PackagingSpecs() []PackagingSpec
+	VintfFragmentModuleNames(ctx ConfigAndErrorContext) []string
 
 	// TransitivePackagingSpecs returns the PackagingSpecs for this module and any transitive
 	// dependencies with dependency tags for which IsInstallDepNeeded() returns true.
 	TransitivePackagingSpecs() []PackagingSpec
 
 	ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator
+
+	// Get the information about the containers this module belongs to.
+	ContainersInfo() ContainersInfo
 }
 
 // Qualified id for a module
@@ -497,6 +498,9 @@
 
 	// The team (defined by the owner/vendor) who owns the property.
 	Team *string `android:"path"`
+
+	// vintf_fragment Modules required from this module.
+	Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"`
 }
 
 type distProperties struct {
@@ -832,30 +836,16 @@
 	primaryLicensesProperty applicableLicensesProperty
 
 	noAddressSanitizer   bool
-	installFiles         InstallPaths
 	installFilesDepSet   *DepSet[InstallPath]
-	checkbuildFiles      Paths
-	packagingSpecs       []PackagingSpec
 	packagingSpecsDepSet *DepSet[PackagingSpec]
-	// katiInstalls tracks the install rules that were created by Soong but are being exported
-	// to Make to convert to ninja rules so that Make can add additional dependencies.
-	katiInstalls katiInstalls
 	// katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
 	// allowed to have duplicates across modules and variants.
 	katiInitRcInstalls katiInstalls
 	katiVintfInstalls  katiInstalls
-	katiSymlinks       katiInstalls
-	testData           []DataPath
 
 	// The files to copy to the dist as explicitly specified in the .bp file.
 	distFiles TaggedDistFiles
 
-	// Used by buildTargetSingleton to create checkbuild and per-directory build targets
-	// Only set on the final variant of each module
-	installTarget    WritablePath
-	checkbuildTarget WritablePath
-	blueprintDir     string
-
 	hooks hooks
 
 	registerProps []interface{}
@@ -892,6 +882,10 @@
 	// complianceMetadataInfo is for different module types to dump metadata.
 	// See android.ModuleContext interface.
 	complianceMetadataInfo *ComplianceMetadataInfo
+
+	// containersInfo stores the information about the containers and the information of the
+	// apexes the module belongs to.
+	containersInfo ContainersInfo
 }
 
 func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
@@ -1028,6 +1022,7 @@
 	fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil
 	if fullManifest {
 		addRequiredDeps(ctx)
+		addVintfFragmentDeps(ctx)
 	}
 }
 
@@ -1105,6 +1100,16 @@
 	}
 }
 
+var vintfDepTag = struct {
+	blueprint.BaseDependencyTag
+	InstallAlwaysNeededDependencyTag
+}{}
+
+func addVintfFragmentDeps(ctx BottomUpMutatorContext) {
+	mod := ctx.Module()
+	ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+}
+
 // AddProperties "registers" the provided props
 // each value in props MUST be a pointer to a struct
 func (m *ModuleBase) AddProperties(props ...interface{}) {
@@ -1476,14 +1481,6 @@
 	return IsInstallDepNeededTag(tag)
 }
 
-func (m *ModuleBase) FilesToInstall() InstallPaths {
-	return m.installFiles
-}
-
-func (m *ModuleBase) PackagingSpecs() []PackagingSpec {
-	return m.packagingSpecs
-}
-
 func (m *ModuleBase) TransitivePackagingSpecs() []PackagingSpec {
 	return m.packagingSpecsDepSet.ToList()
 }
@@ -1597,6 +1594,10 @@
 	return m.base().commonProperties.Target_required
 }
 
+func (m *ModuleBase) VintfFragmentModuleNames(ctx ConfigAndErrorContext) []string {
+	return m.base().commonProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
+}
+
 func (m *ModuleBase) InitRc() Paths {
 	return append(Paths{}, m.initRcPaths...)
 }
@@ -1615,40 +1616,51 @@
 	m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
 }
 
-func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
+func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
 	var allInstalledFiles InstallPaths
 	var allCheckbuildFiles Paths
 	ctx.VisitAllModuleVariants(func(module Module) {
 		a := module.base()
-		allInstalledFiles = append(allInstalledFiles, a.installFiles...)
+		var checkBuilds Paths
+		if a == m {
+			allInstalledFiles = append(allInstalledFiles, ctx.installFiles...)
+			checkBuilds = ctx.checkbuildFiles
+		} else {
+			info := OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider)
+			allInstalledFiles = append(allInstalledFiles, info.InstallFiles...)
+			checkBuilds = info.CheckbuildFiles
+		}
 		// A module's -checkbuild phony targets should
 		// not be created if the module is not exported to make.
 		// Those could depend on the build target and fail to compile
 		// for the current build target.
 		if !ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, a) {
-			allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
+			allCheckbuildFiles = append(allCheckbuildFiles, checkBuilds...)
 		}
 	})
 
 	var deps Paths
 
-	namespacePrefix := ctx.Namespace().id
-	if namespacePrefix != "" {
-		namespacePrefix = namespacePrefix + "-"
+	var namespacePrefix string
+	nameSpace := ctx.Namespace().Path
+	if nameSpace != "." {
+		namespacePrefix = strings.ReplaceAll(nameSpace, "/", ".") + "-"
 	}
 
+	var info FinalModuleBuildTargetsInfo
+
 	if len(allInstalledFiles) > 0 {
 		name := namespacePrefix + ctx.ModuleName() + "-install"
 		ctx.Phony(name, allInstalledFiles.Paths()...)
-		m.installTarget = PathForPhony(ctx, name)
-		deps = append(deps, m.installTarget)
+		info.InstallTarget = PathForPhony(ctx, name)
+		deps = append(deps, info.InstallTarget)
 	}
 
 	if len(allCheckbuildFiles) > 0 {
 		name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
 		ctx.Phony(name, allCheckbuildFiles...)
-		m.checkbuildTarget = PathForPhony(ctx, name)
-		deps = append(deps, m.checkbuildTarget)
+		info.CheckbuildTarget = PathForPhony(ctx, name)
+		deps = append(deps, info.CheckbuildTarget)
 	}
 
 	if len(deps) > 0 {
@@ -1659,7 +1671,8 @@
 
 		ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
 
-		m.blueprintDir = ctx.ModuleDir()
+		info.BlueprintDir = ctx.ModuleDir()
+		SetProvider(ctx, FinalModuleBuildTargetsProvider, info)
 	}
 }
 
@@ -1763,12 +1776,36 @@
 
 }
 
+type InstallFilesInfo struct {
+	InstallFiles    InstallPaths
+	CheckbuildFiles Paths
+	PackagingSpecs  []PackagingSpec
+	// katiInstalls tracks the install rules that were created by Soong but are being exported
+	// to Make to convert to ninja rules so that Make can add additional dependencies.
+	KatiInstalls katiInstalls
+	KatiSymlinks katiInstalls
+	TestData     []DataPath
+}
+
+var FinalModuleBuildTargetsProvider = blueprint.NewProvider[FinalModuleBuildTargetsInfo]()
+
+type FinalModuleBuildTargetsInfo struct {
+	// Used by buildTargetSingleton to create checkbuild and per-directory build targets
+	// Only set on the final variant of each module
+	InstallTarget    WritablePath
+	CheckbuildTarget WritablePath
+	BlueprintDir     string
+}
+
+var InstallFilesProvider = blueprint.NewProvider[InstallFilesInfo]()
+
 func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
 	ctx := &moduleContext{
 		module:            m.module,
 		bp:                blueprintCtx,
 		baseModuleContext: m.baseModuleContextFactory(blueprintCtx),
 		variables:         make(map[string]string),
+		phonies:           make(map[string]Paths),
 	}
 
 	setContainerInfo(ctx)
@@ -1944,12 +1981,14 @@
 			return
 		}
 
-		m.installFiles = append(m.installFiles, ctx.installFiles...)
-		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
-		m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
-		m.katiInstalls = append(m.katiInstalls, ctx.katiInstalls...)
-		m.katiSymlinks = append(m.katiSymlinks, ctx.katiSymlinks...)
-		m.testData = append(m.testData, ctx.testData...)
+		SetProvider(ctx, InstallFilesProvider, InstallFilesInfo{
+			InstallFiles:    ctx.installFiles,
+			CheckbuildFiles: ctx.checkbuildFiles,
+			PackagingSpecs:  ctx.packagingSpecs,
+			KatiInstalls:    ctx.katiInstalls,
+			KatiSymlinks:    ctx.katiSymlinks,
+			TestData:        ctx.testData,
+		})
 	} else if ctx.Config().AllowMissingDependencies() {
 		// If the module is not enabled it will not create any build rules, nothing will call
 		// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -1965,15 +2004,15 @@
 		}
 	}
 
-	m.installFilesDepSet = NewDepSet[InstallPath](TOPOLOGICAL, m.installFiles, dependencyInstallFiles)
-	m.packagingSpecsDepSet = NewDepSet[PackagingSpec](TOPOLOGICAL, m.packagingSpecs, dependencyPackagingSpecs)
+	m.installFilesDepSet = NewDepSet[InstallPath](TOPOLOGICAL, ctx.installFiles, dependencyInstallFiles)
+	m.packagingSpecsDepSet = NewDepSet[PackagingSpec](TOPOLOGICAL, ctx.packagingSpecs, dependencyPackagingSpecs)
 
 	buildLicenseMetadata(ctx, m.licenseMetadataFile)
 
 	if m.moduleInfoJSON != nil {
 		var installed InstallPaths
-		installed = append(installed, m.katiInstalls.InstallPaths()...)
-		installed = append(installed, m.katiSymlinks.InstallPaths()...)
+		installed = append(installed, ctx.katiInstalls.InstallPaths()...)
+		installed = append(installed, ctx.katiSymlinks.InstallPaths()...)
 		installed = append(installed, m.katiInitRcInstalls.InstallPaths()...)
 		installed = append(installed, m.katiVintfInstalls.InstallPaths()...)
 		installedStrings := installed.Strings()
@@ -1986,7 +2025,7 @@
 		}
 
 		var data []string
-		for _, d := range m.testData {
+		for _, d := range ctx.testData {
 			data = append(data, d.ToRelativeInstallPath())
 		}
 
@@ -2022,6 +2061,11 @@
 		SetProvider(ctx, OutputFilesProvider, m.outputFiles)
 	}
 
+	if len(ctx.phonies) > 0 {
+		SetProvider(ctx, ModulePhonyProvider, ModulePhonyInfo{
+			Phonies: ctx.phonies,
+		})
+	}
 	buildComplianceMetadataProvider(ctx, m)
 }
 
@@ -2068,6 +2112,10 @@
 	return variant
 }
 
+func (m *ModuleBase) ContainersInfo() ContainersInfo {
+	return m.containersInfo
+}
+
 // Check the supplied dist structure to make sure that it is valid.
 //
 // property - the base property, e.g. dist or dists[1], which is combined with the
@@ -2621,17 +2669,15 @@
 	modulesInDir := make(map[string]Paths)
 
 	ctx.VisitAllModules(func(module Module) {
-		blueprintDir := module.base().blueprintDir
-		installTarget := module.base().installTarget
-		checkbuildTarget := module.base().checkbuildTarget
+		info := OtherModuleProviderOrDefault(ctx, module, FinalModuleBuildTargetsProvider)
 
-		if checkbuildTarget != nil {
-			checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
-			modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], checkbuildTarget)
+		if info.CheckbuildTarget != nil {
+			checkbuildDeps = append(checkbuildDeps, info.CheckbuildTarget)
+			modulesInDir[info.BlueprintDir] = append(modulesInDir[info.BlueprintDir], info.CheckbuildTarget)
 		}
 
-		if installTarget != nil {
-			modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget)
+		if info.InstallTarget != nil {
+			modulesInDir[info.BlueprintDir] = append(modulesInDir[info.BlueprintDir], info.InstallTarget)
 		}
 	})
 
@@ -2666,7 +2712,7 @@
 	ctx.VisitAllModules(func(module Module) {
 		if module.Enabled(ctx) {
 			key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross}
-			osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...)
+			osDeps[key] = append(osDeps[key], OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).CheckbuildFiles...)
 		}
 	})
 
diff --git a/android/module_context.go b/android/module_context.go
index 253bebd..5146782 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -231,8 +231,8 @@
 	module          Module
 	phonies         map[string]Paths
 
-	katiInstalls []katiInstall
-	katiSymlinks []katiInstall
+	katiInstalls katiInstalls
+	katiSymlinks katiInstalls
 
 	testData []DataPath
 
@@ -361,7 +361,7 @@
 }
 
 func (m *moduleContext) Phony(name string, deps ...Path) {
-	addPhony(m.config, name, deps...)
+	m.phonies[name] = append(m.phonies[name], deps...)
 }
 
 func (m *moduleContext) GetMissingDependencies() []string {
diff --git a/android/phony.go b/android/phony.go
index 814a9e3..f8db88d 100644
--- a/android/phony.go
+++ b/android/phony.go
@@ -26,14 +26,20 @@
 
 var phonyMapLock sync.Mutex
 
-func getPhonyMap(config Config) phonyMap {
+type ModulePhonyInfo struct {
+	Phonies map[string]Paths
+}
+
+var ModulePhonyProvider = blueprint.NewProvider[ModulePhonyInfo]()
+
+func getSingletonPhonyMap(config Config) phonyMap {
 	return config.Once(phonyMapOnceKey, func() interface{} {
 		return make(phonyMap)
 	}).(phonyMap)
 }
 
-func addPhony(config Config, name string, deps ...Path) {
-	phonyMap := getPhonyMap(config)
+func addSingletonPhony(config Config, name string, deps ...Path) {
+	phonyMap := getSingletonPhonyMap(config)
 	phonyMapLock.Lock()
 	defer phonyMapLock.Unlock()
 	phonyMap[name] = append(phonyMap[name], deps...)
@@ -47,7 +53,15 @@
 var _ SingletonMakeVarsProvider = (*phonySingleton)(nil)
 
 func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
-	p.phonyMap = getPhonyMap(ctx.Config())
+	p.phonyMap = getSingletonPhonyMap(ctx.Config())
+	ctx.VisitAllModules(func(m Module) {
+		if info, ok := OtherModuleProvider(ctx, m, ModulePhonyProvider); ok {
+			for k, v := range info.Phonies {
+				p.phonyMap[k] = append(p.phonyMap[k], v...)
+			}
+		}
+	})
+
 	p.phonyList = SortedKeys(p.phonyMap)
 	for _, phony := range p.phonyList {
 		p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony])
diff --git a/android/provider.go b/android/provider.go
index 327f224..5ded4cc 100644
--- a/android/provider.go
+++ b/android/provider.go
@@ -32,6 +32,11 @@
 	return value.(K), ok
 }
 
+func OtherModuleProviderOrDefault[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) K {
+	value, _ := OtherModuleProvider(ctx, module, provider)
+	return value
+}
+
 // ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
 // TopDownMutatorContext for use in ModuleProvider.
 type ModuleProviderContext interface {
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 8b03124..464aca4 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -554,6 +554,12 @@
 					To:   proto.String(r.sboxPathForInputRel(input)),
 				})
 			}
+			for _, input := range r.OrderOnlys() {
+				command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
+					From: proto.String(input.String()),
+					To:   proto.String(r.sboxPathForInputRel(input)),
+				})
+			}
 
 			// If using rsp files copy them and their contents into the sbox directory with
 			// the appropriate path mappings.
diff --git a/android/sdk.go b/android/sdk.go
index 4bcbe2e..d3f04a4 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -813,6 +813,7 @@
 
 // SdkMemberContext provides access to information common to a specific member.
 type SdkMemberContext interface {
+	ConfigAndErrorContext
 
 	// SdkModuleContext returns the module context of the sdk common os variant which is creating the
 	// snapshot.
diff --git a/android/singleton.go b/android/singleton.go
index 92264d2..8542bd9 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -177,7 +177,7 @@
 }
 
 func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
-	addPhony(s.Config(), name, deps...)
+	addSingletonPhony(s.Config(), name, deps...)
 }
 
 func (s *singletonContextAdaptor) SetOutDir(pctx PackageContext, value string) {
diff --git a/android/test_suites.go b/android/test_suites.go
index ff75f26..936d2b6 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -47,7 +47,8 @@
 					files[testSuite] = make(map[string]InstallPaths)
 				}
 				name := ctx.ModuleName(m)
-				files[testSuite][name] = append(files[testSuite][name], tsm.FilesToInstall()...)
+				files[testSuite][name] = append(files[testSuite][name],
+					OtherModuleProviderOrDefault(ctx, tsm, InstallFilesProvider).InstallFiles...)
 			}
 		}
 	})
diff --git a/android/testing.go b/android/testing.go
index a3e35cb..79d0c9b 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -126,6 +126,10 @@
 	ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
 })
 
+var PrepareForTestVintfFragmentModules = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+	registerVintfFragmentComponents(ctx)
+})
+
 // Test fixture preparer that will register most java build components.
 //
 // Singletons and mutators should only be added here if they are needed for a majority of java
@@ -149,6 +153,7 @@
 	PrepareForTestWithPackageModule,
 	PrepareForTestWithPrebuilts,
 	PrepareForTestWithVisibility,
+	PrepareForTestVintfFragmentModules,
 )
 
 // Prepares an integration test with all build components from the android package.
diff --git a/android/variable.go b/android/variable.go
index 4025607..c141437 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -513,6 +513,11 @@
 	ProductPropFiles   []string `json:",omitempty"`
 
 	EnableUffdGc *string `json:",omitempty"`
+
+	BoardAvbEnable                         *bool    `json:",omitempty"`
+	BoardAvbSystemAddHashtreeFooterArgs    []string `json:",omitempty"`
+	DeviceFrameworkCompatibilityMatrixFile []string `json:",omitempty"`
+	DeviceProductCompatibilityMatrixFile   []string `json:",omitempty"`
 }
 
 type PartitionQualifiedVariablesType struct {
diff --git a/android/variable_test.go b/android/variable_test.go
index 928bca6..73dc052 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -199,9 +199,7 @@
 			ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
 				Foo []string
 			}{}))
-			ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
-				ctx.BottomUp("variable", VariableMutator).Parallel()
-			})
+			registerVariableBuildComponents(ctx)
 		}),
 		FixtureWithRootAndroidBp(bp),
 	).RunTest(t)
@@ -210,14 +208,14 @@
 var testProductVariableDefaultsProperties = struct {
 	Product_variables struct {
 		Eng struct {
-			Foo []string
+			Foo []string `android:"arch_variant"`
 			Bar []string
-		}
-	}
+		} `android:"arch_variant"`
+	} `android:"arch_variant"`
 }{}
 
 type productVariablesDefaultsTestProperties struct {
-	Foo []string
+	Foo []string `android:"arch_variant"`
 }
 
 type productVariablesDefaultsTestProperties2 struct {
@@ -242,7 +240,7 @@
 	module := &productVariablesDefaultsTestModule{}
 	module.AddProperties(&module.properties)
 	module.variableProperties = testProductVariableDefaultsProperties
-	InitAndroidModule(module)
+	InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
 	InitDefaultableModule(module)
 	return module
 }
@@ -324,3 +322,46 @@
 		})
 	}
 }
+
+// Test a defaults module that supports more product variable properties than the target module.
+func TestProductVariablesArch(t *testing.T) {
+	bp := `
+		test {
+			name: "foo",
+			arch: {
+				arm: {
+					product_variables: {
+						eng: {
+							foo: ["arm"],
+						},
+					},
+				},
+				arm64: {
+					product_variables: {
+						eng: {
+							foo: ["arm64"],
+						},
+					},
+				},
+			},
+			foo: ["module"],
+		}
+	`
+
+	result := GroupFixturePreparers(
+		FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+			variables.Eng = boolPtr(true)
+		}),
+		PrepareForTestWithArchMutator,
+		PrepareForTestWithVariables,
+		FixtureRegisterWithContext(func(ctx RegistrationContext) {
+			ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
+		}),
+		FixtureWithRootAndroidBp(bp),
+	).RunTest(t)
+
+	foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*productVariablesDefaultsTestModule)
+
+	want := []string{"module", "arm64"}
+	AssertDeepEquals(t, "foo", want, foo.properties.Foo)
+}
diff --git a/android/vintf_fragment.go b/android/vintf_fragment.go
new file mode 100644
index 0000000..329eac9
--- /dev/null
+++ b/android/vintf_fragment.go
@@ -0,0 +1,84 @@
+// Copyright 2024 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
+
+type vintfFragmentProperties struct {
+	// Vintf fragment XML file.
+	Src string `android:"path"`
+}
+
+type vintfFragmentModule struct {
+	ModuleBase
+
+	properties vintfFragmentProperties
+
+	installDirPath InstallPath
+	outputFilePath OutputPath
+}
+
+func init() {
+	registerVintfFragmentComponents(InitRegistrationContext)
+}
+
+func registerVintfFragmentComponents(ctx RegistrationContext) {
+	ctx.RegisterModuleType("vintf_fragment", vintfLibraryFactory)
+}
+
+// vintf_fragment module processes vintf fragment file and installs under etc/vintf/manifest.
+// Vintf fragment files formerly listed in vintf_fragment property would be transformed into
+// this module type.
+func vintfLibraryFactory() Module {
+	m := &vintfFragmentModule{}
+	m.AddProperties(
+		&m.properties,
+	)
+	InitAndroidArchModule(m, DeviceSupported, MultilibFirst)
+
+	return m
+}
+
+func (m *vintfFragmentModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	builder := NewRuleBuilder(pctx, ctx)
+	srcVintfFragment := PathForModuleSrc(ctx, m.properties.Src)
+	processedVintfFragment := PathForModuleOut(ctx, srcVintfFragment.Base())
+
+	// Process vintf fragment source file with assemble_vintf tool
+	builder.Command().
+		Flag("VINTF_IGNORE_TARGET_FCM_VERSION=true").
+		BuiltTool("assemble_vintf").
+		FlagWithInput("-i ", srcVintfFragment).
+		FlagWithOutput("-o ", processedVintfFragment)
+
+	builder.Build("assemble_vintf", "Process vintf fragment "+processedVintfFragment.String())
+
+	m.installDirPath = PathForModuleInstall(ctx, "etc", "vintf", "manifest")
+	m.outputFilePath = processedVintfFragment.OutputPath
+
+	ctx.InstallFile(m.installDirPath, processedVintfFragment.Base(), processedVintfFragment)
+}
+
+// Make this module visible to AndroidMK so it can be referenced from modules defined from Android.mk files
+func (m *vintfFragmentModule) AndroidMkEntries() []AndroidMkEntries {
+	return []AndroidMkEntries{{
+		Class:      "ETC",
+		OutputFile: OptionalPathForPath(m.outputFilePath),
+		ExtraEntries: []AndroidMkExtraEntriesFunc{
+			func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
+				entries.SetString("LOCAL_MODULE_PATH", m.installDirPath.String())
+				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", m.outputFilePath.Base())
+			},
+		},
+	}}
+}
diff --git a/android/vintf_fragment_test.go b/android/vintf_fragment_test.go
new file mode 100644
index 0000000..8be534c
--- /dev/null
+++ b/android/vintf_fragment_test.go
@@ -0,0 +1,36 @@
+// Copyright 2024 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
+
+import (
+	"strings"
+	"testing"
+)
+
+func TestVintfManifestBuildAction(t *testing.T) {
+	bp := `
+	vintf_fragment {
+		name: "test_vintf_fragment",
+		src: "test_vintf_file",
+	}
+	`
+
+	testResult := PrepareForTestWithAndroidBuildComponents.RunTestWithBp(t, bp)
+
+	vintfFragmentBuild := testResult.TestContext.ModuleForTests("test_vintf_fragment", "android_arm64_armv8-a").Rule("assemble_vintf")
+	if !strings.Contains(vintfFragmentBuild.RuleParams.Command, "assemble_vintf") {
+		t.Errorf("Vintf_manifest build command does not process with assemble_vintf : " + vintfFragmentBuild.RuleParams.Command)
+	}
+}
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index 373e883..a2486fd 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -46,6 +46,9 @@
 
 	outputBaseName string
 	outputFile     android.OptionalPath
+
+	// TODO(b/357908583): Temp field, remove this once we support Android Mk providers
+	installFile android.InstallPath
 }
 
 type remapProperties struct {
@@ -234,14 +237,18 @@
 
 	s.outputBaseName = name
 	s.outputFile = android.OptionalPathForPath(outputZipFile)
-	ctx.InstallFile(android.PathForModuleInstall(ctx, "sdk-repo"), name+".zip", outputZipFile)
+	installPath := android.PathForModuleInstall(ctx, "sdk-repo")
+	name = name + ".zip"
+	ctx.InstallFile(installPath, name, outputZipFile)
+	// TODO(b/357908583): Temp field, remove this once we support Android Mk providers
+	s.installFile = installPath.Join(ctx, name)
 }
 
 func (s *sdkRepoHost) AndroidMk() android.AndroidMkData {
 	return android.AndroidMkData{
 		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
 			fmt.Fprintln(w, ".PHONY:", name, "sdk_repo", "sdk-repo-"+name)
-			fmt.Fprintln(w, "sdk_repo", "sdk-repo-"+name+":", strings.Join(s.FilesToInstall().Strings(), " "))
+			fmt.Fprintln(w, "sdk_repo", "sdk-repo-"+name+":", s.installFile.String())
 
 			fmt.Fprintf(w, "$(call dist-for-goals,sdk_repo sdk-repo-%s,%s:%s-FILE_NAME_TAG_PLACEHOLDER.zip)\n\n", s.BaseModuleName(), s.outputFile.String(), s.outputBaseName)
 		},
diff --git a/apex/apex.go b/apex/apex.go
index fc0500a..ec71c18 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -213,6 +213,50 @@
 
 type ApexNativeDependencies struct {
 	// List of native libraries that are embedded inside this APEX.
+	Native_shared_libs proptools.Configurable[[]string]
+
+	// List of JNI libraries that are embedded inside this APEX.
+	Jni_libs []string
+
+	// List of rust dyn libraries that are embedded inside this APEX.
+	Rust_dyn_libs []string
+
+	// List of native executables that are embedded inside this APEX.
+	Binaries proptools.Configurable[[]string]
+
+	// List of native tests that are embedded inside this APEX.
+	Tests []string
+
+	// List of filesystem images that are embedded inside this APEX bundle.
+	Filesystems []string
+
+	// List of prebuilt_etcs that are embedded inside this APEX bundle.
+	Prebuilts proptools.Configurable[[]string]
+
+	// List of native libraries to exclude from this APEX.
+	Exclude_native_shared_libs []string
+
+	// List of JNI libraries to exclude from this APEX.
+	Exclude_jni_libs []string
+
+	// List of rust dyn libraries to exclude from this APEX.
+	Exclude_rust_dyn_libs []string
+
+	// List of native executables to exclude from this APEX.
+	Exclude_binaries []string
+
+	// List of native tests to exclude from this APEX.
+	Exclude_tests []string
+
+	// List of filesystem images to exclude from this APEX bundle.
+	Exclude_filesystems []string
+
+	// List of prebuilt_etcs to exclude from this APEX bundle.
+	Exclude_prebuilts []string
+}
+
+type ResolvedApexNativeDependencies struct {
+	// List of native libraries that are embedded inside this APEX.
 	Native_shared_libs []string
 
 	// List of JNI libraries that are embedded inside this APEX.
@@ -222,8 +266,7 @@
 	Rust_dyn_libs []string
 
 	// List of native executables that are embedded inside this APEX.
-	Binaries         proptools.Configurable[[]string]
-	ResolvedBinaries []string `blueprint:"mutated"`
+	Binaries []string
 
 	// List of native tests that are embedded inside this APEX.
 	Tests []string
@@ -232,8 +275,7 @@
 	Filesystems []string
 
 	// List of prebuilt_etcs that are embedded inside this APEX bundle.
-	Prebuilts         proptools.Configurable[[]string]
-	ResolvedPrebuilts []string `blueprint:"mutated"`
+	Prebuilts []string
 
 	// List of native libraries to exclude from this APEX.
 	Exclude_native_shared_libs []string
@@ -258,14 +300,14 @@
 }
 
 // Merge combines another ApexNativeDependencies into this one
-func (a *ApexNativeDependencies) Merge(ctx android.BaseMutatorContext, b ApexNativeDependencies) {
-	a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...)
+func (a *ResolvedApexNativeDependencies) Merge(ctx android.BaseMutatorContext, b ApexNativeDependencies) {
+	a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs.GetOrDefault(ctx, nil)...)
 	a.Jni_libs = append(a.Jni_libs, b.Jni_libs...)
 	a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
-	a.ResolvedBinaries = append(a.ResolvedBinaries, b.Binaries.GetOrDefault(ctx, nil)...)
+	a.Binaries = append(a.Binaries, b.Binaries.GetOrDefault(ctx, nil)...)
 	a.Tests = append(a.Tests, b.Tests...)
 	a.Filesystems = append(a.Filesystems, b.Filesystems...)
-	a.ResolvedPrebuilts = append(a.ResolvedPrebuilts, b.Prebuilts.GetOrDefault(ctx, nil)...)
+	a.Prebuilts = append(a.Prebuilts, b.Prebuilts.GetOrDefault(ctx, nil)...)
 
 	a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
 	a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
@@ -700,7 +742,7 @@
 )
 
 // TODO(jiyong): shorten this function signature
-func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ApexNativeDependencies, target android.Target, imageVariation string) {
+func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ResolvedApexNativeDependencies, target android.Target, imageVariation string) {
 	binVariations := target.Variations()
 	libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
 	rustLibVariations := append(
@@ -718,7 +760,7 @@
 	// this module. This is required since arch variant of an APEX bundle is 'common' but it is
 	// 'arm' or 'arm64' for native shared libs.
 	ctx.AddFarVariationDependencies(binVariations, executableTag,
-		android.RemoveListFromList(nativeModules.ResolvedBinaries, nativeModules.Exclude_binaries)...)
+		android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
 	ctx.AddFarVariationDependencies(binVariations, testTag,
 		android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
 	ctx.AddFarVariationDependencies(libVariations, jniLibTag,
@@ -730,7 +772,7 @@
 	ctx.AddFarVariationDependencies(target.Variations(), fsTag,
 		android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
 	ctx.AddFarVariationDependencies(target.Variations(), prebuiltTag,
-		android.RemoveListFromList(nativeModules.ResolvedPrebuilts, nativeModules.Exclude_prebuilts)...)
+		android.RemoveListFromList(nativeModules.Prebuilts, nativeModules.Exclude_prebuilts)...)
 }
 
 func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -781,7 +823,7 @@
 		}
 	}
 	for i, target := range targets {
-		var deps ApexNativeDependencies
+		var deps ResolvedApexNativeDependencies
 
 		// Add native modules targeting both ABIs. When multilib.* is omitted for
 		// native_shared_libs/jni_libs/tests, it implies multilib.both
@@ -798,7 +840,7 @@
 		if isPrimaryAbi {
 			deps.Merge(ctx, a.properties.Multilib.First)
 			deps.Merge(ctx, ApexNativeDependencies{
-				Native_shared_libs: nil,
+				Native_shared_libs: proptools.NewConfigurable[[]string](nil, nil),
 				Tests:              nil,
 				Jni_libs:           nil,
 				Binaries:           a.properties.Binaries,
@@ -1035,7 +1077,7 @@
 
 	if a.dynamic_common_lib_apex() {
 		android.SetProvider(mctx, DCLAInfoProvider, DCLAInfo{
-			ProvidedLibs: a.properties.Native_shared_libs,
+			ProvidedLibs: a.properties.Native_shared_libs.GetOrDefault(mctx, nil),
 		})
 	}
 }
@@ -1492,7 +1534,7 @@
 		imageVariation := a.getImageVariation()
 		for _, target := range ctx.MultiTargets() {
 			if target.Arch.ArchType.Multilib == "lib64" {
-				addDependenciesForNativeModules(ctx, ApexNativeDependencies{
+				addDependenciesForNativeModules(ctx, ResolvedApexNativeDependencies{
 					Native_shared_libs: []string{"libclang_rt.hwasan"},
 					Tests:              nil,
 					Jni_libs:           nil,
@@ -2370,6 +2412,7 @@
 	a.providePrebuiltInfo(ctx)
 
 	a.required = a.RequiredModuleNames(ctx)
+	a.required = append(a.required, a.VintfFragmentModuleNames(ctx)...)
 
 	a.setOutputFiles(ctx)
 }
@@ -2766,10 +2809,21 @@
 		if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
 			return true
 		}
+
+		// Let's give some hint for apex_available
+		hint := fmt.Sprintf("%q", apexName)
+
+		if strings.HasPrefix(apexName, "com.") && !strings.HasPrefix(apexName, "com.android.") && strings.Count(apexName, ".") >= 2 {
+			// In case of a partner APEX, prefix format might be an option.
+			components := strings.Split(apexName, ".")
+			components[len(components)-1] = "*"
+			hint += fmt.Sprintf(" or %q", strings.Join(components, "."))
+		}
+
 		ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
 			"\n\nDependency path:%s\n\n"+
-			"Consider adding %q to 'apex_available' property of %q",
-			fromName, toName, ctx.GetPathString(true), apexName, toName)
+			"Consider adding %s to 'apex_available' property of %q",
+			fromName, toName, ctx.GetPathString(true), hint, toName)
 		// Visit this module's dependencies to check and report any issues with their availability.
 		return true
 	})
diff --git a/apex/apex_test.go b/apex/apex_test.go
index d6c8a8a..6b9944d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -384,7 +384,7 @@
 			symlink_preferred_arch: true,
 			system_shared_libs: [],
 			stl: "none",
-			apex_available: [ "myapex", "com.android.gki.*" ],
+			apex_available: [ "myapex" ],
 		}
 
 		rust_binary {
@@ -432,14 +432,6 @@
 			apex_available: ["myapex"],
 		}
 
-		apex {
-			name: "com.android.gki.fake",
-			binaries: ["foo"],
-			key: "myapex.key",
-			file_contexts: ":myapex-file_contexts",
-			updatable: false,
-		}
-
 		cc_library_shared {
 			name: "mylib2",
 			srcs: ["mylib.cpp"],
@@ -6730,6 +6722,99 @@
 	}
 }
 
+func TestApexAvailable_PrefixMatch(t *testing.T) {
+
+	for _, tc := range []struct {
+		name          string
+		apexAvailable string
+		expectedError string
+	}{
+		{
+			name:          "prefix matches correctly",
+			apexAvailable: "com.foo.*",
+		},
+		{
+			name:          "prefix doesn't match",
+			apexAvailable: "com.bar.*",
+			expectedError: `Consider .* "com.foo\.\*"`,
+		},
+		{
+			name:          "short prefix",
+			apexAvailable: "com.*",
+			expectedError: "requires two or more components",
+		},
+		{
+			name:          "wildcard not in the end",
+			apexAvailable: "com.*.foo",
+			expectedError: "should end with .*",
+		},
+		{
+			name:          "wildcard in the middle",
+			apexAvailable: "com.foo*.*",
+			expectedError: "not allowed in the middle",
+		},
+		{
+			name:          "hint with prefix pattern",
+			apexAvailable: "//apex_available:platform",
+			expectedError: "Consider adding \"com.foo.bar\" or \"com.foo.*\"",
+		},
+	} {
+		t.Run(tc.name, func(t *testing.T) {
+			errorHandler := android.FixtureExpectsNoErrors
+			if tc.expectedError != "" {
+				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
+			}
+			context := android.GroupFixturePreparers(
+				prepareForApexTest,
+				android.FixtureMergeMockFs(android.MockFS{
+					"system/sepolicy/apex/com.foo.bar-file_contexts": nil,
+				}),
+			).ExtendWithErrorHandler(errorHandler)
+
+			context.RunTestWithBp(t, `
+				apex {
+					name: "com.foo.bar",
+					key: "myapex.key",
+					native_shared_libs: ["libfoo"],
+					updatable: false,
+				}
+
+				apex_key {
+					name: "myapex.key",
+					public_key: "testkey.avbpubkey",
+					private_key: "testkey.pem",
+				}
+
+				cc_library {
+					name: "libfoo",
+					stl: "none",
+					system_shared_libs: [],
+					apex_available: ["`+tc.apexAvailable+`"],
+				}`)
+		})
+	}
+	testApexError(t, `Consider adding "com.foo" to`, `
+		apex {
+			name: "com.foo", // too short for a partner apex
+			key: "myapex.key",
+			native_shared_libs: ["libfoo"],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "libfoo",
+			stl: "none",
+			system_shared_libs: [],
+		}
+	`)
+}
+
 func TestOverrideApex(t *testing.T) {
 	ctx := testApex(t, `
 		apex {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 449510a..9dc8a63 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -459,7 +459,7 @@
 	// This cannot be marked as `android:"arch_variant"` because the `prebuilt_apex` is only mutated
 	// for android_common. That is so that it will have the same arch variant as, and so be compatible
 	// with, the source `apex` module type that it replaces.
-	Src  *string `android:"path"`
+	Src  proptools.Configurable[string] `android:"path,replace_instead_of_append"`
 	Arch struct {
 		Arm struct {
 			Src *string `android:"path"`
@@ -509,7 +509,7 @@
 		src = String(p.Arch.X86_64.Src)
 	}
 	if src == "" {
-		src = String(p.Src)
+		src = p.Src.GetOrDefault(ctx, "")
 	}
 
 	if src == "" {
@@ -722,7 +722,7 @@
 func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) {
 	if p.hasExportedDeps() {
 		// Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module
-		// The deapexer will return a provider that will be bubbled up to the rdeps of apexes (e.g. dex_bootjars)
+		// The deapexer will return a provider which will be used to determine the exported artfifacts from this prebuilt.
 		ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name()))
 	}
 }
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 71e0cd8..8a7ea88 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -132,7 +132,7 @@
 
 	if ccModule.linker != nil {
 		specifiedDeps := specifiedDeps{}
-		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
+		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx, ccModule, specifiedDeps)
 
 		p.SharedLibs = specifiedDeps.sharedLibs
 		p.SystemSharedLibs = specifiedDeps.systemSharedLibs
diff --git a/cc/builder.go b/cc/builder.go
index a05a16d..cd535c1 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -22,6 +22,7 @@
 	"fmt"
 	"path/filepath"
 	"runtime"
+	"slices"
 	"strconv"
 	"strings"
 
@@ -910,6 +911,16 @@
 		"ldFlags":       flags.globalLdFlags + " " + flags.localLdFlags,
 		"crtEnd":        strings.Join(crtEnd.Strings(), " "),
 	}
+
+	// On Windows, we always generate a PDB file
+	// --strip-debug is needed to also keep COFF symbols which are needed when
+	// we patch binaries with symbol_inject.
+	if ctx.Windows() {
+		pdb := outputFile.ReplaceExtension(ctx, "pdb")
+		args["ldFlags"] = args["ldFlags"] + " -Wl,--strip-debug -Wl,--pdb=" + pdb.String() + " "
+		implicitOutputs = append(slices.Clone(implicitOutputs), pdb)
+	}
+
 	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
 		rule = ldRE
 		args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",")
diff --git a/cc/cc.go b/cc/cc.go
index b3cac62..947dc1a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -613,7 +613,7 @@
 	coverageOutputFilePath() android.OptionalPath
 
 	// Get the deps that have been explicitly specified in the properties.
-	linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps
+	linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps
 
 	moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
 }
diff --git a/cc/cmake_module_cc.txt b/cc/cmake_module_cc.txt
index 0dc45ae..0f6e62f 100644
--- a/cc/cmake_module_cc.txt
+++ b/cc/cmake_module_cc.txt
@@ -2,10 +2,10 @@
 <<$includeDirs := getIncludeDirs .Ctx .M>>
 <<$cflags := getCflagsProperty .Ctx .M>>
 <<$deps := mapLibraries .Ctx .M (concat5
-(getLinkerProperties .M).Whole_static_libs
-(getLinkerProperties .M).Static_libs
-(getLinkerProperties .M).Shared_libs
-(getLinkerProperties .M).Header_libs
+(getWholeStaticLibsProperty .Ctx .M)
+(getStaticLibsProperty .Ctx .M)
+(getSharedLibsProperty .Ctx .M)
+(getHeaderLibsProperty .Ctx .M)
 (getExtraLibs .M)
 ) .Pprop.LibraryMapping>>
 <<$moduleType := getModuleType .M>>
diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go
index 8f3ad96..61fa46d 100644
--- a/cc/cmake_snapshot.go
+++ b/cc/cmake_snapshot.go
@@ -204,12 +204,28 @@
 			return m.compiler.baseCompilerProps()
 		},
 		"getCflagsProperty": func(ctx android.ModuleContext, m *Module) []string {
-			cflags := m.compiler.baseCompilerProps().Cflags
-			return cflags.GetOrDefault(ctx, nil)
+			prop := m.compiler.baseCompilerProps().Cflags
+			return prop.GetOrDefault(ctx, nil)
 		},
 		"getLinkerProperties": func(m *Module) BaseLinkerProperties {
 			return m.linker.baseLinkerProps()
 		},
+		"getWholeStaticLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
+			prop := m.linker.baseLinkerProps().Whole_static_libs
+			return prop.GetOrDefault(ctx, nil)
+		},
+		"getStaticLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
+			prop := m.linker.baseLinkerProps().Static_libs
+			return prop.GetOrDefault(ctx, nil)
+		},
+		"getSharedLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
+			prop := m.linker.baseLinkerProps().Shared_libs
+			return prop.GetOrDefault(ctx, nil)
+		},
+		"getHeaderLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
+			prop := m.linker.baseLinkerProps().Header_libs
+			return prop.GetOrDefault(ctx, nil)
+		},
 		"getExtraLibs":   getExtraLibs,
 		"getIncludeDirs": getIncludeDirs,
 		"mapLibraries": func(ctx android.ModuleContext, m *Module, libs []string, mapping map[string]LibraryMappingProperty) []string {
@@ -476,7 +492,8 @@
 		var prebuiltsList android.Paths
 
 		ctx.VisitDirectDepsWithTag(cmakeSnapshotPrebuiltTag, func(dep android.Module) {
-			for _, file := range dep.FilesToInstall() {
+			for _, file := range android.OtherModuleProviderOrDefault(
+				ctx, dep, android.InstallFilesProvider).InstallFiles {
 				prebuiltsList = append(prebuiltsList, file)
 			}
 		})
diff --git a/cc/compdb.go b/cc/compdb.go
index da28183..b33f490 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -85,23 +85,24 @@
 	if err != nil {
 		log.Fatalf("Could not create file %s: %s", compDBFile, err)
 	}
-	defer f.Close()
+	defer func() {
+		if err := f.Close(); err != nil {
+			log.Fatalf("Could not close file %s: %s", compDBFile, err)
+		}
+	}()
 
 	v := make([]compDbEntry, 0, len(m))
-
 	for _, value := range m {
 		v = append(v, value)
 	}
-	var dat []byte
+
+	w := json.NewEncoder(f)
 	if outputCompdbDebugInfo {
-		dat, err = json.MarshalIndent(v, "", " ")
-	} else {
-		dat, err = json.Marshal(v)
+		w.SetIndent("", " ")
 	}
-	if err != nil {
-		log.Fatalf("Failed to marshal: %s", err)
+	if err := w.Encode(v); err != nil {
+		log.Fatalf("Failed to encode: %s", err)
 	}
-	f.Write(dat)
 
 	if finalLinkDir := ctx.Config().Getenv(envVariableCompdbLink); finalLinkDir != "" {
 		finalLinkPath := filepath.Join(finalLinkDir, compdbFilename)
diff --git a/cc/compiler.go b/cc/compiler.go
index 0e0b9a7..396ec88 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -798,13 +798,13 @@
 	Local_include_dirs []string `android:"arch_variant,variant_prepend"`
 
 	// list of static libraries that provide headers for this binding.
-	Static_libs []string `android:"arch_variant,variant_prepend"`
+	Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of shared libraries that provide headers for this binding.
-	Shared_libs []string `android:"arch_variant"`
+	Shared_libs proptools.Configurable[[]string] `android:"arch_variant"`
 
 	// List of libraries which export include paths required for this module
-	Header_libs []string `android:"arch_variant,variant_prepend"`
+	Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of clang flags required to correctly interpret the headers.
 	Cflags proptools.Configurable[[]string] `android:"arch_variant"`
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 2ea607a..1783f49 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -29,6 +29,7 @@
 	darwinCflags = []string{
 		"-fPIC",
 		"-funwind-tables",
+		"-fno-omit-frame-pointer",
 
 		"-isysroot ${macSdkRoot}",
 		"-mmacosx-version-min=${macMinVersion}",
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 515cb21..ddc86c2 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -25,6 +25,8 @@
 
 		"-fPIC",
 
+		"-fno-omit-frame-pointer",
+
 		"-U_FORTIFY_SOURCE",
 		"-D_FORTIFY_SOURCE=2",
 		"-fstack-protector-strong",
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 7f22377..287967c 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -26,6 +26,8 @@
 
 		"-fPIC",
 
+		"-fno-omit-frame-pointer",
+
 		"-U_FORTIFY_SOURCE",
 		"-D_FORTIFY_SOURCE=2",
 		"-fstack-protector",
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 1e61b01..a4d43b9 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -43,6 +43,12 @@
 		"-mno-ms-bitfields",
 
 		"--sysroot ${WindowsGccRoot}/${WindowsGccTriple}",
+
+		// Windows flags to generate PDB
+		"-g",
+		"-gcodeview",
+
+		"-fno-omit-frame-pointer",
 	}
 
 	windowsIncludeFlags = []string{
diff --git a/cc/library.go b/cc/library.go
index de0070a..6017848 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -152,11 +152,11 @@
 
 	Cflags proptools.Configurable[[]string] `android:"arch_variant"`
 
-	Enabled            *bool    `android:"arch_variant"`
-	Whole_static_libs  []string `android:"arch_variant"`
-	Static_libs        []string `android:"arch_variant"`
-	Shared_libs        []string `android:"arch_variant"`
-	System_shared_libs []string `android:"arch_variant"`
+	Enabled            *bool                            `android:"arch_variant"`
+	Whole_static_libs  proptools.Configurable[[]string] `android:"arch_variant"`
+	Static_libs        proptools.Configurable[[]string] `android:"arch_variant"`
+	Shared_libs        proptools.Configurable[[]string] `android:"arch_variant"`
+	System_shared_libs []string                         `android:"arch_variant"`
 
 	Export_shared_lib_headers []string `android:"arch_variant"`
 	Export_static_lib_headers []string `android:"arch_variant"`
@@ -837,9 +837,9 @@
 
 	if library.static() {
 		deps.WholeStaticLibs = append(deps.WholeStaticLibs,
-			library.StaticProperties.Static.Whole_static_libs...)
-		deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs...)
-		deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs...)
+			library.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)...)
+		deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)...)
+		deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)...)
 
 		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.StaticProperties.Static.Export_shared_lib_headers...)
 		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.StaticProperties.Static.Export_static_lib_headers...)
@@ -852,9 +852,9 @@
 		if library.baseLinker.Properties.crtPadSegment() {
 			deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtPadSegmentSharedLibrary()...)
 		}
-		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs...)
-		deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs...)
-		deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs...)
+		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)...)
+		deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)...)
+		deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)...)
 
 		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.SharedProperties.Shared.Export_shared_lib_headers...)
 		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.SharedProperties.Shared.Export_static_lib_headers...)
@@ -900,8 +900,8 @@
 	return deps
 }
 
-func (library *libraryDecorator) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
-	specifiedDeps = library.baseLinker.linkerSpecifiedDeps(specifiedDeps)
+func (library *libraryDecorator) linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
+	specifiedDeps = library.baseLinker.linkerSpecifiedDeps(ctx, module, specifiedDeps)
 	var properties StaticOrSharedProperties
 	if library.static() {
 		properties = library.StaticProperties.Static
@@ -909,7 +909,8 @@
 		properties = library.SharedProperties.Shared
 	}
 
-	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs...)
+	eval := module.ConfigurableEvaluator(ctx)
+	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs.GetOrDefault(eval, nil)...)
 
 	// Must distinguish nil and [] in system_shared_libs - ensure that [] in
 	// either input list doesn't come out as nil.
@@ -2079,12 +2080,12 @@
 		// include directories.
 		if len(sharedCompiler.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)) == 0 &&
 			len(sharedCompiler.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)) == 0 &&
-			len(sharedCompiler.StaticProperties.Static.Whole_static_libs) == 0 &&
-			len(sharedCompiler.SharedProperties.Shared.Whole_static_libs) == 0 &&
-			len(sharedCompiler.StaticProperties.Static.Static_libs) == 0 &&
-			len(sharedCompiler.SharedProperties.Shared.Static_libs) == 0 &&
-			len(sharedCompiler.StaticProperties.Static.Shared_libs) == 0 &&
-			len(sharedCompiler.SharedProperties.Shared.Shared_libs) == 0 &&
+			len(sharedCompiler.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 &&
+			len(sharedCompiler.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 &&
+			len(sharedCompiler.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)) == 0 &&
+			len(sharedCompiler.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)) == 0 &&
+			len(sharedCompiler.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)) == 0 &&
+			len(sharedCompiler.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)) == 0 &&
 			// Compare System_shared_libs properties with nil because empty lists are
 			// semantically significant for them.
 			sharedCompiler.StaticProperties.Static.System_shared_libs == nil &&
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index e8a9827..053c460 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -543,7 +543,7 @@
 	p.ExportedFlags = exportedInfo.Flags
 	if ccModule.linker != nil {
 		specifiedDeps := specifiedDeps{}
-		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
+		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx, ccModule, specifiedDeps)
 
 		if lib := ccModule.library; lib != nil {
 			if !lib.hasStubsVariants() {
diff --git a/cc/linker.go b/cc/linker.go
index d2974c2..0056817 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -37,16 +37,16 @@
 	// in their entirety.  For static library modules, all of the .o files from the intermediate
 	// directory of the dependency will be linked into this modules .a file.  For a shared library,
 	// the dependency's .a file will be linked into this module using -Wl,--whole-archive.
-	Whole_static_libs []string `android:"arch_variant,variant_prepend"`
+	Whole_static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of modules that should be statically linked into this module.
-	Static_libs []string `android:"arch_variant,variant_prepend"`
+	Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of modules that should be dynamically linked into this module.
-	Shared_libs []string `android:"arch_variant"`
+	Shared_libs proptools.Configurable[[]string] `android:"arch_variant"`
 
 	// list of modules that should only provide headers for this module.
-	Header_libs []string `android:"arch_variant,variant_prepend"`
+	Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of module-specific flags that will be used for all link steps
 	Ldflags []string `android:"arch_variant"`
@@ -296,10 +296,10 @@
 }
 
 func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
-	deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
-	deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
-	deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
+	deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs.GetOrDefault(ctx, nil)...)
+	deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs.GetOrDefault(ctx, nil)...)
+	deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs.GetOrDefault(ctx, nil)...)
+	deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs.GetOrDefault(ctx, nil)...)
 	deps.RuntimeLibs = append(deps.RuntimeLibs, linker.Properties.Runtime_libs...)
 
 	deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...)
@@ -645,8 +645,9 @@
 	panic(fmt.Errorf("baseLinker doesn't know how to link"))
 }
 
-func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
-	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...)
+func (linker *baseLinker) linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
+	eval := module.ConfigurableEvaluator(ctx)
+	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs.GetOrDefault(eval, nil)...)
 
 	// Must distinguish nil and [] in system_shared_libs - ensure that [] in
 	// either input list doesn't come out as nil.
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 57a3b3a..e002931 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -18,6 +18,7 @@
 	"path/filepath"
 
 	"android/soong/android"
+
 	"github.com/google/blueprint"
 )
 
@@ -44,7 +45,7 @@
 }
 
 // Returns the NDK base include path for use with sdk_version current. Usable with -I.
-func getCurrentIncludePath(ctx android.ModuleContext) android.OutputPath {
+func getCurrentIncludePath(ctx android.PathContext) android.OutputPath {
 	return getNdkSysrootBase(ctx).Join(ctx, "usr/include")
 }
 
@@ -73,6 +74,13 @@
 
 	// Path to the NOTICE file associated with the headers.
 	License *string `android:"path"`
+
+	// Set to true if the headers installed by this module should skip
+	// verification. This step ensures that each header is self-contained (can
+	// be #included alone) and is valid C. This should not be disabled except in
+	// rare cases. Outside bionic and external, if you're using this option
+	// you've probably made a mistake.
+	Skip_verification *bool
 }
 
 type headerModule struct {
@@ -309,6 +317,13 @@
 
 	// Path to the NOTICE file associated with the headers.
 	License *string
+
+	// Set to true if the headers installed by this module should skip
+	// verification. This step ensures that each header is self-contained (can
+	// be #included alone) and is valid C. This should not be disabled except in
+	// rare cases. Outside bionic and external, if you're using this option
+	// you've probably made a mistake.
+	Skip_verification *bool
 }
 
 type preprocessedHeadersModule struct {
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 3c48f68..f571523 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -54,7 +54,22 @@
 
 import (
 	"android/soong/android"
+	"fmt"
+	"path/filepath"
 	"strings"
+
+	"github.com/google/blueprint"
+)
+
+var (
+	verifyCCompat = pctx.AndroidStaticRule("verifyCCompat",
+		blueprint.RuleParams{
+			Command:     "$ccCmd -x c -fsyntax-only $flags $in && touch $out",
+			CommandDeps: []string{"$ccCmd"},
+		},
+		"ccCmd",
+		"flags",
+	)
 )
 
 func init() {
@@ -103,6 +118,45 @@
 	return android.PathForOutput(ctx, "ndk_abi_headers.txt")
 }
 
+func verifyNdkHeaderIsCCompatible(ctx android.SingletonContext,
+	src android.Path, dest android.Path) android.Path {
+	sysrootInclude := getCurrentIncludePath(ctx)
+	baseOutputDir := android.PathForOutput(ctx, "c-compat-verification")
+	installRelPath, err := filepath.Rel(sysrootInclude.String(), dest.String())
+	if err != nil {
+		ctx.Errorf("filepath.Rel(%q, %q) failed: %s", dest, sysrootInclude, err)
+	}
+	output := baseOutputDir.Join(ctx, installRelPath)
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        verifyCCompat,
+		Description: fmt.Sprintf("Verifying C compatibility of %s", src),
+		Output:      output,
+		Input:       dest,
+		// Ensures that all the headers in the sysroot are already installed
+		// before testing any of the headers for C compatibility, and also that
+		// the check will be re-run whenever the sysroot changes. This is
+		// necessary because many of the NDK headers depend on other NDK
+		// headers, but we don't have explicit dependency tracking for that.
+		Implicits: []android.Path{getNdkHeadersTimestampFile(ctx)},
+		Args: map[string]string{
+			"ccCmd": "${config.ClangBin}/clang",
+			"flags": fmt.Sprintf(
+				// Ideally we'd check each ABI, multiple API levels,
+				// fortify/non-fortify, and a handful of other variations. It's
+				// a lot more difficult to do that though, and would eat up more
+				// build time. All the problems we've seen so far that this
+				// check would catch have been in arch-generic and
+				// minSdkVersion-generic code in frameworks though, so this is a
+				// good place to start.
+				"-target aarch64-linux-android%d --sysroot %s",
+				android.FutureApiLevel.FinalOrFutureInt(),
+				getNdkSysrootBase(ctx).String(),
+			),
+		},
+	})
+	return output
+}
+
 func NdkSingleton() android.Singleton {
 	return &ndkSingleton{}
 }
@@ -143,10 +197,17 @@
 
 type ndkSingleton struct{}
 
+type srcDestPair struct {
+	src  android.Path
+	dest android.Path
+}
+
 func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 	var staticLibInstallPaths android.Paths
 	var headerSrcPaths android.Paths
 	var headerInstallPaths android.Paths
+	var headersToVerify []srcDestPair
+	var headerCCompatVerificationTimestampPaths android.Paths
 	var installPaths android.Paths
 	var licensePaths android.Paths
 	ctx.VisitAllModules(func(module android.Module) {
@@ -157,6 +218,14 @@
 		if m, ok := module.(*headerModule); ok {
 			headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
 			headerInstallPaths = append(headerInstallPaths, m.installPaths...)
+			if !Bool(m.properties.Skip_verification) {
+				for i, installPath := range m.installPaths {
+					headersToVerify = append(headersToVerify, srcDestPair{
+						src:  m.srcPaths[i],
+						dest: installPath,
+					})
+				}
+			}
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
@@ -164,6 +233,10 @@
 		if m, ok := module.(*versionedHeaderModule); ok {
 			headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
 			headerInstallPaths = append(headerInstallPaths, m.installPaths...)
+			// Verification intentionally not done for headers that go through
+			// versioner. It'd be nice to have, but the only user is bionic, and
+			// that one module would also need to use skip_verification, so it
+			// wouldn't help at all.
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
@@ -171,6 +244,14 @@
 		if m, ok := module.(*preprocessedHeadersModule); ok {
 			headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
 			headerInstallPaths = append(headerInstallPaths, m.installPaths...)
+			if !Bool(m.properties.Skip_verification) {
+				for i, installPath := range m.installPaths {
+					headersToVerify = append(headersToVerify, srcDestPair{
+						src:  m.srcPaths[i],
+						dest: installPath,
+					})
+				}
+			}
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
@@ -223,6 +304,12 @@
 		Implicits: headerInstallPaths,
 	})
 
+	for _, srcDestPair := range headersToVerify {
+		headerCCompatVerificationTimestampPaths = append(
+			headerCCompatVerificationTimestampPaths,
+			verifyNdkHeaderIsCCompatible(ctx, srcDestPair.src, srcDestPair.dest))
+	}
+
 	writeNdkAbiSrcFilter(ctx, headerSrcPaths, getNdkABIHeadersFile(ctx))
 
 	fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
@@ -235,6 +322,6 @@
 	ctx.Build(pctx, android.BuildParams{
 		Rule:      android.Touch,
 		Output:    getNdkFullTimestampFile(ctx),
-		Implicits: fullDepPaths,
+		Implicits: append(fullDepPaths, headerCCompatVerificationTimestampPaths...),
 	})
 }
diff --git a/cc/object.go b/cc/object.go
index 8b23295..a4f4c84 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -19,6 +19,8 @@
 	"strings"
 
 	"android/soong/android"
+
+	"github.com/google/blueprint/proptools"
 )
 
 //
@@ -50,13 +52,13 @@
 
 type ObjectLinkerProperties struct {
 	// list of static library modules that should only provide headers for this module.
-	Static_libs []string `android:"arch_variant,variant_prepend"`
+	Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of shared library modules should only provide headers for this module.
-	Shared_libs []string `android:"arch_variant,variant_prepend"`
+	Shared_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of modules that should only provide headers for this module.
-	Header_libs []string `android:"arch_variant,variant_prepend"`
+	Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
 
 	// list of default libraries that will provide headers for this module.  If unset, generally
 	// defaults to libc, libm, and libdl.  Set to [] to prevent using headers from the defaults.
@@ -116,9 +118,9 @@
 func (*objectLinker) linkerInit(ctx BaseModuleContext) {}
 
 func (object *objectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs...)
-	deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs...)
-	deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs...)
+	deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs.GetOrDefault(ctx, nil)...)
+	deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs.GetOrDefault(ctx, nil)...)
+	deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs.GetOrDefault(ctx, nil)...)
 	deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
 
 	deps.SystemSharedLibs = object.Properties.System_shared_libs
@@ -201,8 +203,9 @@
 	return outputFile
 }
 
-func (object *objectLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
-	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs...)
+func (object *objectLinker) linkerSpecifiedDeps(ctx android.ConfigAndErrorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
+	eval := module.ConfigurableEvaluator(ctx)
+	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs.GetOrDefault(eval, nil)...)
 
 	// Must distinguish nil and [] in system_shared_libs - ensure that [] in
 	// either input list doesn't come out as nil.
diff --git a/cc/stub_library.go b/cc/stub_library.go
index 47c6cb9..f15a604 100644
--- a/cc/stub_library.go
+++ b/cc/stub_library.go
@@ -39,8 +39,9 @@
 }
 
 // Get target file name to be installed from this module
-func getInstalledFileName(m *Module) string {
-	for _, ps := range m.PackagingSpecs() {
+func getInstalledFileName(ctx android.SingletonContext, m *Module) string {
+	for _, ps := range android.OtherModuleProviderOrDefault(
+		ctx, m.Module(), android.InstallFilesProvider).PackagingSpecs {
 		if name := ps.FileName(); name != "" {
 			return name
 		}
@@ -53,7 +54,7 @@
 	ctx.VisitAllModules(func(module android.Module) {
 		if m, ok := module.(*Module); ok {
 			if IsStubTarget(m) {
-				if name := getInstalledFileName(m); name != "" {
+				if name := getInstalledFileName(ctx, m); name != "" {
 					s.stubLibraryMap[name] = true
 					if m.InVendor() {
 						s.stubVendorLibraryMap[name] = true
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 69d922d..a8fd368 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -61,7 +61,8 @@
 
 	deps := s.gatherFilteredPackagingSpecs(ctx)
 	ctx.WalkDeps(func(child, parent android.Module) bool {
-		for _, ps := range child.PackagingSpecs() {
+		for _, ps := range android.OtherModuleProviderOrDefault(
+			ctx, child, android.InstallFilesProvider).PackagingSpecs {
 			if _, ok := deps[ps.RelPathInPackage()]; ok {
 				modulesInPackageByModule[child] = true
 				modulesInPackageByName[child.Name()] = true
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 2557922..9195643 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -147,6 +147,21 @@
 
 	// Enable restat to update the output only if the output is changed
 	Write_if_changed *bool
+
+	// When set to true, an additional $(build_number_file) label will be available
+	// to use in the cmd. This will be the location of a text file containing the
+	// build number. The dependency on this file will be "order-only", meaning that
+	// the genrule will not rerun when only this file changes, to avoid rerunning
+	// the genrule every build, because the build number changes every build.
+	// This also means that you should not attempt to consume the build number from
+	// the result of this genrule in another build rule. If you do, the build number
+	// in the second build rule will be stale when the second build rule rebuilds
+	// but this genrule does not. Only certain allowlisted modules are allowed to
+	// use this property, usages of the build number should be kept to the absolute
+	// minimum. Particularly no modules on the system image may include the build
+	// number. Prefer using libbuildversion via the use_version_lib property on
+	// cc modules.
+	Uses_order_only_build_number_file *bool
 }
 
 type Module struct {
@@ -228,6 +243,15 @@
 	}
 }
 
+// This allowlist should be kept to the bare minimum, it's
+// intended for things that existed before the build number
+// was tightly controlled. Prefer using libbuildversion
+// via the use_version_lib property of cc modules.
+var genrule_build_number_allowlist = map[string]bool{
+	"build/soong/tests:gen":                   true,
+	"tools/tradefederation/core:tradefed_zip": true,
+}
+
 // generateCommonBuildActions contains build action generation logic
 // common to both the mixed build case and the legacy case of genrule processing.
 // To fully support genrule in mixed builds, the contents of this function should
@@ -470,6 +494,11 @@
 				return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil
 			case "genDir":
 				return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil
+			case "build_number_file":
+				if !proptools.Bool(g.properties.Uses_order_only_build_number_file) {
+					return reportError("to use the $(build_number_file) label, you must set uses_order_only_build_number_file: true")
+				}
+				return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildNumberFile(ctx))), nil
 			default:
 				if strings.HasPrefix(name, "location ") {
 					label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
@@ -516,6 +545,12 @@
 		cmd.Implicits(task.in)
 		cmd.ImplicitTools(tools)
 		cmd.ImplicitPackagedTools(packagedTools)
+		if proptools.Bool(g.properties.Uses_order_only_build_number_file) {
+			if _, ok := genrule_build_number_allowlist[ctx.ModuleDir()+":"+ctx.ModuleName()]; !ok {
+				ctx.ModuleErrorf("Only allowlisted modules may use uses_order_only_build_number_file: true")
+			}
+			cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx))
+		}
 
 		// Create the rule to run the genrule command inside sbox.
 		rule.Build(name, desc)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 444aedb..9278f15 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -19,6 +19,7 @@
 	"os"
 	"regexp"
 	"strconv"
+	"strings"
 	"testing"
 
 	"android/soong/android"
@@ -1192,6 +1193,68 @@
 	}
 }
 
+func TestGenruleUsesOrderOnlyBuildNumberFile(t *testing.T) {
+	testCases := []struct {
+		name            string
+		bp              string
+		fs              android.MockFS
+		expectedError   string
+		expectedCommand string
+	}{
+		{
+			name: "not allowed when not in allowlist",
+			fs: android.MockFS{
+				"foo/Android.bp": []byte(`
+genrule {
+	name: "gen",
+	uses_order_only_build_number_file: true,
+	cmd: "cp $(build_number_file) $(out)",
+	out: ["out.txt"],
+}
+`),
+			},
+			expectedError: `Only allowlisted modules may use uses_order_only_build_number_file: true`,
+		},
+		{
+			name: "normal",
+			fs: android.MockFS{
+				"build/soong/tests/Android.bp": []byte(`
+genrule {
+	name: "gen",
+	uses_order_only_build_number_file: true,
+	cmd: "cp $(build_number_file) $(out)",
+	out: ["out.txt"],
+}
+`),
+			},
+			expectedCommand: `cp BUILD_NUMBER_FILE __SBOX_SANDBOX_DIR__/out/out.txt`,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			fixtures := android.GroupFixturePreparers(
+				prepareForGenRuleTest,
+				android.PrepareForTestWithVisibility,
+				android.FixtureMergeMockFs(tc.fs),
+				android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) {
+					config.TestProductVariables.BuildNumberFile = proptools.StringPtr("build_number.txt")
+				}),
+			)
+			if tc.expectedError != "" {
+				fixtures = fixtures.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
+			}
+			result := fixtures.RunTest(t)
+
+			if tc.expectedError == "" {
+				tc.expectedCommand = strings.ReplaceAll(tc.expectedCommand, "BUILD_NUMBER_FILE", result.Config.SoongOutDir()+"/build_number.txt")
+				gen := result.Module("gen", "").(*Module)
+				android.AssertStringEquals(t, "raw commands", tc.expectedCommand, gen.rawCommands[0])
+			}
+		})
+	}
+}
+
 type testTool struct {
 	android.ModuleBase
 	outputFile android.Path
diff --git a/java/aar.go b/java/aar.go
index c8563c8..e6ad502 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -1154,8 +1154,9 @@
 
 	if Bool(a.properties.Jetifier) {
 		inputFile := a.aarPath
-		a.aarPath = android.PathForModuleOut(ctx, "jetifier", aarName)
-		TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile)
+		jetifierPath := android.PathForModuleOut(ctx, "jetifier", aarName)
+		TransformJetifier(ctx, jetifierPath, inputFile)
+		a.aarPath = jetifierPath
 	}
 
 	jarName := ctx.ModuleName() + ".jar"
@@ -1306,11 +1307,12 @@
 		addMissingOptionalUsesLibsFromDep(ctx, module, &a.usesLibrary)
 	})
 
-	var implementationJarFile android.OutputPath
+	var implementationJarFile android.Path
 	if len(staticJars) > 0 {
 		combineJars := append(android.Paths{classpathFile}, staticJars...)
-		implementationJarFile = android.PathForModuleOut(ctx, "combined", jarName).OutputPath
-		TransformJarsToJar(ctx, implementationJarFile, "combine", combineJars, android.OptionalPath{}, false, nil, nil)
+		combinedImplementationJar := android.PathForModuleOut(ctx, "combined", jarName).OutputPath
+		TransformJarsToJar(ctx, combinedImplementationJar, "combine", combineJars, android.OptionalPath{}, false, nil, nil)
+		implementationJarFile = combinedImplementationJar
 	} else {
 		implementationJarFile = classpathFile
 	}
@@ -1329,7 +1331,7 @@
 	implementationAndResourcesJar := implementationJarFile
 	if resourceJarFile != nil {
 		jars := android.Paths{resourceJarFile, implementationAndResourcesJar}
-		combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath
+		combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
 		TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
 			false, nil, nil)
 		implementationAndResourcesJar = combinedJar
diff --git a/java/app.go b/java/app.go
index 19dc8d5..1ebf658 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1109,7 +1109,7 @@
 						coverageFile:   dep.CoverageOutputFile(),
 						unstrippedFile: dep.UnstrippedOutputFile(),
 						partition:      dep.Partition(),
-						installPaths:   dep.FilesToInstall(),
+						installPaths:   android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider).InstallFiles,
 					})
 				} else if ctx.Config().AllowMissingDependencies() {
 					ctx.AddMissingDependencies([]string{otherName})
diff --git a/java/base.go b/java/base.go
index 8a4c64d..4ab82c5 100644
--- a/java/base.go
+++ b/java/base.go
@@ -222,6 +222,13 @@
 	// the stubs via libs, but should be set to true when the module depends on
 	// the stubs via static libs.
 	Is_stubs_module *bool
+
+	// If true, enable the "Ravenizer" tool on the output jar.
+	// "Ravenizer" is a tool for Ravenwood tests, but it can also be enabled on other kinds
+	// of java targets.
+	Ravenizer struct {
+		Enabled *bool
+	}
 }
 
 // Properties that are specific to device modules. Host module factories should not add these when
@@ -558,13 +565,23 @@
 	// List of soong module dependencies required to compile the current module.
 	// This information is printed out to `Dependencies` field in module_bp_java_deps.json
 	compileDepNames []string
+
+	ravenizer struct {
+		enabled bool
+	}
 }
 
 var _ android.InstallableModule = (*Module)(nil)
 
 // To satisfy the InstallableModule interface
-func (j *Module) EnforceApiContainerChecks() bool {
-	return true
+func (j *Module) StaticDependencyTags() []blueprint.DependencyTag {
+	return []blueprint.DependencyTag{staticLibTag}
+}
+
+// To satisfy the InstallableModule interface
+func (j *Module) DynamicDependencyTags() []blueprint.DependencyTag {
+	return []blueprint.DependencyTag{libTag, sdkLibTag, bootClasspathTag, systemModulesTag,
+		instrumentationForTag, java9LibTag}
 }
 
 // Overrides android.ModuleBase.InstallInProduct()
@@ -875,9 +892,12 @@
 	if j.hasSrcExt(".kt") {
 		// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
 		// Kotlin files
-		ctx.AddVariationDependencies(nil, kotlinStdlibTag,
-			"kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")
-		ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
+		tag := staticLibTag
+		if !BoolDefault(j.properties.Static_kotlin_stdlib, true) {
+			tag = libTag
+		}
+		ctx.AddVariationDependencies(nil, tag,
+			"kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-annotations")
 	}
 
 	// Framework libraries need special handling in static coverage builds: they should not have
@@ -1113,7 +1133,6 @@
 }
 
 func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
-
 	// Auto-propagating jarjar rules
 	jarjarProviderData := j.collectJarJarRules(ctx)
 	if jarjarProviderData != nil {
@@ -1130,6 +1149,10 @@
 
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
 
+	if re := proptools.Bool(j.properties.Ravenizer.Enabled); re {
+		j.ravenizer.enabled = re
+	}
+
 	deps := j.collectDeps(ctx)
 	flags := j.collectBuilderFlags(ctx, deps)
 
@@ -1211,7 +1234,6 @@
 
 	var kotlinJars android.Paths
 	var kotlinHeaderJars android.Paths
-	var kotlinExtraJars android.Paths
 
 	// Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before
 	// any dependencies so that it can override any non-final R classes from dependencies with the
@@ -1290,9 +1312,6 @@
 		// Collect common .kt files for AIDEGen
 		j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
 
-		flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
-		flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
-
 		flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
 		flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
 
@@ -1322,8 +1341,6 @@
 
 		kotlinJars = append(kotlinJars, kotlinJarPath)
 		kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
-		kotlinExtraJars = append(kotlinExtraJars, deps.kotlinStdlib...)
-		kotlinExtraJars = append(kotlinExtraJars, deps.kotlinAnnotations...)
 	}
 
 	jars := slices.Clone(kotlinJars)
@@ -1342,9 +1359,6 @@
 			// with sharding enabled. See: b/77284273.
 		}
 		extraJars := slices.Clone(kotlinHeaderJars)
-		if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
-			extraJars = append(extraJars, kotlinExtraJars...)
-		}
 		extraJars = append(extraJars, extraCombinedJars...)
 		var combinedHeaderJarFile android.Path
 		headerJarFileWithoutDepsOrJarjar, combinedHeaderJarFile =
@@ -1423,13 +1437,6 @@
 		}
 	}
 
-	// Jar kotlin classes into the final jar after javac
-	if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
-		jars = append(jars, kotlinExtraJars...)
-	} else {
-		flags.dexClasspath = append(flags.dexClasspath, kotlinExtraJars...)
-	}
-
 	jars = append(jars, extraCombinedJars...)
 
 	j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles
@@ -1568,6 +1575,18 @@
 		return
 	}
 
+	if j.ravenizer.enabled {
+		ravenizerInput := outputFile
+		ravenizerOutput := android.PathForModuleOut(ctx, "ravenizer", jarName)
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        ravenizer,
+			Description: "ravenizer",
+			Input:       ravenizerInput,
+			Output:      ravenizerOutput,
+		})
+		outputFile = ravenizerOutput
+	}
+
 	// Check package restrictions if necessary.
 	if len(j.properties.Permitted_packages) > 0 {
 		// Time stamp file created by the package check rule.
@@ -2343,10 +2362,6 @@
 				} else {
 					ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
 				}
-			case kotlinStdlibTag:
-				deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...)
-			case kotlinAnnotationsTag:
-				deps.kotlinAnnotations = dep.HeaderJars
 			case kotlinPluginTag:
 				deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
 			case syspropPublicStubDepTag:
@@ -2570,8 +2585,6 @@
 					return RenameUseInclude, "tagswitch"
 				case exportedPluginTag:
 					return RenameUseInclude, "tagswitch"
-				case kotlinStdlibTag, kotlinAnnotationsTag:
-					return RenameUseExclude, "tagswitch"
 				case kotlinPluginTag:
 					return RenameUseInclude, "tagswitch"
 				default:
diff --git a/java/builder.go b/java/builder.go
index 5d84d0b..49207e5 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -156,7 +156,7 @@
 	turbine, turbineRE = pctx.RemoteStaticRules("turbine",
 		blueprint.RuleParams{
 			Command: `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} $outputFlags ` +
-				`--sources @$out.rsp  --source_jars $srcJars ` +
+				`--sources @$out.rsp ` +
 				`--javacopts ${config.CommonJdkFlags} ` +
 				`$javacFlags -source $javaVersion -target $javaVersion -- $turbineFlags && ` +
 				`(for o in $outputs; do if cmp -s $${o}.tmp $${o} ; then rm $${o}.tmp ; else mv $${o}.tmp $${o} ; fi; done )`,
@@ -170,13 +170,13 @@
 		},
 		&remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"},
 			ExecStrategy:    "${config.RETurbineExecStrategy}",
-			Inputs:          []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"},
-			RSPFiles:        []string{"${out}.rsp"},
+			Inputs:          []string{"${config.TurbineJar}", "${out}.rsp", "$rbeInputs"},
+			RSPFiles:        []string{"$out.rsp", "$rspFiles"},
 			OutputFiles:     []string{"$rbeOutputs"},
 			ToolchainInputs: []string{"${config.JavaCmd}"},
 			Platform:        map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
 		},
-		[]string{"javacFlags", "turbineFlags", "outputFlags", "javaVersion", "outputs", "rbeOutputs", "srcJars"}, []string{"implicits"})
+		[]string{"javacFlags", "turbineFlags", "outputFlags", "javaVersion", "outputs", "rbeOutputs"}, []string{"rbeInputs", "rspFiles"})
 
 	jar, jarRE = pctx.RemoteStaticRules("jar",
 		blueprint.RuleParams{
@@ -258,6 +258,13 @@
 		},
 	)
 
+	ravenizer = pctx.AndroidStaticRule("ravenizer",
+		blueprint.RuleParams{
+			Command:     "rm -f $out && ${ravenizer} --in-jar $in --out-jar $out",
+			CommandDeps: []string{"${ravenizer}"},
+		},
+	)
+
 	zipalign = pctx.AndroidStaticRule("zipalign",
 		blueprint.RuleParams{
 			Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " +
@@ -307,6 +314,7 @@
 	pctx.Import("android/soong/java/config")
 
 	pctx.HostBinToolVariable("aconfig", "aconfig")
+	pctx.HostBinToolVariable("ravenizer", "ravenizer")
 	pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis")
 }
 
@@ -428,53 +436,72 @@
 		})
 }
 
-func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string) (string, android.Paths) {
-	var deps android.Paths
+func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string, srcJars android.Paths) (string, android.Paths, android.Paths, android.Paths) {
+	var implicits android.Paths
+	var rbeInputs android.Paths
+	var rspFiles android.Paths
 
 	classpath := flags.classpath
 
-	var bootClasspath string
+	srcJarArgs := strings.Join(srcJars.Strings(), " ")
+	implicits = append(implicits, srcJars...)
+	const srcJarArgsLimit = 32 * 1024
+	if len(srcJarArgs) > srcJarArgsLimit {
+		srcJarRspFile := android.PathForModuleOut(ctx, "turbine", "srcjars.rsp")
+		android.WriteFileRule(ctx, srcJarRspFile, srcJarArgs)
+		srcJarArgs = "@" + srcJarRspFile.String()
+		implicits = append(implicits, srcJarRspFile)
+		rbeInputs = append(rbeInputs, srcJarRspFile)
+	} else {
+		rbeInputs = append(rbeInputs, srcJars...)
+	}
+
+	var bootClasspathFlags string
 	if flags.javaVersion.usesJavaModules() {
 		var systemModuleDeps android.Paths
-		bootClasspath, systemModuleDeps = flags.systemModules.FormTurbineSystemModulesPath(ctx.Device())
-		deps = append(deps, systemModuleDeps...)
+		bootClasspathFlags, systemModuleDeps = flags.systemModules.FormTurbineSystemModulesPath(ctx.Device())
+		implicits = append(implicits, systemModuleDeps...)
+		rbeInputs = append(rbeInputs, systemModuleDeps...)
 		classpath = append(flags.java9Classpath, classpath...)
 	} else {
-		deps = append(deps, flags.bootClasspath...)
+		implicits = append(implicits, flags.bootClasspath...)
+		rbeInputs = append(rbeInputs, flags.bootClasspath...)
 		if len(flags.bootClasspath) == 0 && ctx.Device() {
 			// explicitly specify -bootclasspath "" if the bootclasspath is empty to
 			// ensure turbine does not fall back to the default bootclasspath.
-			bootClasspath = `--bootclasspath ""`
+			bootClasspathFlags = `--bootclasspath ""`
 		} else {
-			bootClasspath = flags.bootClasspath.FormTurbineClassPath("--bootclasspath ")
+			bootClasspathFlags = flags.bootClasspath.FormTurbineClassPath("--bootclasspath ")
 		}
 	}
 
-	deps = append(deps, classpath...)
-	turbineFlags := bootClasspath + " " + classpath.FormTurbineClassPath("--classpath ")
-
-	const flagsLimit = 32 * 1024
-	if len(turbineFlags) > flagsLimit {
-		flagsRspFile := android.PathForModuleOut(ctx, dir, "turbine-flags.rsp")
-		android.WriteFileRule(ctx, flagsRspFile, turbineFlags)
-		turbineFlags = "@" + flagsRspFile.String()
-		deps = append(deps, flagsRspFile)
+	classpathFlags := classpath.FormTurbineClassPath("")
+	implicits = append(implicits, classpath...)
+	const classpathLimit = 32 * 1024
+	if len(classpathFlags) > classpathLimit {
+		classpathRspFile := android.PathForModuleOut(ctx, dir, "classpath.rsp")
+		android.WriteFileRule(ctx, classpathRspFile, classpathFlags)
+		classpathFlags = "@" + classpathRspFile.String()
+		implicits = append(implicits, classpathRspFile)
+		rspFiles = append(rspFiles, classpathRspFile)
+		rbeInputs = append(rbeInputs, classpathRspFile)
+	} else {
+		rbeInputs = append(rbeInputs, classpath...)
 	}
 
-	return turbineFlags, deps
+	turbineFlags := "--source_jars " + srcJarArgs + " " + bootClasspathFlags + " --classpath " + classpathFlags
+
+	return turbineFlags, implicits, rbeInputs, rspFiles
 }
 
 func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
-	turbineFlags, deps := turbineFlags(ctx, flags, "turbine")
-
-	deps = append(deps, srcJars...)
+	turbineFlags, implicits, rbeInputs, rspFiles := turbineFlags(ctx, flags, "turbine", srcJars)
 
 	rule := turbine
 	args := map[string]string{
 		"javacFlags":   flags.javacFlags,
-		"srcJars":      strings.Join(srcJars.Strings(), " "),
 		"javaVersion":  flags.javaVersion.String(),
 		"turbineFlags": turbineFlags,
 		"outputFlags":  "--output " + outputFile.String() + ".tmp",
@@ -482,15 +509,16 @@
 	}
 	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
 		rule = turbineRE
-		args["implicits"] = strings.Join(deps.Strings(), ",")
+		args["rbeInputs"] = strings.Join(rbeInputs.Strings(), ",")
 		args["rbeOutputs"] = outputFile.String() + ".tmp"
+		args["rspFiles"] = strings.Join(rspFiles.Strings(), ",")
 	}
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        rule,
 		Description: "turbine",
 		Output:      outputFile,
 		Inputs:      srcFiles,
-		Implicits:   deps,
+		Implicits:   implicits,
 		Args:        args,
 	})
 }
@@ -499,11 +527,10 @@
 func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
-	turbineFlags, deps := turbineFlags(ctx, flags, "kapt")
+	turbineFlags, implicits, rbeInputs, rspFiles := turbineFlags(ctx, flags, "turbine-apt", srcJars)
 
-	deps = append(deps, srcJars...)
-
-	deps = append(deps, flags.processorPath...)
+	implicits = append(implicits, flags.processorPath...)
+	rbeInputs = append(rbeInputs, flags.processorPath...)
 	turbineFlags += " " + flags.processorPath.FormTurbineClassPath("--processorpath ")
 	turbineFlags += " --processors " + strings.Join(flags.processors, " ")
 
@@ -514,7 +541,6 @@
 	rule := turbine
 	args := map[string]string{
 		"javacFlags":   flags.javacFlags,
-		"srcJars":      strings.Join(srcJars.Strings(), " "),
 		"javaVersion":  flags.javaVersion.String(),
 		"turbineFlags": turbineFlags,
 		"outputFlags":  outputFlags,
@@ -522,8 +548,9 @@
 	}
 	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
 		rule = turbineRE
-		args["implicits"] = strings.Join(deps.Strings(), ",")
+		args["rbeInputs"] = strings.Join(rbeInputs.Strings(), ",")
 		args["rbeOutputs"] = outputSrcJar.String() + ".tmp," + outputResJar.String() + ".tmp"
+		args["rspFiles"] = strings.Join(rspFiles.Strings(), ",")
 	}
 	ctx.Build(pctx, android.BuildParams{
 		Rule:            rule,
@@ -531,7 +558,7 @@
 		Output:          outputs[0],
 		ImplicitOutputs: outputs[1:],
 		Inputs:          srcFiles,
-		Implicits:       deps,
+		Implicits:       implicits,
 		Args:            args,
 	})
 }
@@ -746,6 +773,16 @@
 	})
 }
 
+func TransformRavenizer(ctx android.ModuleContext, outputFile android.WritablePath,
+	inputFile android.Path) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        ravenizer,
+		Description: "ravenizer",
+		Output:      outputFile,
+		Input:       inputFile,
+	})
+}
+
 func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) {
 	android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
 }
diff --git a/java/config/config.go b/java/config/config.go
index 66e857c..a50c1b4 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -47,7 +47,7 @@
 		"services",
 		"android.car",
 		"android.car7",
-		"android.car.builtin",
+		"android.car.builtin.impl",
 		"conscrypt",
 		"core-icu4j",
 		"core-oj",
diff --git a/java/container_test.go b/java/container_test.go
index 3441855..25cfa4c 100644
--- a/java/container_test.go
+++ b/java/container_test.go
@@ -65,6 +65,18 @@
 				"general-tests",
 			],
 		}
+		java_library {
+			name: "bar",
+			static_libs: [
+				"framework-minus-apex",
+			],
+		}
+		java_library {
+			name: "baz",
+			static_libs: [
+				"bar",
+			],
+		}
 	`)
 
 	testcases := []struct {
@@ -73,6 +85,7 @@
 		isVendorContainer  bool
 		isProductContainer bool
 		isCts              bool
+		isUnstable         bool
 	}{
 		{
 			moduleName:         "foo",
@@ -80,6 +93,7 @@
 			isVendorContainer:  false,
 			isProductContainer: false,
 			isCts:              false,
+			isUnstable:         false,
 		},
 		{
 			moduleName:         "foo_vendor",
@@ -87,6 +101,7 @@
 			isVendorContainer:  true,
 			isProductContainer: false,
 			isCts:              false,
+			isUnstable:         false,
 		},
 		{
 			moduleName:         "foo_soc_specific",
@@ -94,6 +109,7 @@
 			isVendorContainer:  true,
 			isProductContainer: false,
 			isCts:              false,
+			isUnstable:         false,
 		},
 		{
 			moduleName:         "foo_product_specific",
@@ -101,6 +117,7 @@
 			isVendorContainer:  false,
 			isProductContainer: true,
 			isCts:              false,
+			isUnstable:         false,
 		},
 		{
 			moduleName:         "foo_cts_test",
@@ -108,6 +125,7 @@
 			isVendorContainer:  false,
 			isProductContainer: false,
 			isCts:              true,
+			isUnstable:         false,
 		},
 		{
 			moduleName:         "foo_non_cts_test",
@@ -115,6 +133,23 @@
 			isVendorContainer:  false,
 			isProductContainer: false,
 			isCts:              false,
+			isUnstable:         false,
+		},
+		{
+			moduleName:         "bar",
+			isSystemContainer:  true,
+			isVendorContainer:  false,
+			isProductContainer: false,
+			isCts:              false,
+			isUnstable:         true,
+		},
+		{
+			moduleName:         "baz",
+			isSystemContainer:  true,
+			isVendorContainer:  false,
+			isProductContainer: false,
+			isCts:              false,
+			isUnstable:         true,
 		},
 	}
 
@@ -125,5 +160,7 @@
 		checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
 		checkContainerMatch(t, c.moduleName, "vendor", c.isVendorContainer, android.InList(android.VendorContainer, belongingContainers))
 		checkContainerMatch(t, c.moduleName, "product", c.isProductContainer, android.InList(android.ProductContainer, belongingContainers))
+		checkContainerMatch(t, c.moduleName, "cts", c.isCts, android.InList(android.CtsContainer, belongingContainers))
+		checkContainerMatch(t, c.moduleName, "unstable", c.isUnstable, android.InList(android.UnstableContainer, belongingContainers))
 	}
 }
diff --git a/java/dex.go b/java/dex.go
index d88e8f8..6c739a2 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -289,15 +289,18 @@
 	// - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version.
 	// - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version.
 	// See b/20667396
-	var proguardRaiseDeps classpath
-	ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
-		if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
-			proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
-		}
-	})
+	// TODO(b/360905238): Remove SdkSystemServer exception after resolving missing class references.
+	if !dexParams.sdkVersion.Stable() || dexParams.sdkVersion.Kind == android.SdkSystemServer {
+		var proguardRaiseDeps classpath
+		ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
+			if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+				proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
+			}
+		})
+		r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
+		r8Deps = append(r8Deps, proguardRaiseDeps...)
+	}
 
-	r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
-	r8Deps = append(r8Deps, proguardRaiseDeps...)
 	r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
 	r8Deps = append(r8Deps, flags.bootClasspath...)
 	r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
diff --git a/java/java.go b/java/java.go
index 126d8f3..46344c8 100644
--- a/java/java.go
+++ b/java/java.go
@@ -421,8 +421,6 @@
 	bootClasspathTag        = dependencyTag{name: "bootclasspath", runtimeLinked: true}
 	systemModulesTag        = dependencyTag{name: "system modules", runtimeLinked: true}
 	frameworkResTag         = dependencyTag{name: "framework-res"}
-	kotlinStdlibTag         = dependencyTag{name: "kotlin-stdlib", runtimeLinked: true}
-	kotlinAnnotationsTag    = dependencyTag{name: "kotlin-annotations", runtimeLinked: true}
 	kotlinPluginTag         = dependencyTag{name: "kotlin-plugin", toolchain: true}
 	proguardRaiseTag        = dependencyTag{name: "proguard-raise"}
 	certificateTag          = dependencyTag{name: "certificate"}
@@ -458,8 +456,6 @@
 		bootClasspathTag,
 		systemModulesTag,
 		java9LibTag,
-		kotlinStdlibTag,
-		kotlinAnnotationsTag,
 		kotlinPluginTag,
 		syspropPublicStubDepTag,
 		instrumentationForTag,
@@ -568,8 +564,6 @@
 	srcJars                 android.Paths
 	systemModules           *systemModules
 	aidlPreprocess          android.OptionalPath
-	kotlinStdlib            android.Paths
-	kotlinAnnotations       android.Paths
 	kotlinPlugins           android.Paths
 	aconfigProtoFiles       android.Paths
 
@@ -1870,10 +1864,12 @@
 	if ctx.Arch().ArchType == android.Common {
 		j.deps(ctx)
 	}
-	if ctx.Arch().ArchType != android.Common {
-		// These dependencies ensure the host installation rules will install the jar file and
-		// the jni libraries when the wrapper is installed.
+	// These dependencies ensure the installation rules will install the jar file when the
+	// wrapper is installed, and the jni libraries on host when the wrapper is installed.
+	if ctx.Arch().ArchType != android.Common && ctx.Os().Class == android.Host {
 		ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
+	}
+	if ctx.Arch().ArchType != android.Common {
 		ctx.AddVariationDependencies(
 			[]blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
 			binaryInstallTag, ctx.ModuleName())
@@ -2640,6 +2636,7 @@
 
 	j.collectTransitiveHeaderJars(ctx)
 	var staticJars android.Paths
+	var staticResourceJars android.Paths
 	var staticHeaderJars android.Paths
 	ctx.VisitDirectDeps(func(module android.Module) {
 		tag := ctx.OtherModuleDependencyTag(module)
@@ -2650,7 +2647,8 @@
 				flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
 			case staticLibTag:
 				flags.classpath = append(flags.classpath, dep.HeaderJars...)
-				staticJars = append(staticJars, dep.ImplementationAndResourcesJars...)
+				staticJars = append(staticJars, dep.ImplementationJars...)
+				staticResourceJars = append(staticResourceJars, dep.ResourceJars...)
 				staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
 			case bootClasspathTag:
 				flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
@@ -2670,43 +2668,67 @@
 
 	// Always pass the input jars to TransformJarsToJar, even if there is only a single jar, we need the output
 	// file of the module to be named jarName.
-	outputFile := android.PathForModuleOut(ctx, "combined", jarName)
+	var outputFile android.Path
+	combinedImplementationJar := android.PathForModuleOut(ctx, "combined", jarName)
 	implementationJars := append(slices.Clone(jars), staticJars...)
-	TransformJarsToJar(ctx, outputFile, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
+	TransformJarsToJar(ctx, combinedImplementationJar, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
 		false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+	outputFile = combinedImplementationJar
 
 	// If no dependencies have separate header jars then there is no need to create a separate
 	// header jar for this module.
 	reuseImplementationJarAsHeaderJar := slices.Equal(staticJars, staticHeaderJars)
 
-	var headerOutputFile android.ModuleOutPath
+	var resourceJarFile android.Path
+	if len(staticResourceJars) > 1 {
+		combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
+		TransformJarsToJar(ctx, combinedJar, "for resources", staticResourceJars, android.OptionalPath{},
+			false, nil, nil)
+		resourceJarFile = combinedJar
+	} else if len(staticResourceJars) == 1 {
+		resourceJarFile = staticResourceJars[0]
+	}
+
+	var headerJar android.Path
 	if reuseImplementationJarAsHeaderJar {
-		headerOutputFile = outputFile
+		headerJar = outputFile
 	} else {
 		headerJars := append(slices.Clone(jars), staticHeaderJars...)
-		headerOutputFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
+		headerOutputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
 		TransformJarsToJar(ctx, headerOutputFile, "combine prebuilt header jars", headerJars, android.OptionalPath{},
 			false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+		headerJar = headerOutputFile
 	}
 
 	if Bool(j.properties.Jetifier) {
-		inputFile := outputFile
-		outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
-		TransformJetifier(ctx, outputFile, inputFile)
+		jetifierOutputFile := android.PathForModuleOut(ctx, "jetifier", jarName)
+		TransformJetifier(ctx, jetifierOutputFile, outputFile)
+		outputFile = jetifierOutputFile
 
 		if !reuseImplementationJarAsHeaderJar {
-			headerInputFile := headerOutputFile
-			headerOutputFile = android.PathForModuleOut(ctx, "jetifier-headers", jarName)
-			TransformJetifier(ctx, headerOutputFile, headerInputFile)
+			jetifierHeaderJar := android.PathForModuleOut(ctx, "jetifier-headers", jarName)
+			TransformJetifier(ctx, jetifierHeaderJar, headerJar)
+			headerJar = jetifierHeaderJar
 		} else {
-			headerOutputFile = outputFile
+			headerJar = outputFile
 		}
 	}
 
+	implementationJarFile := outputFile
+
+	// merge implementation jar with resources if necessary
+	if resourceJarFile != nil {
+		jars := android.Paths{resourceJarFile, outputFile}
+		combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
+		TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
+			false, nil, nil)
+		outputFile = combinedJar
+	}
+
 	// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource.
 	// Also strip the relative path from the header output file so that the reuseImplementationJarAsHeaderJar check
 	// in a module that depends on this module considers them equal.
-	j.combinedHeaderFile = headerOutputFile.WithoutRel()
+	j.combinedHeaderFile = headerJar.WithoutRel()
 	j.combinedImplementationFile = outputFile.WithoutRel()
 
 	j.maybeInstall(ctx, jarName, outputFile)
@@ -2796,7 +2818,8 @@
 		TransitiveLibsHeaderJars:       j.transitiveLibsHeaderJars,
 		TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
 		ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile),
-		ImplementationJars:             android.PathsIfNonNil(j.combinedImplementationFile),
+		ImplementationJars:             android.PathsIfNonNil(implementationJarFile.WithoutRel()),
+		ResourceJars:                   android.PathsIfNonNil(resourceJarFile),
 		AidlIncludeDirs:                j.exportAidlIncludeDirs,
 		StubsLinkType:                  j.stubsLinkType,
 		// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 933fc51..844e974 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -15,6 +15,7 @@
 package java
 
 import (
+	"slices"
 	"strconv"
 	"strings"
 	"testing"
@@ -23,10 +24,11 @@
 )
 
 func TestKotlin(t *testing.T) {
-	ctx, _ := testJava(t, `
+	bp := `
 		java_library {
 			name: "foo",
 			srcs: ["a.java", "b.kt"],
+			static_libs: ["quz"],
 		}
 
 		java_library {
@@ -39,85 +41,156 @@
 		java_library {
 			name: "baz",
 			srcs: ["c.java"],
+			static_libs: ["quz"],
 		}
-		`)
 
-	kotlinStdlib := ctx.ModuleForTests("kotlin-stdlib", "android_common").
-		Output("turbine-combined/kotlin-stdlib.jar").Output
-	kotlinStdlibJdk7 := ctx.ModuleForTests("kotlin-stdlib-jdk7", "android_common").
-		Output("turbine-combined/kotlin-stdlib-jdk7.jar").Output
-	kotlinStdlibJdk8 := ctx.ModuleForTests("kotlin-stdlib-jdk8", "android_common").
-		Output("turbine-combined/kotlin-stdlib-jdk8.jar").Output
-	kotlinAnnotations := ctx.ModuleForTests("kotlin-annotations", "android_common").
-		Output("turbine-combined/kotlin-annotations.jar").Output
+		java_library {
+			name: "quz",
+			srcs: ["d.kt"],
+		}`
 
-	fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
-	fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
-	fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
-	fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
-
-	fooKotlincClasses := fooKotlinc.Output
-	fooKotlincHeaderClasses := fooKotlinc.ImplicitOutput
-
-	if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
-		fooKotlinc.Inputs[1].String() != "b.kt" {
-		t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, fooKotlinc.Inputs)
+	kotlinStdlibTurbineCombinedJars := []string{
+		"out/soong/.intermediates/default/java/kotlin-stdlib/android_common/turbine-combined/kotlin-stdlib.jar",
+		"out/soong/.intermediates/default/java/kotlin-stdlib-jdk7/android_common/turbine-combined/kotlin-stdlib-jdk7.jar",
+		"out/soong/.intermediates/default/java/kotlin-stdlib-jdk8/android_common/turbine-combined/kotlin-stdlib-jdk8.jar",
+		"out/soong/.intermediates/default/java/kotlin-annotations/android_common/turbine-combined/kotlin-annotations.jar",
 	}
 
-	if len(fooJavac.Inputs) != 1 || fooJavac.Inputs[0].String() != "a.java" {
-		t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
+	kotlinStdlibJavacJars := []string{
+		"out/soong/.intermediates/default/java/kotlin-stdlib/android_common/javac/kotlin-stdlib.jar",
+		"out/soong/.intermediates/default/java/kotlin-stdlib-jdk7/android_common/javac/kotlin-stdlib-jdk7.jar",
+		"out/soong/.intermediates/default/java/kotlin-stdlib-jdk8/android_common/javac/kotlin-stdlib-jdk8.jar",
+		"out/soong/.intermediates/default/java/kotlin-annotations/android_common/javac/kotlin-annotations.jar",
 	}
 
-	if !strings.Contains(fooJavac.Args["classpath"], fooKotlincHeaderClasses.String()) {
-		t.Errorf("foo classpath %v does not contain %q",
-			fooJavac.Args["classpath"], fooKotlincHeaderClasses.String())
+	bootclasspathTurbineCombinedJars := []string{
+		"out/soong/.intermediates/default/java/stable.core.platform.api.stubs/android_common/turbine-combined/stable.core.platform.api.stubs.jar",
+		"out/soong/.intermediates/default/java/core-lambda-stubs/android_common/turbine-combined/core-lambda-stubs.jar",
 	}
 
-	if !inList(fooKotlincClasses.String(), fooJar.Inputs.Strings()) {
-		t.Errorf("foo jar inputs %v does not contain %q",
-			fooJar.Inputs.Strings(), fooKotlincClasses.String())
+	frameworkTurbineCombinedJars := []string{
+		"out/soong/.intermediates/default/java/ext/android_common/turbine-combined/ext.jar",
+		"out/soong/.intermediates/default/java/framework/android_common/turbine-combined/framework.jar",
 	}
 
-	if !inList(kotlinStdlib.String(), fooJar.Inputs.Strings()) {
-		t.Errorf("foo jar inputs %v does not contain %v",
-			fooJar.Inputs.Strings(), kotlinStdlib.String())
+	testCases := []struct {
+		name string
+
+		preparer android.FixturePreparer
+
+		fooKotlincInputs        []string
+		fooJavacInputs          []string
+		fooKotlincClasspath     []string
+		fooJavacClasspath       []string
+		fooCombinedInputs       []string
+		fooHeaderCombinedInputs []string
+
+		barKotlincInputs        []string
+		barKotlincClasspath     []string
+		barCombinedInputs       []string
+		barHeaderCombinedInputs []string
+	}{
+		{
+			name:             "normal",
+			preparer:         android.NullFixturePreparer,
+			fooKotlincInputs: []string{"a.java", "b.kt"},
+			fooJavacInputs:   []string{"a.java"},
+			fooKotlincClasspath: slices.Concat(
+				bootclasspathTurbineCombinedJars,
+				frameworkTurbineCombinedJars,
+				[]string{"out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar"},
+				kotlinStdlibTurbineCombinedJars,
+			),
+			fooJavacClasspath: slices.Concat(
+				[]string{"out/soong/.intermediates/foo/android_common/kotlin_headers/foo.jar"},
+				frameworkTurbineCombinedJars,
+				[]string{"out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar"},
+				kotlinStdlibTurbineCombinedJars,
+			),
+			fooCombinedInputs: slices.Concat(
+				[]string{
+					"out/soong/.intermediates/foo/android_common/kotlin/foo.jar",
+					"out/soong/.intermediates/foo/android_common/javac/foo.jar",
+					"out/soong/.intermediates/quz/android_common/combined/quz.jar",
+				},
+				kotlinStdlibJavacJars,
+			),
+			fooHeaderCombinedInputs: slices.Concat(
+				[]string{
+					"out/soong/.intermediates/foo/android_common/turbine/foo.jar",
+					"out/soong/.intermediates/foo/android_common/kotlin_headers/foo.jar",
+					"out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar",
+				},
+				kotlinStdlibTurbineCombinedJars,
+			),
+
+			barKotlincInputs: []string{"b.kt"},
+			barKotlincClasspath: slices.Concat(
+				bootclasspathTurbineCombinedJars,
+				frameworkTurbineCombinedJars,
+				[]string{
+					"out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar",
+					"out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar",
+				},
+				kotlinStdlibTurbineCombinedJars,
+			),
+			barCombinedInputs: slices.Concat(
+				[]string{
+					"out/soong/.intermediates/bar/android_common/kotlin/bar.jar",
+					"out/soong/.intermediates/baz/android_common/combined/baz.jar",
+				},
+				kotlinStdlibJavacJars,
+				[]string{},
+			),
+			barHeaderCombinedInputs: slices.Concat(
+				[]string{
+					"out/soong/.intermediates/bar/android_common/kotlin_headers/bar.jar",
+					"out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar",
+				},
+				kotlinStdlibTurbineCombinedJars,
+			),
+		},
 	}
 
-	if !inList(kotlinStdlibJdk7.String(), fooJar.Inputs.Strings()) {
-		t.Errorf("foo jar inputs %v does not contain %v",
-			fooJar.Inputs.Strings(), kotlinStdlibJdk7.String())
-	}
+	for _, tt := range testCases {
+		t.Run(tt.name, func(t *testing.T) {
+			result := android.GroupFixturePreparers(
+				PrepareForTestWithJavaDefaultModules,
+				tt.preparer,
+			).RunTestWithBp(t, bp)
+			foo := result.ModuleForTests("foo", "android_common")
+			fooKotlinc := foo.Rule("kotlinc")
+			android.AssertPathsRelativeToTopEquals(t, "foo kotlinc inputs", tt.fooKotlincInputs, fooKotlinc.Inputs)
 
-	if !inList(kotlinStdlibJdk8.String(), fooJar.Inputs.Strings()) {
-		t.Errorf("foo jar inputs %v does not contain %v",
-			fooJar.Inputs.Strings(), kotlinStdlibJdk8.String())
-	}
+			fooKotlincClasspath := android.ContentFromFileRuleForTests(t, result.TestContext, foo.Output("kotlinc/classpath.rsp"))
+			android.AssertStringPathsRelativeToTopEquals(t, "foo kotlinc classpath", result.Config, tt.fooKotlincClasspath, strings.Fields(fooKotlincClasspath))
 
-	if !inList(kotlinAnnotations.String(), fooJar.Inputs.Strings()) {
-		t.Errorf("foo jar inputs %v does not contain %v",
-			fooJar.Inputs.Strings(), kotlinAnnotations.String())
-	}
+			fooJavac := foo.Rule("javac")
+			android.AssertPathsRelativeToTopEquals(t, "foo javac inputs", tt.fooJavacInputs, fooJavac.Inputs)
 
-	if !inList(fooKotlincHeaderClasses.String(), fooHeaderJar.Inputs.Strings()) {
-		t.Errorf("foo header jar inputs %v does not contain %q",
-			fooHeaderJar.Inputs.Strings(), fooKotlincHeaderClasses.String())
-	}
+			fooJavacClasspath := fooJavac.Args["classpath"]
+			android.AssertStringPathsRelativeToTopEquals(t, "foo javac classpath", result.Config, tt.fooJavacClasspath,
+				strings.Split(strings.TrimPrefix(fooJavacClasspath, "-classpath "), ":"))
 
-	bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
-	barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
+			fooCombinedJar := foo.Output("combined/foo.jar")
+			android.AssertPathsRelativeToTopEquals(t, "foo combined inputs", tt.fooCombinedInputs, fooCombinedJar.Inputs)
 
-	if len(barKotlinc.Inputs) != 1 || barKotlinc.Inputs[0].String() != "b.kt" {
-		t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, barKotlinc.Inputs)
-	}
+			fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar")
+			android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs)
 
-	if !inList(fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
-		t.Errorf(`expected %q in bar implicits %v`,
-			fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
-	}
+			bar := result.ModuleForTests("bar", "android_common")
+			barKotlinc := bar.Rule("kotlinc")
+			android.AssertPathsRelativeToTopEquals(t, "bar kotlinc inputs", tt.barKotlincInputs, barKotlinc.Inputs)
 
-	if !inList(bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
-		t.Errorf(`expected %q in bar implicits %v`,
-			bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
+			barKotlincClasspath := android.ContentFromFileRuleForTests(t, result.TestContext, bar.Output("kotlinc/classpath.rsp"))
+			android.AssertStringPathsRelativeToTopEquals(t, "bar kotlinc classpath", result.Config, tt.barKotlincClasspath, strings.Fields(barKotlincClasspath))
+
+			barCombinedJar := bar.Output("combined/bar.jar")
+			android.AssertPathsRelativeToTopEquals(t, "bar combined inputs", tt.barCombinedInputs, barCombinedJar.Inputs)
+
+			barCombinedHeaderJar := bar.Output("turbine-combined/bar.jar")
+			android.AssertPathsRelativeToTopEquals(t, "bar header combined inputs", tt.barHeaderCombinedInputs, barCombinedHeaderJar.Inputs)
+		})
 	}
 }
 
diff --git a/java/ravenwood.go b/java/ravenwood.go
index a52f405..bb136cf 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -143,6 +143,9 @@
 		HostTemplate:           "${RavenwoodTestConfigTemplate}",
 	})
 
+	// Always enable Ravenizer for ravenwood tests.
+	r.Library.ravenizer.enabled = true
+
 	r.Library.GenerateAndroidBuildActions(ctx)
 
 	// Start by depending on all files installed by dependencies
@@ -152,7 +155,8 @@
 	var runtimeJniModuleNames map[string]bool
 
 	if utils := ctx.GetDirectDepsWithTag(ravenwoodUtilsTag)[0]; utils != nil {
-		for _, installFile := range utils.FilesToInstall() {
+		for _, installFile := range android.OtherModuleProviderOrDefault(
+			ctx, utils, android.InstallFilesProvider).InstallFiles {
 			installDeps = append(installDeps, installFile)
 		}
 		jniDeps, ok := android.OtherModuleProvider(ctx, utils, ravenwoodLibgroupJniDepProvider)
@@ -162,7 +166,8 @@
 	}
 
 	if runtime := ctx.GetDirectDepsWithTag(ravenwoodRuntimeTag)[0]; runtime != nil {
-		for _, installFile := range runtime.FilesToInstall() {
+		for _, installFile := range android.OtherModuleProviderOrDefault(
+			ctx, runtime, android.InstallFilesProvider).InstallFiles {
 			installDeps = append(installDeps, installFile)
 		}
 		jniDeps, ok := android.OtherModuleProvider(ctx, runtime, ravenwoodLibgroupJniDepProvider)
@@ -191,7 +196,8 @@
 
 	resApkInstallPath := installPath.Join(ctx, "ravenwood-res-apks")
 	if resApk := ctx.GetDirectDepsWithTag(ravenwoodTestResourceApkTag); len(resApk) > 0 {
-		for _, installFile := range resApk[0].FilesToInstall() {
+		for _, installFile := range android.OtherModuleProviderOrDefault(
+			ctx, resApk[0], android.InstallFilesProvider).InstallFiles {
 			installResApk := ctx.InstallFile(resApkInstallPath, "ravenwood-res.apk", installFile)
 			installDeps = append(installDeps, installResApk)
 		}
diff --git a/java/testing.go b/java/testing.go
index e1bf537..0e85022 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -542,6 +542,16 @@
 			},
 			compile_dex: true,
 		}
+		java_library {
+			name: "framework-minus-apex",
+			srcs: ["a.java"],
+			sdk_version: "none",
+			system_modules: "stable-core-platform-api-stubs-system-modules",
+			aidl: {
+				export_include_dirs: ["framework/aidl"],
+			},
+			compile_dex: true,
+		}
 
 		android_app {
 			name: "framework-res",
diff --git a/kernel/prebuilt_kernel_modules_test.go b/kernel/prebuilt_kernel_modules_test.go
index 90b9886..7b81869 100644
--- a/kernel/prebuilt_kernel_modules_test.go
+++ b/kernel/prebuilt_kernel_modules_test.go
@@ -49,7 +49,8 @@
 	}
 
 	var actual []string
-	for _, ps := range ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().PackagingSpecs() {
+	for _, ps := range android.OtherModuleProviderOrDefault(
+		ctx, ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module(), android.InstallFilesProvider).PackagingSpecs {
 		actual = append(actual, ps.RelPathInPackage())
 	}
 	actual = android.SortedUniqueStrings(actual)
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index 87c0814..533ec62 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -105,7 +105,8 @@
 	var provideLibs []string
 	for _, m := range provideModules {
 		if c, ok := m.(*cc.Module); ok && (cc.IsStubTarget(c) || c.HasLlndkStubs()) {
-			for _, ps := range c.PackagingSpecs() {
+			for _, ps := range android.OtherModuleProviderOrDefault(
+				ctx, c, android.InstallFilesProvider).PackagingSpecs {
 				provideLibs = append(provideLibs, ps.FileName())
 			}
 		}
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 78ab771..2e408b7 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -72,6 +72,7 @@
 	"add_soong_config_namespace":           &simpleCallParser{name: baseName + ".soong_config_namespace", returnType: starlarkTypeVoid, addGlobals: true},
 	"add_soong_config_var_value":           &simpleCallParser{name: baseName + ".soong_config_set", returnType: starlarkTypeVoid, addGlobals: true},
 	soongConfigAssign:                      &simpleCallParser{name: baseName + ".soong_config_set", returnType: starlarkTypeVoid, addGlobals: true},
+	"soong_config_set_bool":                &simpleCallParser{name: baseName + ".soong_config_set_bool", returnType: starlarkTypeVoid, addGlobals: true},
 	soongConfigAppend:                      &simpleCallParser{name: baseName + ".soong_config_append", returnType: starlarkTypeVoid, addGlobals: true},
 	"soong_config_get":                     &simpleCallParser{name: baseName + ".soong_config_get", returnType: starlarkTypeString, addGlobals: true},
 	"add-to-product-copy-files-if-exists":  &simpleCallParser{name: baseName + ".copy_if_exists", returnType: starlarkTypeList},
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 0c4d213..c295c40 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -853,6 +853,7 @@
 $(call add_soong_config_namespace,snsconfig)
 $(call add_soong_config_var_value,snsconfig,imagetype,odm_image)
 $(call soong_config_set, snsconfig, foo, foo_value)
+$(call soong_config_set_bool, snsconfig, bar, true)
 $(call soong_config_append, snsconfig, bar, bar_value)
 PRODUCT_COPY_FILES := $(call copy-files,$(wildcard foo*.mk),etc)
 PRODUCT_COPY_FILES := $(call product-copy-files-by-pattern,from/%,to/%,a b c)
@@ -880,6 +881,7 @@
   rblf.soong_config_namespace(g, "snsconfig")
   rblf.soong_config_set(g, "snsconfig", "imagetype", "odm_image")
   rblf.soong_config_set(g, "snsconfig", "foo", "foo_value")
+  rblf.soong_config_set_bool(g, "snsconfig", "bar", "true")
   rblf.soong_config_append(g, "snsconfig", "bar", "bar_value")
   cfg["PRODUCT_COPY_FILES"] = rblf.copy_files(rblf.expand_wildcard("foo*.mk"), "etc")
   cfg["PRODUCT_COPY_FILES"] = rblf.product_copy_files_by_pattern("from/%", "to/%", "a b c")
diff --git a/rust/bindgen.go b/rust/bindgen.go
index a81024a..31aa137 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -393,8 +393,8 @@
 		deps.StaticLibs = append(deps.StaticLibs, String(b.Properties.Static_inline_library))
 	}
 
-	deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
-	deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs...)
-	deps.HeaderLibs = append(deps.HeaderLibs, b.ClangProperties.Header_libs...)
+	deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs.GetOrDefault(ctx, nil)...)
+	deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs.GetOrDefault(ctx, nil)...)
+	deps.HeaderLibs = append(deps.HeaderLibs, b.ClangProperties.Header_libs.GetOrDefault(ctx, nil)...)
 	return deps
 }
diff --git a/sdk/update.go b/sdk/update.go
index 198c8d4..a4b1967 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -1989,6 +1989,14 @@
 	return m.builder.targetBuildRelease.EarlierThan(buildReleaseT)
 }
 
+func (m *memberContext) Config() android.Config {
+	return m.sdkMemberContext.Config()
+}
+
+func (m *memberContext) OtherModulePropertyErrorf(module android.Module, property string, fmt string, args ...interface{}) {
+	m.sdkMemberContext.OtherModulePropertyErrorf(module, property, fmt, args)
+}
+
 var _ android.SdkMemberContext = (*memberContext)(nil)
 
 func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule *bpModule) {
diff --git a/ui/build/config.go b/ui/build/config.go
index b8fcb6b..dfe0dfe 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -1041,7 +1041,7 @@
 
 func (c *configImpl) UsedEnvFile(tag string) string {
 	if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
-		return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+"."+tag)
+		return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+c.CoverageSuffix()+"."+tag)
 	}
 	return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
 }
@@ -1149,6 +1149,13 @@
 	return "", fmt.Errorf("TARGET_PRODUCT is not defined")
 }
 
+func (c *configImpl) CoverageSuffix() string {
+	if v := c.environ.IsEnvTrue("EMMA_INSTRUMENT"); v {
+		return ".coverage"
+	}
+	return ""
+}
+
 func (c *configImpl) TargetDevice() string {
 	return c.targetDevice
 }
@@ -1520,7 +1527,7 @@
 	if err != nil {
 		return filepath.Join(c.SoongOutDir(), "soong.variables")
 	} else {
-		return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".variables")
+		return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".variables")
 	}
 }
 
@@ -1529,7 +1536,7 @@
 	if err != nil {
 		return filepath.Join(c.SoongOutDir(), "soong.extra.variables")
 	} else {
-		return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".extra.variables")
+		return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".extra.variables")
 	}
 }
 
@@ -1538,7 +1545,7 @@
 	if err != nil {
 		return filepath.Join(c.SoongOutDir(), "build.ninja")
 	} else {
-		return filepath.Join(c.SoongOutDir(), "build."+targetProduct+".ninja")
+		return filepath.Join(c.SoongOutDir(), "build."+targetProduct+c.CoverageSuffix()+".ninja")
 	}
 }
 
@@ -1550,11 +1557,11 @@
 }
 
 func (c *configImpl) SoongAndroidMk() string {
-	return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
+	return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
 }
 
 func (c *configImpl) SoongMakeVarsMk() string {
-	return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
+	return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
 }
 
 func (c *configImpl) SoongBuildMetrics() string {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index a0efd2c..5743ff7 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -41,7 +41,7 @@
 // arguments.
 func genKatiSuffix(ctx Context, config Config) {
 	// Construct the base suffix.
-	katiSuffix := "-" + config.TargetProduct()
+	katiSuffix := "-" + config.TargetProduct() + config.CoverageSuffix()
 
 	// Append kati arguments to the suffix.
 	if args := config.KatiArgs(); len(args) > 0 {
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index b5e74b4..8ca62d3 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -229,6 +229,7 @@
 			"BUILD_BROKEN_INCORRECT_PARTITION_IMAGES",
 			"SOONG_USE_N2",
 			"RUST_BACKTRACE",
+			"RUST_LOG",
 		}, config.BuildBrokenNinjaUsesEnvVars()...)...)
 	}