Merge "Remove ApexBundleDepsInfo.MinSdkVersion()"
diff --git a/android/module.go b/android/module.go
index e2b7dd3..7e64f0a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -898,6 +898,13 @@
 	return Bool(m.commonProperties.System_ext_specific)
 }
 
+// RequiresStableAPIs returns true if the module will be installed to a partition that may
+// be updated separately from the system image.
+func (m *ModuleBase) RequiresStableAPIs(ctx BaseModuleContext) bool {
+	return m.SocSpecific() || m.DeviceSpecific() ||
+		(m.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface())
+}
+
 func (m *ModuleBase) PartitionTag(config DeviceConfig) string {
 	partition := "system"
 	if m.SocSpecific() {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 82745a4..ee4a13a 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -69,6 +69,10 @@
 	p.properties.Prefer = proptools.BoolPtr(true)
 }
 
+func (p *Prebuilt) Prefer() bool {
+	return proptools.Bool(p.properties.Prefer)
+}
+
 // The below source-related functions and the srcs, src fields are based on an assumption that
 // prebuilt modules have a static source property at the moment. Currently there is only one
 // exception, android_app_import, which chooses a source file depending on the product's DPI
diff --git a/android/visibility.go b/android/visibility.go
index 2cb0023..5aa7f3f 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -140,7 +140,7 @@
 }
 
 func (r packageRule) String() string {
-	return fmt.Sprintf("//%s:__pkg__", r.pkg)
+	return fmt.Sprintf("//%s", r.pkg) // :__pkg__ is the default, so skip it.
 }
 
 // A subpackagesRule is a visibility rule that matches modules in a specific package (i.e.
@@ -496,6 +496,13 @@
 
 	rule := effectiveVisibilityRules(ctx.Config(), qualified)
 
+	// Modules are implicitly visible to other modules in the same package,
+	// without checking the visibility rules. Here we need to add that visibility
+	// explicitly.
+	if rule != nil && !rule.matches(qualified) {
+		rule = append(rule, packageRule{dir})
+	}
+
 	return rule.Strings()
 }
 
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 2c5407c..5774809 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -120,6 +120,9 @@
 			if len(fi.symlinks) > 0 {
 				fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " "))
 			}
+			if len(fi.dataPaths) > 0 {
+				fmt.Println(w, "LOCAL_TEST_DATA :=", strings.Join(cc.AndroidMkDataPaths(fi.dataPaths), " "))
+			}
 
 			if fi.module != nil && len(fi.module.NoticeFiles()) > 0 {
 				fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(fi.module.NoticeFiles().Strings(), " "))
diff --git a/apex/apex.go b/apex/apex.go
index fa71ffa..9525ff2 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -251,7 +251,6 @@
 		"libtextclassifier_hash_static",
 		"libtflite_static",
 		"libutf",
-		"libz_current",
 		"tensorflow_headers",
 	}
 	//
@@ -1214,6 +1213,7 @@
 	module     android.Module
 	// list of symlinks that will be created in installDir that point to this apexFile
 	symlinks      []string
+	dataPaths     android.Paths
 	transitiveDep bool
 	moduleDir     string
 
@@ -1249,16 +1249,20 @@
 	return af.builtFile != nil && af.builtFile.String() != ""
 }
 
+func (af *apexFile) apexRelativePath(path string) string {
+	return filepath.Join(af.installDir, path)
+}
+
 // Path() returns path of this apex file relative to the APEX root
 func (af *apexFile) Path() string {
-	return filepath.Join(af.installDir, af.builtFile.Base())
+	return af.apexRelativePath(af.builtFile.Base())
 }
 
 // SymlinkPaths() returns paths of the symlinks (if any) relative to the APEX root
 func (af *apexFile) SymlinkPaths() []string {
 	var ret []string
 	for _, symlink := range af.symlinks {
-		ret = append(ret, filepath.Join(af.installDir, symlink))
+		ret = append(ret, af.apexRelativePath(symlink))
 	}
 	return ret
 }
@@ -1664,6 +1668,7 @@
 	fileToCopy := cc.OutputFile().Path()
 	af := newApexFile(ctx, fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
 	af.symlinks = cc.Symlinks()
+	af.dataPaths = cc.DataPaths()
 	return af
 }
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index dc69862..021c3e2 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -180,6 +180,8 @@
 		"build/make/core/proguard.flags":             nil,
 		"build/make/core/proguard_basic_keeps.flags": nil,
 		"dummy.txt":                                  nil,
+		"baz":                                        nil,
+		"bar/baz":                                    nil,
 	}
 
 	cc.GatherRequiredFilesForTest(fs)
@@ -3267,6 +3269,14 @@
 			private_key: "testkey.pem",
 		}
 
+		filegroup {
+			name: "fg",
+			srcs: [
+				"baz",
+				"bar/baz"
+			],
+		}
+
 		cc_test {
 			name: "mytest",
 			gtest: false,
@@ -3276,6 +3286,7 @@
 			system_shared_libs: [],
 			static_executable: true,
 			stl: "none",
+			data: [":fg"],
 		}
 
 		cc_library {
@@ -3308,6 +3319,10 @@
 	ensureContains(t, copyCmds, "image.apex/bin/test/mytest")
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
 
+	//Ensure that test data are copied into apex.
+	ensureContains(t, copyCmds, "image.apex/bin/test/baz")
+	ensureContains(t, copyCmds, "image.apex/bin/test/bar/baz")
+
 	// Ensure that test deps built with `test_per_src` are copied into apex.
 	ensureContains(t, copyCmds, "image.apex/bin/test/mytest1")
 	ensureContains(t, copyCmds, "image.apex/bin/test/mytest2")
diff --git a/apex/builder.go b/apex/builder.go
index ca24f2c..47ae501 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -350,6 +350,19 @@
 			symlinkDest := android.PathForModuleOut(ctx, "image"+suffix, symlinkPath).String()
 			copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest)
 		}
+		for _, d := range fi.dataPaths {
+			// TODO(eakammer): This is now the third repetition of ~this logic for test paths, refactoring should be possible
+			relPath := d.Rel()
+			dataPath := d.String()
+			if !strings.HasSuffix(dataPath, relPath) {
+				panic(fmt.Errorf("path %q does not end with %q", dataPath, relPath))
+			}
+
+			dataDest := android.PathForModuleOut(ctx, "image"+suffix, fi.apexRelativePath(relPath)).String()
+
+			copyCommands = append(copyCommands, "cp -f "+d.String()+" "+dataDest)
+			implicitInputs = append(implicitInputs, d)
+		}
 	}
 
 	// TODO(jiyong): use RuleBuilder
@@ -406,6 +419,9 @@
 			pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
 			if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
 				executablePaths = append(executablePaths, pathInApex)
+				for _, d := range f.dataPaths {
+					readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.Rel()))
+				}
 				for _, s := range f.symlinks {
 					executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
 				}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 671adb5..3ce1a89 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -149,7 +149,7 @@
 	return []android.AndroidMkEntries{entries}
 }
 
-func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func AndroidMkDataPaths(data android.Paths) []string {
 	var testFiles []string
 	for _, d := range data {
 		rel := d.Rel()
@@ -160,6 +160,11 @@
 		path = strings.TrimSuffix(path, rel)
 		testFiles = append(testFiles, path+":"+rel)
 	}
+	return testFiles
+}
+
+func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+	testFiles := AndroidMkDataPaths(data)
 	if len(testFiles) > 0 {
 		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 			entries.AddStrings("LOCAL_TEST_DATA", testFiles...)
diff --git a/cc/cc.go b/cc/cc.go
index 02c4879..fbd5bdf 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1395,6 +1395,15 @@
 	return ok && test.isAllTestsVariation()
 }
 
+func (c *Module) DataPaths() android.Paths {
+	if p, ok := c.installer.(interface {
+		dataPaths() android.Paths
+	}); ok {
+		return p.dataPaths()
+	}
+	return nil
+}
+
 func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string {
 	// Returns the name suffix for product and vendor variants. If the VNDK version is not
 	// "current", it will append the VNDK version to the name suffix.
diff --git a/cc/config/global.go b/cc/config/global.go
index 1dd8a2d..4f3f25e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -162,7 +162,7 @@
 
 		// http://b/131390872
 		// Automatically initialize any uninitialized stack variables.
-		// Prefer zero-init if multiple options are set.
+		// Prefer zero-init if both options are set.
 		if ctx.Config().IsEnvTrue("AUTO_ZERO_INITIALIZE") {
 			flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang")
 		} else if ctx.Config().IsEnvTrue("AUTO_PATTERN_INITIALIZE") {
@@ -170,8 +170,8 @@
 		} else if ctx.Config().IsEnvTrue("AUTO_UNINITIALIZE") {
 			flags = append(flags, "-ftrivial-auto-var-init=uninitialized")
 		} else {
-			// Default to zero initialization.
-			flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang")
+			// Default to pattern initialization.
+			flags = append(flags, "-ftrivial-auto-var-init=pattern")
 		}
 
 		return strings.Join(flags, " ")
diff --git a/cc/test.go b/cc/test.go
index b1f8eec..2439c94 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -160,6 +160,10 @@
 	return test.baseCompiler.Properties.Srcs
 }
 
+func (test *testBinary) dataPaths() android.Paths {
+	return test.data
+}
+
 func (test *testBinary) isAllTestsVariation() bool {
 	stem := test.binaryDecorator.Properties.Stem
 	return stem != nil && *stem == ""
@@ -345,9 +349,7 @@
 	}
 	if Bool(test.Properties.Disable_framework) {
 		var options []tradefed.Option
-		options = append(options, tradefed.Option{Name: "run-command", Value: "stop"})
-		options = append(options, tradefed.Option{Name: "teardown-command", Value: "start"})
-		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RunCommandTargetPreparer", options})
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
 	}
 	if Bool(test.testDecorator.Properties.Isolated) {
 		configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
diff --git a/java/app.go b/java/app.go
index e08a1ae..a81a061 100755
--- a/java/app.go
+++ b/java/app.go
@@ -129,6 +129,9 @@
 	// or an android_app_certificate module name in the form ":module".
 	Certificate *string
 
+	// Name of the signing certificate lineage file.
+	Lineage *string
+
 	// the package name of this app. The package name in the manifest file is used if one was not given.
 	Package_name *string
 
@@ -249,7 +252,10 @@
 
 		// If the app builds against an Android SDK use the SDK variant of JNI dependencies
 		// unless jni_uses_platform_apis is set.
-		if (usesSDK && !Bool(a.appProperties.Jni_uses_platform_apis)) ||
+		// Don't require the SDK variant for apps that are shipped on vendor, etc., as they already
+		// have stable APIs through the VNDK.
+		if (usesSDK && !a.RequiresStableAPIs(ctx) &&
+			!Bool(a.appProperties.Jni_uses_platform_apis)) ||
 			Bool(a.appProperties.Jni_uses_sdk_apis) {
 			variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
 		}
@@ -612,7 +618,7 @@
 
 	dexJarFile := a.dexBuildActions(ctx)
 
-	jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
+	jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
 	jniJarFile := a.jniBuildActions(jniLibs, ctx)
 
 	if ctx.Failed() {
@@ -624,13 +630,17 @@
 
 	// Build a final signed app package.
 	packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk")
-	CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps)
+	var lineageFile android.Path
+	if lineage := String(a.overridableAppProperties.Lineage); lineage != "" {
+		lineageFile = android.PathForModuleSrc(ctx, lineage)
+	}
+	CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, lineageFile)
 	a.outputFile = packageFile
 
 	for _, split := range a.aapt.splits {
 		// Sign the split APKs
 		packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk")
-		CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps)
+		CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, lineageFile)
 		a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
 	}
 
@@ -650,12 +660,25 @@
 	a.buildAppDependencyInfo(ctx)
 }
 
-func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool,
+type appDepsInterface interface {
+	sdkVersion() sdkSpec
+	minSdkVersion() sdkSpec
+	RequiresStableAPIs(ctx android.BaseModuleContext) bool
+}
+
+func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
+	shouldCollectRecursiveNativeDeps bool,
 	checkNativeSdkVersion bool) ([]jniLib, []Certificate) {
+
 	var jniLibs []jniLib
 	var certificates []Certificate
 	seenModulePaths := make(map[string]bool)
 
+	if checkNativeSdkVersion {
+		checkNativeSdkVersion = app.sdkVersion().specified() &&
+			app.sdkVersion().kind != sdkCorePlatform && !app.RequiresStableAPIs(ctx)
+	}
+
 	ctx.WalkDeps(func(module android.Module, parent android.Module) bool {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
@@ -673,16 +696,9 @@
 				}
 				seenModulePaths[path.String()] = true
 
-				if checkNativeSdkVersion {
-					if app, ok := ctx.Module().(interface{ sdkVersion() sdkSpec }); ok {
-						if app.sdkVersion().specified() &&
-							app.sdkVersion().kind != sdkCorePlatform &&
-							dep.SdkVersion() == "" {
-							ctx.PropertyErrorf("jni_libs",
-								"JNI dependency %q uses platform APIs, but this module does not",
-								otherName)
-						}
-					}
+				if checkNativeSdkVersion && dep.SdkVersion() == "" {
+					ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not",
+						otherName)
 				}
 
 				if lib.Valid() {
@@ -1272,7 +1288,7 @@
 		ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
 	}
 
-	_, certificates := collectAppDeps(ctx, false, false)
+	_, certificates := collectAppDeps(ctx, a, false, false)
 
 	// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
 	// TODO: LOCAL_PACKAGE_SPLITS
@@ -1327,7 +1343,7 @@
 		}
 		a.certificate = certificates[0]
 		signed := android.PathForModuleOut(ctx, "signed", apkFilename)
-		SignAppPackage(ctx, signed, dexOutput, certificates)
+		SignAppPackage(ctx, signed, dexOutput, certificates, nil)
 		a.outputFile = signed
 	} else {
 		alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
@@ -1398,6 +1414,14 @@
 	return false
 }
 
+func (a *AndroidAppImport) sdkVersion() sdkSpec {
+	return sdkSpecFrom("")
+}
+
+func (a *AndroidAppImport) minSdkVersion() sdkSpec {
+	return sdkSpecFrom("")
+}
+
 func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
 	props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
 
@@ -1583,10 +1607,10 @@
 	r.aapt.buildActions(ctx, r, aaptLinkFlags...)
 
 	// Sign the built package
-	_, certificates := collectAppDeps(ctx, false, false)
+	_, certificates := collectAppDeps(ctx, r, false, false)
 	certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
 	signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
-	SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates)
+	SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil)
 	r.certificate = certificates[0]
 
 	r.outputFile = signed
diff --git a/java/app_builder.go b/java/app_builder.go
index 5e7fbe6..1efc856 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -45,7 +45,7 @@
 	})
 
 func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
-	packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) {
+	packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, lineageFile android.Path) {
 
 	unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
 	unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -66,10 +66,10 @@
 		Implicits: deps,
 	})
 
-	SignAppPackage(ctx, outputFile, unsignedApk, certificates)
+	SignAppPackage(ctx, outputFile, unsignedApk, certificates, lineageFile)
 }
 
-func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) {
+func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate, lineageFile android.Path) {
 
 	var certificateArgs []string
 	var deps android.Paths
@@ -78,6 +78,11 @@
 		deps = append(deps, c.Pem, c.Key)
 	}
 
+	var flags []string
+	if lineageFile != nil {
+		flags = append(flags, "--lineage", lineageFile.String())
+	}
+
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        Signapk,
 		Description: "signapk",
@@ -86,6 +91,7 @@
 		Implicits:   deps,
 		Args: map[string]string{
 			"certificates": strings.Join(certificateArgs, " "),
+			"flags":        strings.Join(flags, " "),
 		},
 	})
 }
diff --git a/java/app_test.go b/java/app_test.go
index 4249abd..45dab62 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1265,25 +1265,44 @@
 			platform_apis: true,
 			jni_uses_sdk_apis: true,
 		}
+
+		cc_library {
+			name: "libvendorjni",
+			system_shared_libs: [],
+			stl: "none",
+			vendor: true,
+		}
+
+		android_test {
+			name: "app_vendor",
+			jni_libs: ["libvendorjni"],
+			sdk_version: "current",
+			vendor: true,
+		}
 	`)
 
 	testCases := []struct {
-		name   string
-		sdkJNI bool
+		name      string
+		sdkJNI    bool
+		vendorJNI bool
 	}{
-		{"app_platform", false},
-		{"app_sdk", true},
-		{"app_force_platform", false},
-		{"app_force_sdk", true},
+		{name: "app_platform"},
+		{name: "app_sdk", sdkJNI: true},
+		{name: "app_force_platform"},
+		{name: "app_force_sdk", sdkJNI: true},
+		{name: "app_vendor", vendorJNI: true},
 	}
 
+	platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
+		Output("libjni.so").Output.String()
+	sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
+		Output("libjni.so").Output.String()
+	vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared").
+		Output("libvendorjni.so").Output.String()
+
 	for _, test := range testCases {
 		t.Run(test.name, func(t *testing.T) {
 			app := ctx.ModuleForTests(test.name, "android_common")
-			platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
-				Output("libjni.so").Output.String()
-			sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
-				Output("libjni.so").Output.String()
 
 			jniLibZip := app.MaybeOutput("jnilibs.zip")
 			if len(jniLibZip.Implicits) != 1 {
@@ -1295,6 +1314,10 @@
 				if gotJNI != sdkJNI {
 					t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI)
 				}
+			} else if test.vendorJNI {
+				if gotJNI != vendorJNI {
+					t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI)
+				}
 			} else {
 				if gotJNI != platformJNI {
 					t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI)
@@ -1330,7 +1353,8 @@
 		name                string
 		bp                  string
 		certificateOverride string
-		expected            string
+		expectedLineage     string
+		expectedCertificate string
 	}{
 		{
 			name: "default",
@@ -1342,7 +1366,8 @@
 				}
 			`,
 			certificateOverride: "",
-			expected:            "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8",
+			expectedLineage:     "",
+			expectedCertificate: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8",
 		},
 		{
 			name: "module certificate property",
@@ -1360,7 +1385,8 @@
 				}
 			`,
 			certificateOverride: "",
-			expected:            "cert/new_cert.x509.pem cert/new_cert.pk8",
+			expectedLineage:     "",
+			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
 		},
 		{
 			name: "path certificate property",
@@ -1373,7 +1399,8 @@
 				}
 			`,
 			certificateOverride: "",
-			expected:            "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+			expectedLineage:     "",
+			expectedCertificate: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
 		},
 		{
 			name: "certificate overrides",
@@ -1391,7 +1418,28 @@
 				}
 			`,
 			certificateOverride: "foo:new_certificate",
-			expected:            "cert/new_cert.x509.pem cert/new_cert.pk8",
+			expectedLineage:     "",
+			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
+		},
+		{
+			name: "certificate lineage",
+			bp: `
+				android_app {
+					name: "foo",
+					srcs: ["a.java"],
+					certificate: ":new_certificate",
+					lineage: "lineage.bin",
+					sdk_version: "current",
+				}
+
+				android_app_certificate {
+					name: "new_certificate",
+					certificate: "cert/new_cert",
+				}
+			`,
+			certificateOverride: "",
+			expectedLineage:     "--lineage lineage.bin",
+			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
 		},
 	}
 
@@ -1407,9 +1455,14 @@
 			foo := ctx.ModuleForTests("foo", "android_common")
 
 			signapk := foo.Output("foo.apk")
-			signFlags := signapk.Args["certificates"]
-			if test.expected != signFlags {
-				t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
+			signCertificateFlags := signapk.Args["certificates"]
+			if test.expectedCertificate != signCertificateFlags {
+				t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedCertificate, signCertificateFlags)
+			}
+
+			signFlags := signapk.Args["flags"]
+			if test.expectedLineage != signFlags {
+				t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedLineage, signFlags)
 			}
 		})
 	}
@@ -1523,6 +1576,7 @@
 			name: "bar",
 			base: "foo",
 			certificate: ":new_certificate",
+			lineage: "lineage.bin",
 			logging_parent: "bah",
 		}
 
@@ -1543,7 +1597,8 @@
 		variantName    string
 		apkName        string
 		apkPath        string
-		signFlag       string
+		certFlag       string
+		lineageFlag    string
 		overrides      []string
 		aaptFlag       string
 		logging_parent string
@@ -1552,7 +1607,8 @@
 			moduleName:     "foo",
 			variantName:    "android_common",
 			apkPath:        "/target/product/test_device/system/app/foo/foo.apk",
-			signFlag:       "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+			certFlag:       "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+			lineageFlag:    "",
 			overrides:      []string{"qux"},
 			aaptFlag:       "",
 			logging_parent: "",
@@ -1561,7 +1617,8 @@
 			moduleName:     "bar",
 			variantName:    "android_common_bar",
 			apkPath:        "/target/product/test_device/system/app/bar/bar.apk",
-			signFlag:       "cert/new_cert.x509.pem cert/new_cert.pk8",
+			certFlag:       "cert/new_cert.x509.pem cert/new_cert.pk8",
+			lineageFlag:    "--lineage lineage.bin",
 			overrides:      []string{"qux", "foo"},
 			aaptFlag:       "",
 			logging_parent: "bah",
@@ -1570,7 +1627,8 @@
 			moduleName:     "baz",
 			variantName:    "android_common_baz",
 			apkPath:        "/target/product/test_device/system/app/baz/baz.apk",
-			signFlag:       "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+			certFlag:       "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+			lineageFlag:    "",
 			overrides:      []string{"qux", "foo"},
 			aaptFlag:       "--rename-manifest-package org.dandroid.bp",
 			logging_parent: "",
@@ -1595,9 +1653,15 @@
 
 		// Check the certificate paths
 		signapk := variant.Output(expected.moduleName + ".apk")
-		signFlag := signapk.Args["certificates"]
-		if expected.signFlag != signFlag {
-			t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag)
+		certFlag := signapk.Args["certificates"]
+		if expected.certFlag != certFlag {
+			t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.certFlag, certFlag)
+		}
+
+		// Check the lineage flags
+		lineageFlag := signapk.Args["flags"]
+		if expected.lineageFlag != lineageFlag {
+			t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.lineageFlag, lineageFlag)
 		}
 
 		// Check if the overrides field values are correctly aggregated.
diff --git a/java/java.go b/java/java.go
index de38b26..17b963f 100644
--- a/java/java.go
+++ b/java/java.go
@@ -95,8 +95,7 @@
 }
 
 func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
-	if j.SocSpecific() || j.DeviceSpecific() ||
-		(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
+	if j.RequiresStableAPIs(ctx) {
 		if sc, ok := ctx.Module().(sdkContext); ok {
 			if !sc.sdkVersion().specified() {
 				ctx.PropertyErrorf("sdk_version",
diff --git a/java/java_test.go b/java/java_test.go
index 5e43ce5..f61f4bb 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1247,6 +1247,20 @@
 		`)
 }
 
+func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
+	testJava(t, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java", "b.java"],
+			api_packages: ["foo"],
+			system: {
+				enabled: true,
+				sdk_version: "module_current",
+			},
+		}
+		`)
+}
+
 var compilerFlagsTestCases = []struct {
 	in  string
 	out bool
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 4a94264..7e81c1e 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -92,6 +92,9 @@
 	// The name of the field in the dynamically created structure.
 	fieldName string
 
+	// The name of the property in the java_sdk_library_import
+	propertyName string
+
 	// The tag to use to depend on the stubs library module.
 	stubsTag scopeDependencyTag
 
@@ -142,7 +145,8 @@
 // Initialize a scope, creating and adding appropriate dependency tags
 func initApiScope(scope *apiScope) *apiScope {
 	name := scope.name
-	scope.fieldName = proptools.FieldNameForProperty(name)
+	scope.propertyName = strings.ReplaceAll(name, "-", "_")
+	scope.fieldName = proptools.FieldNameForProperty(scope.propertyName)
 	scope.stubsTag = scopeDependencyTag{
 		name:             name + "-stubs",
 		apiScope:         scope,
@@ -253,7 +257,7 @@
 		unstable:       true,
 	})
 	apiScopeModuleLib = initApiScope(&apiScope{
-		name:    "module_lib",
+		name:    "module-lib",
 		extends: apiScopeSystem,
 		// Module_lib scope is disabled by default in legacy mode.
 		//
@@ -320,6 +324,22 @@
 	// Otherwise, if this is not set for any scope then the default  behavior is
 	// scope specific so please refer to the scope specific property documentation.
 	Enabled *bool
+
+	// The sdk_version to use for building the stubs.
+	//
+	// If not specified then it will use an sdk_version determined as follows:
+	// 1) If the sdk_version specified on the java_sdk_library is none then this
+	//    will be none. This is used for java_sdk_library instances that are used
+	//    to create stubs that contribute to the core_current sdk version.
+	// 2) Otherwise, it is assumed that this library extends but does not contribute
+	//    directly to a specific sdk_version and so this uses the sdk_version appropriate
+	//    for the api scope. e.g. public will use sdk_version: current, system will use
+	//    sdk_version: system_current, etc.
+	//
+	// This does not affect the sdk_version used for either generating the stubs source
+	// or the API file. They both have to use the same sdk_version as is used for
+	// compiling the implementation library.
+	Sdk_version *string
 }
 
 type sdkLibraryProperties struct {
@@ -701,6 +721,11 @@
 
 // Get the sdk version for use when compiling the stubs library.
 func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string {
+	scopeProperties := module.scopeToProperties[apiScope]
+	if scopeProperties.Sdk_version != nil {
+		return proptools.String(scopeProperties.Sdk_version)
+	}
+
 	sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
 	if sdkDep.hasStandardLibs() {
 		// If building against a standard sdk then use the sdk version appropriate for the scope.
@@ -1427,22 +1452,23 @@
 	} else if module.SystemExtSpecific() {
 		props.System_ext_specific = proptools.BoolPtr(true)
 	}
-	// If the build should use prebuilt sdks then set prefer to true on the stubs library.
-	// That will cause the prebuilt version of the stubs to override the source version.
-	if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
-		props.Prefer = proptools.BoolPtr(true)
-	}
+	// The imports are preferred if the java_sdk_library_import is preferred.
+	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
 	mctx.CreateModule(ImportFactory, &props)
 }
 
 func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
 	props := struct {
-		Name *string
-		Srcs []string
+		Name   *string
+		Srcs   []string
+		Prefer *bool
 	}{}
 	props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
 	props.Srcs = scopeProperties.Stub_srcs
 	mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
+
+	// The stubs source is preferred if the java_sdk_library_import is preferred.
+	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
 }
 
 func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1646,6 +1672,9 @@
 
 	// The Java stubs source files.
 	Stub_srcs []string
+
+	// The naming scheme.
+	Naming_scheme *string
 }
 
 type scopeProperties struct {
@@ -1675,12 +1704,17 @@
 	}
 
 	s.Libs = sdk.properties.Libs
+	s.Naming_scheme = sdk.commonProperties.Naming_scheme
 }
 
 func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
+	if s.Naming_scheme != nil {
+		propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme))
+	}
+
 	for _, apiScope := range allApiScopes {
 		if properties, ok := s.Scopes[apiScope]; ok {
-			scopeSet := propertySet.AddPropertySet(apiScope.name)
+			scopeSet := propertySet.AddPropertySet(apiScope.propertyName)
 
 			scopeDir := filepath.Join("sdk_library", s.OsPrefix(), apiScope.name)
 
diff --git a/java/testing.go b/java/testing.go
index 6929bb7..7d7cb57 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -116,6 +116,7 @@
 
 		"cert/new_cert.x509.pem": nil,
 		"cert/new_cert.pk8":      nil,
+		"lineage.bin":            nil,
 
 		"testdata/data": nil,
 
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index acacd97..bbd6384 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -1134,7 +1134,69 @@
 	)
 }
 
-func TestSnapshotWithJavaSdkLibrary_ApiSurfaces(t *testing.T) {
+func TestSnapshotWithJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
+	result := testSdkWithJava(t, `
+		sdk {
+			name: "mysdk",
+			java_sdk_libs: ["myjavalib"],
+		}
+
+		java_sdk_library {
+			name: "myjavalib",
+			srcs: ["Test.java"],
+			sdk_version: "module_current",
+			public: {
+				enabled: true,
+				sdk_version: "module_current",
+			},
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+    name: "mysdk_myjavalib@current",
+    sdk_member_name: "myjavalib",
+    public: {
+        jars: ["sdk_library/public/myjavalib-stubs.jar"],
+        stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+        current_api: "sdk_library/public/myjavalib.txt",
+        removed_api: "sdk_library/public/myjavalib-removed.txt",
+        sdk_version: "module_current",
+    },
+}
+
+java_sdk_library_import {
+    name: "myjavalib",
+    prefer: false,
+    public: {
+        jars: ["sdk_library/public/myjavalib-stubs.jar"],
+        stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+        current_api: "sdk_library/public/myjavalib.txt",
+        removed_api: "sdk_library/public/myjavalib-removed.txt",
+        sdk_version: "module_current",
+    },
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    java_sdk_libs: ["mysdk_myjavalib@current"],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
+`),
+		checkMergeZips(
+			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
+		),
+	)
+}
+
+func TestSnapshotWithJavaSdkLibrary_ApiScopes(t *testing.T) {
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
@@ -1266,10 +1328,10 @@
         sdk_version: "system_current",
     },
     module_lib: {
-        jars: ["sdk_library/module_lib/myjavalib-stubs.jar"],
-        stub_srcs: ["sdk_library/module_lib/myjavalib_stub_sources"],
-        current_api: "sdk_library/module_lib/myjavalib.txt",
-        removed_api: "sdk_library/module_lib/myjavalib-removed.txt",
+        jars: ["sdk_library/module-lib/myjavalib-stubs.jar"],
+        stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"],
+        current_api: "sdk_library/module-lib/myjavalib.txt",
+        removed_api: "sdk_library/module-lib/myjavalib-removed.txt",
         sdk_version: "module_current",
     },
 }
@@ -1293,10 +1355,10 @@
         sdk_version: "system_current",
     },
     module_lib: {
-        jars: ["sdk_library/module_lib/myjavalib-stubs.jar"],
-        stub_srcs: ["sdk_library/module_lib/myjavalib_stub_sources"],
-        current_api: "sdk_library/module_lib/myjavalib.txt",
-        removed_api: "sdk_library/module_lib/myjavalib-removed.txt",
+        jars: ["sdk_library/module-lib/myjavalib-stubs.jar"],
+        stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"],
+        current_api: "sdk_library/module-lib/myjavalib.txt",
+        removed_api: "sdk_library/module-lib/myjavalib-removed.txt",
         sdk_version: "module_current",
     },
 }
@@ -1313,14 +1375,81 @@
 .intermediates/myjavalib.stubs.system/android_common/javac/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
 .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.module_lib/android_common/javac/myjavalib.stubs.module_lib.jar -> sdk_library/module_lib/myjavalib-stubs.jar
-.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module_lib/myjavalib.txt
-.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module_lib/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.module_lib/android_common/javac/myjavalib.stubs.module_lib.jar -> sdk_library/module-lib/myjavalib-stubs.jar
+.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt
+.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib-removed.txt
 `),
 		checkMergeZips(
 			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
 			".intermediates/mysdk/common_os/tmp/sdk_library/system/myjavalib_stub_sources.zip",
-			".intermediates/mysdk/common_os/tmp/sdk_library/module_lib/myjavalib_stub_sources.zip",
+			".intermediates/mysdk/common_os/tmp/sdk_library/module-lib/myjavalib_stub_sources.zip",
+		),
+	)
+}
+
+func TestSnapshotWithJavaSdkLibrary_NamingScheme(t *testing.T) {
+	result := testSdkWithJava(t, `
+		sdk {
+			name: "mysdk",
+			java_sdk_libs: ["myjavalib"],
+		}
+
+		java_sdk_library {
+			name: "myjavalib",
+			apex_available: ["//apex_available:anyapex"],
+			srcs: ["Test.java"],
+			sdk_version: "current",
+			naming_scheme: "framework-modules",
+			public: {
+				enabled: true,
+			},
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+    name: "mysdk_myjavalib@current",
+    sdk_member_name: "myjavalib",
+    apex_available: ["//apex_available:anyapex"],
+    naming_scheme: "framework-modules",
+    public: {
+        jars: ["sdk_library/public/myjavalib-stubs.jar"],
+        stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+        current_api: "sdk_library/public/myjavalib.txt",
+        removed_api: "sdk_library/public/myjavalib-removed.txt",
+        sdk_version: "current",
+    },
+}
+
+java_sdk_library_import {
+    name: "myjavalib",
+    prefer: false,
+    apex_available: ["//apex_available:anyapex"],
+    naming_scheme: "framework-modules",
+    public: {
+        jars: ["sdk_library/public/myjavalib-stubs.jar"],
+        stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+        current_api: "sdk_library/public/myjavalib.txt",
+        removed_api: "sdk_library/public/myjavalib-removed.txt",
+        sdk_version: "current",
+    },
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    java_sdk_libs: ["mysdk_myjavalib@current"],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/myjavalib-stubs-publicapi/android_common/javac/myjavalib-stubs-publicapi.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib-stubs-srcs-publicapi/android_common/myjavalib-stubs-srcs-publicapi_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib-stubs-srcs-publicapi/android_common/myjavalib-stubs-srcs-publicapi_api.txt -> sdk_library/public/myjavalib-removed.txt
+`),
+		checkMergeZips(
+			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
 		),
 	)
 }
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index ae1a492..9bbf410 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -155,14 +155,20 @@
 java_import {
     name: "mysdk_myjavalib@current",
     sdk_member_name: "myjavalib",
-    visibility: ["//other/foo:__pkg__"],
+    visibility: [
+        "//other/foo",
+        "//package",
+    ],
     jars: ["java/myjavalib.jar"],
 }
 
 java_import {
     name: "myjavalib",
     prefer: false,
-    visibility: ["//other/foo:__pkg__"],
+    visibility: [
+        "//other/foo",
+        "//package",
+    ],
     jars: ["java/myjavalib.jar"],
 }
 
@@ -183,21 +189,27 @@
 java_import {
     name: "mysdk_mydefaultedjavalib@current",
     sdk_member_name: "mydefaultedjavalib",
-    visibility: ["//other/bar:__pkg__"],
+    visibility: [
+        "//other/bar",
+        "//package",
+    ],
     jars: ["java/mydefaultedjavalib.jar"],
 }
 
 java_import {
     name: "mydefaultedjavalib",
     prefer: false,
-    visibility: ["//other/bar:__pkg__"],
+    visibility: [
+        "//other/bar",
+        "//package",
+    ],
     jars: ["java/mydefaultedjavalib.jar"],
 }
 
 sdk_snapshot {
     name: "mysdk@current",
     visibility: [
-        "//other/foo:__pkg__",
+        "//other/foo",
         "//package:__subpackages__",
     ],
     java_header_libs: [