Merge changes from topic "llndk_cc_library"

* changes:
  Don't rewrite LLNDK dependencies with .llndk suffix
  Don't strip stub libraries
diff --git a/android/namespace.go b/android/namespace.go
index 9d7e8ac..d137636 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -232,13 +232,14 @@
 
 }
 
-func (r *NameResolver) getNamespacesToSearchForModule(sourceNamespace *Namespace) (searchOrder []*Namespace) {
-	if sourceNamespace.visibleNamespaces == nil {
+func (r *NameResolver) getNamespacesToSearchForModule(sourceNamespace blueprint.Namespace) (searchOrder []*Namespace) {
+	ns, ok := sourceNamespace.(*Namespace)
+	if !ok || ns.visibleNamespaces == nil {
 		// When handling dependencies before namespaceMutator, assume they are non-Soong Blueprint modules and give
 		// access to all namespaces.
 		return r.sortedNamespaces.sortedItems()
 	}
-	return sourceNamespace.visibleNamespaces
+	return ns.visibleNamespaces
 }
 
 func (r *NameResolver) ModuleFromName(name string, namespace blueprint.Namespace) (group blueprint.ModuleGroup, found bool) {
@@ -252,7 +253,7 @@
 		container := namespace.moduleContainer
 		return container.ModuleFromName(moduleName, nil)
 	}
-	for _, candidate := range r.getNamespacesToSearchForModule(namespace.(*Namespace)) {
+	for _, candidate := range r.getNamespacesToSearchForModule(namespace) {
 		group, found = candidate.moduleContainer.ModuleFromName(name, nil)
 		if found {
 			return group, true
diff --git a/android/neverallow.go b/android/neverallow.go
index 8b8e1ac..031b3f4 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -51,7 +51,6 @@
 func init() {
 	AddNeverAllowRules(createIncludeDirsRules()...)
 	AddNeverAllowRules(createTrebleRules()...)
-	AddNeverAllowRules(createLibcoreRules()...)
 	AddNeverAllowRules(createMediaRules()...)
 	AddNeverAllowRules(createJavaDeviceForHostRules()...)
 	AddNeverAllowRules(createCcSdkVariantRules()...)
@@ -133,38 +132,6 @@
 	}
 }
 
-func createLibcoreRules() []Rule {
-	var coreLibraryProjects = []string{
-		"libcore",
-		"external/apache-harmony",
-		"external/apache-xml",
-		"external/bouncycastle",
-		"external/conscrypt",
-		"external/icu",
-		"external/okhttp",
-		"external/wycheproof",
-		"prebuilts",
-	}
-
-	// Additional whitelisted path only used for ART testing, which needs access to core library
-	// targets. This does not affect the contents of a device image (system, vendor, etc.).
-	var artTests = []string{
-		"art/test",
-	}
-
-	// Core library constraints. The sdk_version: "none" can only be used in core library projects and ART tests.
-	// Access to core library targets is restricted using visibility rules.
-	rules := []Rule{
-		NeverAllow().
-			NotIn(coreLibraryProjects...).
-			NotIn(artTests...).
-			With("sdk_version", "none").
-			WithoutMatcher("name", Regexp("^android_.*stubs_current$")),
-	}
-
-	return rules
-}
-
 func createMediaRules() []Rule {
 	return []Rule{
 		NeverAllow().
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 1d454e5..8c7a538 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -215,50 +215,6 @@
 			"java_device_for_host can only be used in allowed projects",
 		},
 	},
-	// Libcore rule tests
-	{
-		name: "sdk_version: \"none\" inside core libraries",
-		fs: map[string][]byte{
-			"libcore/Android.bp": []byte(`
-				java_library {
-					name: "inside_core_libraries",
-					sdk_version: "none",
-				}`),
-		},
-	},
-	{
-		name: "sdk_version: \"none\" on android_*stubs_current stub",
-		fs: map[string][]byte{
-			"frameworks/base/Android.bp": []byte(`
-				java_library {
-					name: "android_stubs_current",
-					sdk_version: "none",
-				}`),
-		},
-	},
-	{
-		name: "sdk_version: \"none\" outside core libraries",
-		fs: map[string][]byte{
-			"Android.bp": []byte(`
-				java_library {
-					name: "outside_core_libraries",
-					sdk_version: "none",
-				}`),
-		},
-		expectedErrors: []string{
-			"module \"outside_core_libraries\": violates neverallow",
-		},
-	},
-	{
-		name: "sdk_version: \"current\"",
-		fs: map[string][]byte{
-			"Android.bp": []byte(`
-				java_library {
-					name: "outside_core_libraries",
-					sdk_version: "current",
-				}`),
-		},
-	},
 	// CC sdk rule tests
 	{
 		name: `"sdk_variant_only" outside allowed list`,
diff --git a/android/variable.go b/android/variable.go
index 93dac3d..753ddd7 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -126,13 +126,14 @@
 		}
 
 		Arc struct {
-			Cflags       []string
-			Exclude_srcs []string
-			Include_dirs []string
-			Shared_libs  []string
-			Static_libs  []string
-			Srcs         []string
-		}
+			Cflags            []string `android:"arch_variant"`
+			Exclude_srcs      []string `android:"arch_variant"`
+			Include_dirs      []string `android:"arch_variant"`
+			Shared_libs       []string `android:"arch_variant"`
+			Static_libs       []string `android:"arch_variant"`
+			Srcs              []string `android:"arch_variant"`
+			Whole_static_libs []string `android:"arch_variant"`
+		} `android:"arch_variant"`
 
 		Flatten_apex struct {
 			Enabled *bool
diff --git a/apex/apex.go b/apex/apex.go
index 88d93af..9e66254 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1183,6 +1183,9 @@
 // Implements cc.Coverage
 func (a *apexBundle) HideFromMake() {
 	a.properties.HideFromMake = true
+	// This HideFromMake is shadowing the ModuleBase one, call through to it for now.
+	// TODO(ccross): untangle these
+	a.ModuleBase.HideFromMake()
 }
 
 // Implements cc.Coverage
diff --git a/build_test.bash b/build_test.bash
index accca0f..3230f2d 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -23,6 +23,11 @@
 # evolve as we find interesting things to test or track performance for.
 #
 
+# Products that are broken or otherwise don't work with multiproduct_kati
+SKIPPED_PRODUCTS=(
+    mainline_sdk
+)
+
 # To track how long we took to startup. %N isn't supported on Darwin, but
 # that's detected in the Go code, which skips calculating the startup time.
 export TRACE_BEGIN_SOONG=$(date +%s%N)
@@ -50,4 +55,4 @@
 echo
 echo "Running Soong test..."
 soong_build_go multiproduct_kati android/soong/cmd/multiproduct_kati
-exec "$(getoutdir)/multiproduct_kati" "$@"
+exec "$(getoutdir)/multiproduct_kati" --skip-products "$(echo "${SKIPPED_PRODUCTS[@]-}" | tr ' ' ',')" "$@"
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index c079e83..7dd50f6 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -50,12 +50,30 @@
 
 var buildVariant = flag.String("variant", "eng", "build variant to use")
 
-var skipProducts = flag.String("skip-products", "", "comma-separated list of products to skip (known failures, etc)")
-var includeProducts = flag.String("products", "", "comma-separated list of products to build")
-
 var shardCount = flag.Int("shard-count", 1, "split the products into multiple shards (to spread the build onto multiple machines, etc)")
 var shard = flag.Int("shard", 1, "1-indexed shard to execute")
 
+var skipProducts multipleStringArg
+var includeProducts multipleStringArg
+
+func init() {
+	flag.Var(&skipProducts, "skip-products", "comma-separated list of products to skip (known failures, etc)")
+	flag.Var(&includeProducts, "products", "comma-separated list of products to build")
+}
+
+// multipleStringArg is a flag.Value that takes comma separated lists and converts them to a
+// []string.  The argument can be passed multiple times to append more values.
+type multipleStringArg []string
+
+func (m *multipleStringArg) String() string {
+	return strings.Join(*m, `, `)
+}
+
+func (m *multipleStringArg) Set(s string) error {
+	*m = append(*m, strings.Split(s, ",")...)
+	return nil
+}
+
 const errorLeadingLines = 20
 const errorTrailingLines = 20
 
@@ -250,9 +268,9 @@
 	var productsList []string
 	allProducts := strings.Fields(vars["all_named_products"])
 
-	if *includeProducts != "" {
-		missingProducts := []string{}
-		for _, product := range strings.Split(*includeProducts, ",") {
+	if len(includeProducts) > 0 {
+		var missingProducts []string
+		for _, product := range includeProducts {
 			if inList(product, allProducts) {
 				productsList = append(productsList, product)
 			} else {
@@ -267,9 +285,8 @@
 	}
 
 	finalProductsList := make([]string, 0, len(productsList))
-	skipList := strings.Split(*skipProducts, ",")
 	skipProduct := func(p string) bool {
-		for _, s := range skipList {
+		for _, s := range skipProducts {
 			if p == s {
 				return true
 			}
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index deaf77f..874edca 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -335,11 +335,14 @@
 	}
 }
 
-// Add class loader context for the given SDK version. Fail on unknown build/install paths.
+// Add class loader context for the given SDK version. Don't fail on unknown build/install paths, as
+// libraries with unknown paths still need to be processed by manifest_fixer (which doesn't care
+// about paths). For the subset of libraries that are used in dexpreopt, their build/install paths
+// are validated later before CLC is used (in validateClassLoaderContext).
 func (clcMap ClassLoaderContextMap) AddContextForSdk(ctx android.ModuleInstallPathContext, sdkVer int,
 	lib string, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
 
-	clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, true, nestedClcMap)
+	clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, false, nestedClcMap)
 }
 
 // Merge the other class loader context map into this one, do not override existing entries.
diff --git a/java/aar.go b/java/aar.go
index dfcd956..e3ad252 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -416,7 +416,6 @@
 	}
 
 	ctx.VisitDirectDeps(func(module android.Module) {
-		depName := ctx.OtherModuleName(module)
 		depTag := ctx.OtherModuleDependencyTag(module)
 
 		var exportPackage android.Path
@@ -432,15 +431,6 @@
 			if exportPackage != nil {
 				sharedLibs = append(sharedLibs, exportPackage)
 			}
-
-			// If the module is (or possibly could be) a component of a java_sdk_library
-			// (including the java_sdk_library) itself then append any implicit sdk library
-			// names to the list of sdk libraries to be added to the manifest.
-			if component, ok := module.(SdkLibraryComponentDependency); ok {
-				classLoaderContexts.MaybeAddContext(ctx, component.OptionalImplicitSdkLibrary(),
-					component.DexJarBuildPath(), component.DexJarInstallPath())
-			}
-
 		case frameworkResTag:
 			if exportPackage != nil {
 				sharedLibs = append(sharedLibs, exportPackage)
@@ -468,8 +458,7 @@
 			}
 		}
 
-		// Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
-		maybeAddCLCFromDep(module, depTag, depName, classLoaderContexts)
+		addCLCFromDep(ctx, module, classLoaderContexts)
 	})
 
 	deps = append(deps, sharedLibs...)
diff --git a/java/app.go b/java/app.go
index c0ac9c2..272d836 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1546,11 +1546,11 @@
 	a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
 	a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
 
-	dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
+	a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
 	if a.dexpreopter.uncompressedDex {
 		dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
-		a.uncompressDex(ctx, dexOutput, dexUncompressed.OutputPath)
-		dexOutput = dexUncompressed
+		a.uncompressDex(ctx, jnisUncompressed, dexUncompressed.OutputPath)
+		jnisUncompressed = dexUncompressed
 	}
 
 	apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk")
@@ -1574,11 +1574,11 @@
 		if lineage := String(a.properties.Lineage); lineage != "" {
 			lineageFile = android.PathForModuleSrc(ctx, lineage)
 		}
-		SignAppPackage(ctx, signed, dexOutput, certificates, nil, lineageFile)
+		SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile)
 		a.outputFile = signed
 	} else {
 		alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
-		TransformZipAlign(ctx, alignedApk, dexOutput)
+		TransformZipAlign(ctx, alignedApk, jnisUncompressed)
 		a.outputFile = alignedApk
 		a.certificate = PresignedCertificate
 	}
@@ -1990,7 +1990,7 @@
 		ctx.VisitDirectDeps(func(m android.Module) {
 			if tag, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
 				dep := ctx.OtherModuleName(m)
-				if lib, ok := m.(Dependency); ok {
+				if lib, ok := m.(UsesLibraryDependency); ok {
 					clcMap.AddContextForSdk(ctx, tag.sdkVersion, dep,
 						lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
 				} else if ctx.Config().AllowMissingDependencies() {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 67738d4..b5830c7 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -112,13 +112,13 @@
 	return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
 }
 
-func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) android.ModuleOutPath {
+func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) {
 	// TODO(b/148690468): The check on d.installPath is to bail out in cases where
 	// the dexpreopter struct hasn't been fully initialized before we're called,
 	// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
 	// disabled, even if installable is true.
 	if d.dexpreoptDisabled(ctx) || d.installPath.Base() == "." {
-		return dexJarFile
+		return
 	}
 
 	globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
@@ -213,12 +213,10 @@
 	dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
 	if err != nil {
 		ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
-		return dexJarFile
+		return
 	}
 
 	dexpreoptRule.Build("dexpreopt", "dexpreopt")
 
 	d.builtInstalled = dexpreoptRule.Installs().String()
-
-	return dexJarFile
 }
diff --git a/java/java.go b/java/java.go
index 02d78f2..719915e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -510,6 +510,7 @@
 type UsesLibraryDependency interface {
 	DexJarBuildPath() android.Path
 	DexJarInstallPath() android.Path
+	ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
 }
 
 type Dependency interface {
@@ -518,7 +519,6 @@
 	ImplementationJars() android.Paths
 	ResourceJars() android.Paths
 	AidlIncludeDirs() android.Paths
-	ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
 	ExportedPlugins() (android.Paths, []string, bool)
 	SrcJarArgs() ([]string, android.Paths)
 	BaseModuleName() string
@@ -1081,8 +1081,6 @@
 			switch tag {
 			case libTag:
 				deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
-				j.classLoaderContexts.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(),
-					dep.DexJarBuildPath(), dep.DexJarInstallPath())
 			case staticLibTag:
 				ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
 			}
@@ -1092,7 +1090,6 @@
 				deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
 			case libTag, instrumentationForTag:
 				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
-				j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
 				deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
 				pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins()
 				addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1179,8 +1176,7 @@
 			}
 		}
 
-		// Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
-		maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
+		addCLCFromDep(ctx, module, j.classLoaderContexts)
 	})
 
 	return deps
@@ -1786,7 +1782,7 @@
 		j.dexJarFile = dexOutputFile
 
 		// Dexpreopting
-		dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
+		j.dexpreopt(ctx, dexOutputFile)
 
 		j.maybeStrippedDexJarFile = dexOutputFile
 
@@ -2137,18 +2133,6 @@
 		j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
 			j.Stem()+".jar", j.outputFile, extraInstallDeps...)
 	}
-
-	// If this is a component library (stubs, etc.) for a java_sdk_library then
-	// add the name of that java_sdk_library to the exported sdk libs to make sure
-	// that, if necessary, a <uses-library> element for that java_sdk_library is
-	// added to the Android manifest.
-	j.classLoaderContexts.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
-		j.DexJarBuildPath(), j.DexJarInstallPath())
-
-	// A non-SDK library may provide a <uses-library> (the name may be different from the module name).
-	if lib := proptools.String(j.usesLibraryProperties.Provides_uses_lib); lib != "" {
-		j.classLoaderContexts.AddContext(ctx, lib, j.DexJarBuildPath(), j.DexJarInstallPath())
-	}
 }
 
 func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -2810,7 +2794,6 @@
 	var flags javaBuilderFlags
 
 	ctx.VisitDirectDeps(func(module android.Module) {
-		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
 		switch dep := module.(type) {
@@ -2825,27 +2808,17 @@
 			switch tag {
 			case libTag:
 				flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
-				j.classLoaderContexts.AddContext(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
 			}
 		}
 
-		// Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
-		maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
+		addCLCFromDep(ctx, module, j.classLoaderContexts)
 	})
 
-	var installFile android.Path
 	if Bool(j.properties.Installable) {
-		installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
 			jarName, outputFile)
 	}
 
-	// If this is a component library (impl, stubs, etc.) for a java_sdk_library then
-	// add the name of that java_sdk_library to the exported sdk libs to make sure
-	// that, if necessary, a <uses-library> element for that java_sdk_library is
-	// added to the Android manifest.
-	j.classLoaderContexts.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
-		outputFile, installFile)
-
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
 
 	if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
@@ -3123,7 +3096,7 @@
 
 	j.dexJarFile = dexOutputFile
 
-	dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
+	j.dexpreopt(ctx, dexOutputFile)
 
 	j.maybeStrippedDexJarFile = dexOutputFile
 
@@ -3259,30 +3232,63 @@
 var String = proptools.String
 var inList = android.InList
 
-// Add class loader context of a given dependency to the given class loader context, provided that
-// all the necessary conditions are met.
-func maybeAddCLCFromDep(depModule android.Module, depTag blueprint.DependencyTag,
-	depName string, clcMap dexpreopt.ClassLoaderContextMap) {
+// TODO(b/132357300) Generalize SdkLibrarComponentDependency to non-SDK libraries and merge with
+// this interface.
+type ProvidesUsesLib interface {
+	ProvidesUsesLib() *string
+}
 
-	if dep, ok := depModule.(Dependency); ok {
-		if depTag == libTag {
-			// Ok, propagate <uses-library> through non-static library dependencies.
-		} else if depTag == staticLibTag {
-			// Propagate <uses-library> through static library dependencies, unless it is a
-			// component library (such as stubs). Component libraries have a dependency on their
-			// SDK library, which should not be pulled just because of a static component library.
-			if comp, isComp := depModule.(SdkLibraryComponentDependency); isComp {
-				if compName := comp.OptionalImplicitSdkLibrary(); compName != nil {
-					dep = nil
-				}
-			}
-		} else {
-			// Don't propagate <uses-library> for other dependency tags.
-			dep = nil
-		}
+func (j *Module) ProvidesUsesLib() *string {
+	return j.usesLibraryProperties.Provides_uses_lib
+}
 
-		if dep != nil {
-			clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
+// Add class loader context (CLC) of a given dependency to the current CLC.
+func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
+	clcMap dexpreopt.ClassLoaderContextMap) {
+
+	dep, ok := depModule.(UsesLibraryDependency)
+	if !ok {
+		return
+	}
+
+	// Find out if the dependency is either an SDK library or an ordinary library that is disguised
+	// as an SDK library by the means of `provides_uses_lib` property. If yes, the library is itself
+	// a <uses-library> and should be added as a node in the CLC tree, and its CLC should be added
+	// as subtree of that node. Otherwise the library is not a <uses_library> and should not be
+	// added to CLC, but the transitive <uses-library> dependencies from its CLC should be added to
+	// the current CLC.
+	var implicitSdkLib *string
+	comp, isComp := depModule.(SdkLibraryComponentDependency)
+	if isComp {
+		implicitSdkLib = comp.OptionalImplicitSdkLibrary()
+		// OptionalImplicitSdkLibrary() may be nil so need to fall through to ProvidesUsesLib().
+	}
+	if implicitSdkLib == nil {
+		if ulib, ok := depModule.(ProvidesUsesLib); ok {
+			implicitSdkLib = ulib.ProvidesUsesLib()
 		}
 	}
+
+	depTag := ctx.OtherModuleDependencyTag(depModule)
+	if depTag == libTag || depTag == usesLibTag {
+		// Ok, propagate <uses-library> through non-static library dependencies.
+	} else if depTag == staticLibTag {
+		// Propagate <uses-library> through static library dependencies, unless it is a component
+		// library (such as stubs). Component libraries have a dependency on their SDK library,
+		// which should not be pulled just because of a static component library.
+		if implicitSdkLib != nil {
+			return
+		}
+	} else {
+		// Don't propagate <uses-library> for other dependency tags.
+		return
+	}
+
+	if implicitSdkLib != nil {
+		clcMap.AddContextForSdk(ctx, dexpreopt.AnySdkVersion, *implicitSdkLib,
+			dep.DexJarBuildPath(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
+	} else {
+		depName := ctx.OtherModuleName(depModule)
+		clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
+	}
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 2e10f9c..92b554b 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -28,6 +28,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/dexpreopt"
 )
 
 const (
@@ -2020,7 +2021,7 @@
 	return module.sdkJars(ctx, sdkVersion, false)
 }
 
-// to satisfy SdkLibraryDependency interface
+// to satisfy UsesLibraryDependency interface
 func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
 	if module.implLibraryModule == nil {
 		return nil
@@ -2029,7 +2030,7 @@
 	}
 }
 
-// to satisfy SdkLibraryDependency interface
+// to satisfy UsesLibraryDependency interface
 func (module *SdkLibraryImport) DexJarInstallPath() android.Path {
 	if module.implLibraryModule == nil {
 		return nil
@@ -2038,6 +2039,11 @@
 	}
 }
 
+// to satisfy UsesLibraryDependency interface
+func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+	return nil
+}
+
 // to satisfy apex.javaDependency interface
 func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
 	if module.implLibraryModule == nil {
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 1a33219..c27f098 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -56,6 +56,12 @@
     "Ndk_abis": true,
     "Exclude_draft_ndk_apis": true,
 
+    "VendorVars": {
+        "art_module": {
+            "source_build": "true"
+        }
+    },
+
     "MissingUsesLibraries": ${MISSING_USES_LIBRARIES}
 }
 EOF
diff --git a/third_party/zip/android_test.go b/third_party/zip/android_test.go
index 5154a17..9932c1b 100644
--- a/third_party/zip/android_test.go
+++ b/third_party/zip/android_test.go
@@ -74,3 +74,69 @@
 		}
 	}
 }
+
+func TestCopyFromZip64(t *testing.T) {
+	if testing.Short() {
+		t.Skip("slow test; skipping")
+	}
+
+	const size = uint32max + 1
+	fromZipBytes := &bytes.Buffer{}
+	fromZip := NewWriter(fromZipBytes)
+	w, err := fromZip.CreateHeaderAndroid(&FileHeader{
+		Name:               "large",
+		Method:             Store,
+		UncompressedSize64: size,
+		CompressedSize64:   size,
+	})
+	if err != nil {
+		t.Fatalf("Create: %v", err)
+	}
+	_, err = w.Write(make([]byte, size))
+	if err != nil {
+		t.Fatalf("Write: %v", err)
+	}
+	err = fromZip.Close()
+	if err != nil {
+		t.Fatalf("Close: %v", err)
+	}
+	fromZip = nil
+
+	fromZipReader, err := NewReader(bytes.NewReader(fromZipBytes.Bytes()), int64(fromZipBytes.Len()))
+	if err != nil {
+		t.Fatalf("NewReader: %v", err)
+	}
+
+	toZipBytes := &bytes.Buffer{}
+	toZip := NewWriter(toZipBytes)
+	err = toZip.CopyFrom(fromZipReader.File[0], fromZipReader.File[0].Name)
+	if err != nil {
+		t.Fatalf("CopyFrom: %v", err)
+	}
+
+	err = toZip.Close()
+	if err != nil {
+		t.Fatalf("Close: %v", err)
+	}
+
+	// Save some memory
+	fromZipReader = nil
+	fromZipBytes.Reset()
+
+	toZipReader, err := NewReader(bytes.NewReader(toZipBytes.Bytes()), int64(toZipBytes.Len()))
+	if err != nil {
+		t.Fatalf("NewReader: %v", err)
+	}
+
+	if len(toZipReader.File) != 1 {
+		t.Fatalf("Expected 1 file in toZip, got %d", len(toZipReader.File))
+	}
+
+	if g, w := toZipReader.File[0].CompressedSize64, uint64(size); g != w {
+		t.Errorf("Expected CompressedSize64 %d, got %d", w, g)
+	}
+
+	if g, w := toZipReader.File[0].UncompressedSize64, uint64(size); g != w {
+		t.Errorf("Expected UnompressedSize64 %d, got %d", w, g)
+	}
+}
diff --git a/third_party/zip/writer.go b/third_party/zip/writer.go
index 4c5eb78..8dd986e 100644
--- a/third_party/zip/writer.go
+++ b/third_party/zip/writer.go
@@ -276,9 +276,6 @@
 	} else {
 		b.uint32(h.CRC32)
 
-		if h.CompressedSize64 > uint32max || h.UncompressedSize64 > uint32max {
-			panic("skipping writing the data descriptor for a 64-bit value is not yet supported")
-		}
 		compressedSize := uint32(h.CompressedSize64)
 		if compressedSize == 0 {
 			compressedSize = h.CompressedSize
@@ -289,6 +286,21 @@
 			uncompressedSize = h.UncompressedSize
 		}
 
+		if h.CompressedSize64 > uint32max || h.UncompressedSize64 > uint32max {
+			// Sizes don't fit in a 32-bit field, put them in a zip64 extra instead.
+			compressedSize = uint32max
+			uncompressedSize = uint32max
+
+			// append a zip64 extra block to Extra
+			var buf [20]byte // 2x uint16 + 2x uint64
+			eb := writeBuf(buf[:])
+			eb.uint16(zip64ExtraId)
+			eb.uint16(16) // size = 2x uint64
+			eb.uint64(h.UncompressedSize64)
+			eb.uint64(h.CompressedSize64)
+			h.Extra = append(h.Extra, buf[:]...)
+		}
+
 		b.uint32(compressedSize)
 		b.uint32(uncompressedSize)
 	}