Merge "Build zip of all soong-built images" into main
diff --git a/android/Android.bp b/android/Android.bp
index d27a8fa..75027b1 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -141,6 +141,7 @@
         "license_kind_test.go",
         "license_test.go",
         "licenses_test.go",
+        "makevars_test.go",
         "module_test.go",
         "mutator_test.go",
         "namespace_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 2153c27..9c72606 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -719,22 +719,26 @@
 
 type androidMkSingleton struct{}
 
-func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
-	var androidMkModulesList []blueprint.Module
+func allModulesSorted(ctx SingletonContext) []blueprint.Module {
+	var allModules []blueprint.Module
 
 	ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
-		androidMkModulesList = append(androidMkModulesList, module)
+		allModules = append(allModules, module)
 	})
 
 	// Sort the module list by the module names to eliminate random churns, which may erroneously
 	// invoke additional build processes.
-	sort.SliceStable(androidMkModulesList, func(i, j int) bool {
-		return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
+	sort.SliceStable(allModules, func(i, j int) bool {
+		return ctx.ModuleName(allModules[i]) < ctx.ModuleName(allModules[j])
 	})
 
-	// If running in soong-only mode, do a different, more limited version of this singleton
+	return allModules
+}
+
+func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
+	// If running in soong-only mode, more limited version of this singleton is run as
+	// soong only androidmk singleton
 	if !ctx.Config().KatiEnabled() {
-		c.soongOnlyBuildActions(ctx, androidMkModulesList)
 		return
 	}
 
@@ -745,7 +749,7 @@
 
 	moduleInfoJSON := PathForOutput(ctx, "module-info"+String(ctx.Config().productVariables.Make_suffix)+".json")
 
-	err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, androidMkModulesList)
+	err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, allModulesSorted(ctx))
 	if err != nil {
 		ctx.Errorf(err.Error())
 	}
@@ -756,10 +760,24 @@
 	})
 }
 
+type soongOnlyAndroidMkSingleton struct {
+	Singleton
+}
+
+func soongOnlyAndroidMkSingletonFactory() Singleton {
+	return &soongOnlyAndroidMkSingleton{}
+}
+
+func (so *soongOnlyAndroidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
+	if !ctx.Config().KatiEnabled() {
+		so.soongOnlyBuildActions(ctx, allModulesSorted(ctx))
+	}
+}
+
 // In soong-only mode, we don't do most of the androidmk stuff. But disted files are still largely
 // defined through the androidmk mechanisms, so this function is an alternate implementation of
 // the androidmk singleton that just focuses on getting the dist contributions
-func (c *androidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []blueprint.Module) {
+func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []blueprint.Module) {
 	allDistContributions, moduleInfoJSONs := getSoongOnlyDataFromMods(ctx, mods)
 
 	for _, provider := range makeVarsInitProviders {
@@ -768,7 +786,7 @@
 			pctx:             provider.pctx,
 		}
 		provider.call(mctx)
-		if contribution := getMakeVarsDistContributions(mctx); contribution != nil {
+		if contribution := distsToDistContributions(mctx.dists); contribution != nil {
 			allDistContributions = append(allDistContributions, *contribution)
 		}
 	}
@@ -851,24 +869,24 @@
 	}
 }
 
-func getMakeVarsDistContributions(mctx *makeVarsContext) *distContributions {
-	if len(mctx.dists) == 0 {
+func distsToDistContributions(dists []dist) *distContributions {
+	if len(dists) == 0 {
 		return nil
 	}
 
 	copyGoals := []*copiesForGoals{}
-	for _, dist := range mctx.dists {
+	for _, dist := range dists {
 		for _, goal := range dist.goals {
-			copy := &copiesForGoals{}
-			copy.goals = goal
-			copy.copies = dist.paths
-			copyGoals = append(copyGoals, copy)
+			copyGoals = append(copyGoals, &copiesForGoals{
+				goals:  goal,
+				copies: dist.paths,
+			})
 		}
 	}
 
-	contribution := &distContributions{}
-	contribution.copiesForGoals = copyGoals
-	return contribution
+	return &distContributions{
+		copiesForGoals: copyGoals,
+	}
 }
 
 // getSoongOnlyDataFromMods gathers data from the given modules needed in soong-only builds.
@@ -877,6 +895,12 @@
 	var allDistContributions []distContributions
 	var moduleInfoJSONs []*ModuleInfoJSON
 	for _, mod := range mods {
+		if distInfo, ok := OtherModuleProvider(ctx, mod, DistProvider); ok {
+			if contribution := distsToDistContributions(distInfo.Dists); contribution != nil {
+				allDistContributions = append(allDistContributions, *contribution)
+			}
+		}
+
 		if amod, ok := mod.(Module); ok && shouldSkipAndroidMkProcessing(ctx, amod.base()) {
 			continue
 		}
@@ -946,7 +970,7 @@
 					continue
 				}
 				x.MakeVars(mctx)
-				if contribution := getMakeVarsDistContributions(mctx); contribution != nil {
+				if contribution := distsToDistContributions(mctx.dists); contribution != nil {
 					allDistContributions = append(allDistContributions, *contribution)
 				}
 			}
@@ -957,7 +981,7 @@
 					pctx:             pctx,
 				}
 				x.MakeVars(mctx)
-				if contribution := getMakeVarsDistContributions(mctx); contribution != nil {
+				if contribution := distsToDistContributions(mctx.dists); contribution != nil {
 					allDistContributions = append(allDistContributions, *contribution)
 				}
 			}
diff --git a/android/apex.go b/android/apex.go
index c2f73a9..a5ccd52 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -616,25 +616,26 @@
 		apexInfos = allApexInfos.ApexInfos
 	}
 
-	// Shortcut
-	if len(apexInfos) == 0 {
-		return
-	}
-
-	// Do some validity checks.
-	// TODO(jiyong): is this the right place?
-	base.checkApexAvailableProperty(ctx)
-
-	if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
-		apexInfos, _ = mergeApexVariations(apexInfos)
-	}
-
 	if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
 		// Do not install the module for platform, but still allow it to output
 		// uninstallable AndroidMk entries in certain cases when they have side
 		// effects.  TODO(jiyong): move this routine to somewhere else
 		module.MakeUninstallable()
 	}
+
+	// Do some validity checks.
+	// TODO(jiyong): is this the right place?
+	base.checkApexAvailableProperty(ctx)
+
+	// Shortcut
+	if len(apexInfos) == 0 {
+		return
+	}
+
+	if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
+		apexInfos, _ = mergeApexVariations(apexInfos)
+	}
+
 	if !platformVariation {
 		var thisApexInfo ApexInfo
 
diff --git a/android/makevars.go b/android/makevars.go
index c8eb5e4..3a60bbb 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -185,6 +185,7 @@
 type makeVarsSingleton struct {
 	varsForTesting     []makeVarsVariable
 	installsForTesting []byte
+	lateForTesting     []byte
 }
 
 type makeVarsProvider struct {
@@ -285,6 +286,10 @@
 			katiVintfManifestInstalls = append(katiVintfManifestInstalls, info.KatiVintfInstalls...)
 			katiSymlinks = append(katiSymlinks, info.KatiSymlinks...)
 		}
+
+		if distInfo, ok := OtherModuleProvider(ctx, m, DistProvider); ok {
+			dists = append(dists, distInfo.Dists...)
+		}
 	})
 
 	compareKatiInstalls := func(a, b katiInstall) int {
@@ -354,6 +359,7 @@
 	if ctx.Config().RunningInsideUnitTest() {
 		s.varsForTesting = vars
 		s.installsForTesting = installsBytes
+		s.lateForTesting = lateOutBytes
 	}
 }
 
diff --git a/android/makevars_test.go b/android/makevars_test.go
new file mode 100644
index 0000000..5e4499f
--- /dev/null
+++ b/android/makevars_test.go
@@ -0,0 +1,42 @@
+package android
+
+import (
+	"regexp"
+	"testing"
+)
+
+func TestDistFilesInGenerateAndroidBuildActions(t *testing.T) {
+	result := GroupFixturePreparers(
+		FixtureRegisterWithContext(func(ctx RegistrationContext) {
+			ctx.RegisterModuleType("my_module_type", newDistFileModule)
+		}),
+		FixtureModifyConfig(SetKatiEnabledForTests),
+		PrepareForTestWithMakevars,
+	).RunTestWithBp(t, `
+	my_module_type {
+		name: "foo",
+	}
+	`)
+
+	lateContents := string(result.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).lateForTesting)
+	matched, err := regexp.MatchString(`call dist-for-goals,my_goal,.*/my_file.txt:my_file.txt\)`, lateContents)
+	if err != nil || !matched {
+		t.Fatalf("Expected a dist, but got: %s", lateContents)
+	}
+}
+
+type distFileModule struct {
+	ModuleBase
+}
+
+func newDistFileModule() Module {
+	m := &distFileModule{}
+	InitAndroidModule(m)
+	return m
+}
+
+func (m *distFileModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	out := PathForModuleOut(ctx, "my_file.txt")
+	WriteFileRule(ctx, out, "Hello, world!")
+	ctx.DistForGoal("my_goal", out)
+}
diff --git a/android/module.go b/android/module.go
index 39a1654..80275a3 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1925,6 +1925,12 @@
 
 var HostToolProviderInfoProvider = blueprint.NewProvider[HostToolProviderInfo]()
 
+type DistInfo struct {
+	Dists []dist
+}
+
+var DistProvider = blueprint.NewProvider[DistInfo]()
+
 type SourceFileGenerator interface {
 	GeneratedSourceFiles() Paths
 	GeneratedHeaderDirs() Paths
@@ -2222,6 +2228,13 @@
 			Phonies: ctx.phonies,
 		})
 	}
+
+	if len(ctx.dists) > 0 {
+		SetProvider(ctx, DistProvider, DistInfo{
+			Dists: ctx.dists,
+		})
+	}
+
 	buildComplianceMetadataProvider(ctx, m)
 
 	commonData := CommonModuleInfo{
diff --git a/android/module_context.go b/android/module_context.go
index d3c5370..1851e7c 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -255,6 +255,24 @@
 	setContainersInfo(info ContainersInfo)
 
 	setAconfigPaths(paths Paths)
+
+	// DistForGoals creates a rule to copy one or more Paths to the artifacts
+	// directory on the build server when any of the specified goals are built.
+	DistForGoal(goal string, paths ...Path)
+
+	// DistForGoalWithFilename creates a rule to copy a Path to the artifacts
+	// directory on the build server with the given filename when the specified
+	// goal is built.
+	DistForGoalWithFilename(goal string, path Path, filename string)
+
+	// DistForGoals creates a rule to copy one or more Paths to the artifacts
+	// directory on the build server when any of the specified goals are built.
+	DistForGoals(goals []string, paths ...Path)
+
+	// DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
+	// directory on the build server with the given filename when any of the
+	// specified goals are built.
+	DistForGoalsWithFilename(goals []string, path Path, filename string)
 }
 
 type moduleContext struct {
@@ -312,6 +330,8 @@
 	// complianceMetadataInfo is for different module types to dump metadata.
 	// See android.ModuleContext interface.
 	complianceMetadataInfo *ComplianceMetadataInfo
+
+	dists []dist
 }
 
 var _ ModuleContext = &moduleContext{}
@@ -959,3 +979,32 @@
 func (m *moduleContext) setContainersInfo(info ContainersInfo) {
 	m.containersInfo = info
 }
+
+func (c *moduleContext) DistForGoal(goal string, paths ...Path) {
+	c.DistForGoals([]string{goal}, paths...)
+}
+
+func (c *moduleContext) DistForGoalWithFilename(goal string, path Path, filename string) {
+	c.DistForGoalsWithFilename([]string{goal}, path, filename)
+}
+
+func (c *moduleContext) DistForGoals(goals []string, paths ...Path) {
+	var copies distCopies
+	for _, path := range paths {
+		copies = append(copies, distCopy{
+			from: path,
+			dest: path.Base(),
+		})
+	}
+	c.dists = append(c.dists, dist{
+		goals: slices.Clone(goals),
+		paths: copies,
+	})
+}
+
+func (c *moduleContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
+	c.dists = append(c.dists, dist{
+		goals: slices.Clone(goals),
+		paths: distCopies{{from: path, dest: filename}},
+	})
+}
diff --git a/android/register.go b/android/register.go
index 8d2f19e..332ec27 100644
--- a/android/register.go
+++ b/android/register.go
@@ -192,6 +192,11 @@
 func collateGloballyRegisteredSingletons() sortableComponents {
 	allSingletons := append(sortableComponents(nil), singletons...)
 	allSingletons = append(allSingletons,
+		// Soong only androidmk is registered later than other singletons in order to collect
+		// dist contributions from other singletons. This singleton is registered just before
+		// phony so that its phony rules can be collected by the phony singleton.
+		singleton{parallel: false, name: "soongonlyandroidmk", factory: soongOnlyAndroidMkSingletonFactory},
+
 		// Register phony just before makevars so it can write out its phony rules as Make rules
 		singleton{parallel: false, name: "phony", factory: phonySingletonFactory},
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 98af7b6..2be4e48 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2689,7 +2689,7 @@
 	cppOnly := []string{"-fPIC", "${config.CommonGlobalCppflags}", "${config.DeviceGlobalCppflags}", "${config.ArmCppflags}"}
 
 	cflags := []string{"-Werror", "-std=candcpp"}
-	cstd := []string{"-std=gnu17", "-std=conly"}
+	cstd := []string{"-std=gnu23", "-std=conly"}
 	cppstd := []string{"-std=gnu++20", "-std=cpp", "-fno-rtti"}
 
 	lastNDKFlags := []string{
diff --git a/cc/config/global.go b/cc/config/global.go
index 7bea124..5011acd 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -375,7 +375,7 @@
 		"-w",
 	}
 
-	CStdVersion               = "gnu17"
+	CStdVersion               = "gnu23"
 	CppStdVersion             = "gnu++20"
 	ExperimentalCStdVersion   = "gnu2x"
 	ExperimentalCppStdVersion = "gnu++2b"
diff --git a/cc/testing.go b/cc/testing.go
index 14a6b7a..c9d362d 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -193,7 +193,7 @@
 			},
 			apex_available: [
 				"//apex_available:platform",
-				"myapex"
+				"//apex_available:anyapex",
 			],
 			llndk: {
 				symbol_file: "libm.map.txt",
@@ -253,7 +253,7 @@
 			},
 			apex_available: [
 				"//apex_available:platform",
-				"myapex"
+				"//apex_available:anyapex",
 			],
 			llndk: {
 				symbol_file: "libdl.map.txt",
diff --git a/cmd/javac_wrapper/javac_wrapper.go b/cmd/javac_wrapper/javac_wrapper.go
index 4679906..49bcedf 100644
--- a/cmd/javac_wrapper/javac_wrapper.go
+++ b/cmd/javac_wrapper/javac_wrapper.go
@@ -200,6 +200,9 @@
 
 var warningFilters = []*regexp.Regexp{
 	regexp.MustCompile(`bootstrap class path not set in conjunction with -source`),
+	regexp.MustCompile(`source value 8 is obsolete and will be removed in a future release`),
+	regexp.MustCompile(`target value 8 is obsolete and will be removed in a future release`),
+	regexp.MustCompile(`To suppress warnings about obsolete options, use -Xlint:-options.`),
 }
 
 var filters = []*regexp.Regexp{
diff --git a/cmd/javac_wrapper/javac_wrapper_test.go b/cmd/javac_wrapper/javac_wrapper_test.go
index ad23001..5e26786 100644
--- a/cmd/javac_wrapper/javac_wrapper_test.go
+++ b/cmd/javac_wrapper/javac_wrapper_test.go
@@ -90,6 +90,15 @@
 `,
 		out: "\n\x1b[1m\x1b[35mwarning:\x1b[0m\x1b[1m foo\x1b[0m\n1 warning\n",
 	},
+	{
+		in: `
+warning: [options] source value 8 is obsolete and will be removed in a future release
+warning: [options] target value 8 is obsolete and will be removed in a future release
+warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
+3 warnings
+`,
+		out: "\n",
+	},
 }
 
 func TestJavacColorize(t *testing.T) {
diff --git a/python/python.go b/python/python.go
index 10c11ad..f8f4165 100644
--- a/python/python.go
+++ b/python/python.go
@@ -400,7 +400,8 @@
 
 	// generate the zipfile of all source and data files
 	p.srcsZip = p.createSrcsZip(ctx, pkgPath)
-	p.precompiledSrcsZip = p.precompileSrcs(ctx)
+	// TODO(b/388344853): precompilation temporarily disabled for python3.13 upgrade
+	p.precompiledSrcsZip = p.srcsZip //p.precompileSrcs(ctx)
 
 	android.SetProvider(ctx, PythonLibraryInfoProvider, PythonLibraryInfo{
 		SrcsPathMappings:   p.getSrcsPathMappings(),
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 8accd03..2f84168 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -398,7 +398,7 @@
 		//
 		// This is necessary to avoid a circular dependency between the source variant and the
 		// dependent cc module.
-		deps.StaticLibs = append(deps.StaticLibs, String(b.Properties.Static_inline_library))
+		deps.WholeStaticLibs = append(deps.WholeStaticLibs, String(b.Properties.Static_inline_library))
 	}
 
 	deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs.GetOrDefault(ctx, nil)...)
diff --git a/rust/library.go b/rust/library.go
index 94f5730..14d908c 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -771,7 +771,7 @@
 	cc.AddStubDependencyProviders(ctx)
 
 	// Set our flagexporter provider to export relevant Rust flags
-	library.flagExporter.setProvider(ctx)
+	library.flagExporter.setRustProvider(ctx)
 
 	return ret
 }
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index e35e510..9bd5111 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -158,7 +158,7 @@
 
 func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
 	prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
-	prebuilt.flagExporter.setProvider(ctx)
+	prebuilt.flagExporter.setRustProvider(ctx)
 	srcPath := prebuiltPath(ctx, prebuilt)
 	prebuilt.baseCompiler.unstrippedOutputFile = srcPath
 	return buildOutput{outputFile: srcPath}
@@ -211,7 +211,7 @@
 
 func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
 	prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
-	prebuilt.flagExporter.setProvider(ctx)
+	prebuilt.flagExporter.setRustProvider(ctx)
 	srcPath := prebuiltPath(ctx, prebuilt)
 	prebuilt.baseCompiler.unstrippedOutputFile = srcPath
 	return buildOutput{outputFile: srcPath}
diff --git a/rust/rust.go b/rust/rust.go
index 90e5277..dfd39f7 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -573,8 +573,8 @@
 	flagExporter.wholeStaticLibObjects = android.FirstUniqueStrings(append(flagExporter.wholeStaticLibObjects, flags...))
 }
 
-func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
-	android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{
+func (flagExporter *flagExporter) setRustProvider(ctx ModuleContext) {
+	android.SetProvider(ctx, RustFlagExporterInfoProvider, RustFlagExporterInfo{
 		LinkDirs:              flagExporter.linkDirs,
 		RustLibObjects:        flagExporter.rustLibPaths,
 		StaticLibObjects:      flagExporter.staticLibObjects,
@@ -589,7 +589,7 @@
 	return &flagExporter{}
 }
 
-type FlagExporterInfo struct {
+type RustFlagExporterInfo struct {
 	Flags                 []string
 	LinkDirs              []string
 	RustLibObjects        []string
@@ -598,7 +598,7 @@
 	SharedLibPaths        []string
 }
 
-var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]()
+var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]()
 
 func (mod *Module) isCoverageVariant() bool {
 	return mod.coverage.Properties.IsCoverageVariant
@@ -1574,7 +1574,7 @@
 				directSrcProvidersDeps = append(directSrcProvidersDeps, &dep)
 			}
 
-			exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
+			exportedInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
 
 			//Append the dependencies exported objects, except for proc-macros which target a different arch/OS
 			if depTag != procMacroDepTag {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 858c4db..4390f55 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -432,7 +432,7 @@
 	}
 }
 
-func TestRustRlibs(t *testing.T) {
+func TestRustFFIRlibs(t *testing.T) {
 	ctx := testRust(t, `
 		rust_ffi_static {
 			name: "libbar",
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 36f0010..ad315bf 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -759,6 +759,13 @@
 			bootclasspath_fragments: ["mybootclasspathfragment"],
 		}
 
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			min_sdk_version: "1",
+			bootclasspath_fragments: ["mybootclasspathfragment"],
+		}
+
 		bootclasspath_fragment {
 			name: "mybootclasspathfragment",
 			image_name: "art",
@@ -801,7 +808,7 @@
 		java_import {
 			name: "mybootlib",
 			visibility: ["//visibility:public"],
-			apex_available: ["com.android.art"],
+			apex_available: ["myapex"],
 			jars: ["java/mybootlib.jar"],
 		}
 	`),
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 939477f..5bac67d 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -805,13 +805,19 @@
 			native_shared_libs: ["mynativelib"],
 		}
 
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			min_sdk_version: "1",
+		}
+
 		cc_library_shared {
 			name: "mynativelib",
 			srcs: [
 				"Test.cpp",
 				"aidl/foo/bar/Test.aidl",
 			],
-			apex_available: ["apex1", "apex2"],
+			apex_available: ["myapex"],
 			export_include_dirs: ["myinclude"],
 			aidl: {
 				export_aidl_headers: true,
@@ -821,6 +827,18 @@
 	`)
 
 	CheckSnapshot(t, result, "mysdk", "",
+		snapshotTestPreparer(checkSnapshotWithoutSource,
+			android.FixtureMergeMockFs(android.MockFS{
+				"myapex/Android.bp": []byte(`
+				apex {
+					name: "myapex",
+					key: "myapex.key",
+					min_sdk_version: "1",
+				}
+				`),
+				"myapex/apex_manifest.json": nil,
+			}),
+		),
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -833,10 +851,7 @@
     name: "mynativelib",
     prefer: false,
     visibility: ["//visibility:public"],
-    apex_available: [
-        "apex1",
-        "apex2",
-    ],
+    apex_available: ["myapex"],
     stl: "none",
     compile_multilib: "both",
     export_include_dirs: ["include/myinclude"],
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 60e5b95..7ebdcd4 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -87,6 +87,18 @@
 
 	CheckSnapshot(t, result, "mysdk", "",
 		checkAndroidBpContents(expectedSdkSnapshot),
+		snapshotTestPreparer(checkSnapshotWithoutSource,
+			android.FixtureMergeMockFs(android.MockFS{
+				"myapex/Android.bp": []byte(`
+				apex {
+					name: "myapex",
+					key: "myapex.key",
+					min_sdk_version: "1",
+				}
+				`),
+				"myapex/apex_manifest.json": nil,
+			}),
+		),
 	)
 }
 
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index f368ce9..4ea8a0b 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -179,6 +179,12 @@
 			autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
 		} else {
 			if ctx.Device() {
+				if Bool(options.StandaloneTest) {
+					options.TestRunnerOptions = append(options.TestRunnerOptions, Option{
+						Name:  "ld-library-path",
+						Value: "{TEST_INSTALL_BASE}/" + name + "/" + ctx.Arch().ArchType.String() + "/standalone-libs",
+					})
+				}
 				autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
 			} else {
 				if Bool(options.UnitTest) {