Merge "DO NOT MERGE: Remove AppSearch from Android R." into rvc-dev
diff --git a/android/neverallow.go b/android/neverallow.go
index f0d16b6..73cd6e3 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -103,6 +103,7 @@
 			In("vendor", "device").
 			With("vndk.enabled", "true").
 			Without("vendor", "true").
+			Without("product_specific", "true").
 			Because("the VNDK can never contain a library that is device dependent."),
 		NeverAllow().
 			With("vndk.enabled", "true").
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 0abec0d..9a29687 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -308,7 +308,7 @@
 				}
 
 				if a.installedFilesFile != nil {
-					goal := "droidcore"
+					goal := "checkbuild"
 					distFile := name + "-installed-files.txt"
 					fmt.Fprintln(w, ".PHONY:", goal)
 					fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
diff --git a/apex/apex.go b/apex/apex.go
index 902853a..506a89e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1278,6 +1278,9 @@
 	// rules for making sure that the APEX is truely updatable. This will also disable the size optimizations
 	// like symlinking to the system libs. Default is false.
 	Updatable *bool
+
+	// The minimum SDK version that this apex must be compatible with.
+	Min_sdk_version *string
 }
 
 type apexTargetBundleProperties struct {
@@ -1408,6 +1411,7 @@
 
 	jacocoReportClassesFile android.Path     // only for javalibs and apps
 	certificate             java.Certificate // only for apps
+	overriddenPackageName   string           // only for apps
 }
 
 func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
@@ -1917,6 +1921,12 @@
 	af := newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
 	af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
 	af.certificate = aapp.Certificate()
+
+	if app, ok := aapp.(interface {
+		OverriddenManifestPackageName() string
+	}); ok {
+		af.overriddenPackageName = app.OverriddenManifestPackageName()
+	}
 	return af
 }
 
@@ -2228,7 +2238,8 @@
 						return true // track transitive dependencies
 					}
 				} else if java.IsJniDepTag(depTag) {
-					return true
+					// Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
+					return false
 				} else if java.IsXmlPermissionsFileDepTag(depTag) {
 					if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
 						filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
@@ -2321,6 +2332,11 @@
 		a.linkToSystemLib = false
 	}
 
+	// We also don't want the optimization for host APEXes, because it doesn't make sense.
+	if ctx.Host() {
+		a.linkToSystemLib = false
+	}
+
 	// prepare apex_manifest.json
 	a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e694435..36e7ea7 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -87,6 +87,12 @@
 	}
 }
 
+func withManifestPackageNameOverrides(specs []string) testCustomizer {
+	return func(fs map[string][]byte, config android.Config) {
+		config.TestProductVariables.ManifestPackageNameOverrides = specs
+	}
+}
+
 func withBinder32bit(fs map[string][]byte, config android.Config) {
 	config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
 }
@@ -2889,9 +2895,19 @@
 		cc_library_shared {
 			name: "libjni",
 			srcs: ["mylib.cpp"],
+			shared_libs: ["libfoo"],
 			stl: "none",
 			system_shared_libs: [],
 			apex_available: [ "myapex" ],
+			sdk_version: "current",
+		}
+
+		cc_library_shared {
+			name: "libfoo",
+			stl: "none",
+			system_shared_libs: [],
+			apex_available: [ "myapex" ],
+			sdk_version: "current",
 		}
 	`)
 
@@ -2902,16 +2918,19 @@
 	ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
 	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
 
-	// JNI libraries are embedded inside APK
-	appZipRule := ctx.ModuleForTests("AppFoo", "android_common_myapex").Description("zip jni lib")
-	libjniOutput := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module).OutputFile()
-	ensureListContains(t, appZipRule.Implicits.Strings(), libjniOutput.String())
-	// ... uncompressed
+	appZipRule := ctx.ModuleForTests("AppFoo", "android_common_myapex").Description("zip jni libs")
+	// JNI libraries are uncompressed
 	if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
-		t.Errorf("jni lib is not uncompressed for AppFoo")
+		t.Errorf("jni libs are not uncompressed for AppFoo")
 	}
-	// ... and not directly inside the APEX
-	ensureNotContains(t, copyCmds, "image.apex/lib64/libjni.so")
+	// JNI libraries including transitive deps are
+	for _, jni := range []string{"libjni", "libfoo"} {
+		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module).OutputFile()
+		// ... embedded inside APK (jnilibs.zip)
+		ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
+		// ... and not directly inside the APEX
+		ensureNotContains(t, copyCmds, "image.apex/lib64/"+jni+".so")
+	}
 }
 
 func TestApexWithAppImports(t *testing.T) {
@@ -3253,7 +3272,7 @@
 			base: "app",
 			package_name: "bar",
 		}
-	`)
+	`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
 
 	originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(android.OverridableModule)
 	overriddenVariant := ctx.ModuleForTests("myapex", "android_common_override_myapex_myapex_image").Module().(android.OverridableModule)
@@ -3281,6 +3300,9 @@
 		t.Errorf("override_myapex should have logging parent (com.foo.bar), but was %q.", apexBundle.overridableProperties.Logging_parent)
 	}
 
+	optFlags := apexRule.Args["opt_flags"]
+	ensureContains(t, optFlags, "--override_apk_package_name com.android.myapex")
+
 	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
 	var builder strings.Builder
 	data.Custom(&builder, name, "TARGET_", "", data)
@@ -3596,6 +3618,36 @@
 	ensureRealfileExists(t, files, "lib64/myotherlib.so") // this is a real file
 }
 
+func TestAppBundle(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			apps: ["AppFoo"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		android_app {
+			name: "AppFoo",
+			srcs: ["foo/bar/MyClass.java"],
+			sdk_version: "none",
+			system_modules: "none",
+			apex_available: [ "myapex" ],
+		}
+		`, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"}))
+
+	bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Description("Bundle Config")
+	content := bundleConfigRule.Args["content"]
+
+	ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
+	ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo/AppFoo.apk"}]}`)
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/apex/builder.go b/apex/builder.go
index adb3219..5f4bcd2 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -15,6 +15,7 @@
 package apex
 
 import (
+	"encoding/json"
 	"fmt"
 	"path/filepath"
 	"runtime"
@@ -136,15 +137,18 @@
 		})
 
 	apexBundleRule = pctx.StaticRule("apexBundleRule", blueprint.RuleParams{
-		Command: `${zip2zip} -i $in -o $out ` +
+		Command: `${zip2zip} -i $in -o $out.base ` +
 			`apex_payload.img:apex/${abi}.img ` +
+			`apex_build_info.pb:apex/${abi}.build_info.pb ` +
 			`apex_manifest.json:root/apex_manifest.json ` +
 			`apex_manifest.pb:root/apex_manifest.pb ` +
 			`AndroidManifest.xml:manifest/AndroidManifest.xml ` +
-			`assets/NOTICE.html.gz:assets/NOTICE.html.gz`,
-		CommandDeps: []string{"${zip2zip}"},
+			`assets/NOTICE.html.gz:assets/NOTICE.html.gz &&` +
+			`${soong_zip} -o $out.config -C $$(dirname ${config}) -f ${config} && ` +
+			`${merge_zips} $out $out.base $out.config`,
+		CommandDeps: []string{"${zip2zip}", "${soong_zip}", "${merge_zips}"},
 		Description: "app bundle",
-	}, "abi")
+	}, "abi", "config")
 
 	emitApexContentRule = pctx.StaticRule("emitApexContentRule", blueprint.RuleParams{
 		Command:        `rm -f ${out} && touch ${out} && (. ${out}.emit_commands)`,
@@ -246,6 +250,61 @@
 	return output.OutputPath
 }
 
+func (a *apexBundle) buildBundleConfig(ctx android.ModuleContext) android.OutputPath {
+	output := android.PathForModuleOut(ctx, "bundle_config.json")
+
+	type ApkConfig struct {
+		Package_name string `json:"package_name"`
+		Apk_path     string `json:"path"`
+	}
+	config := struct {
+		Compression struct {
+			Uncompressed_glob []string `json:"uncompressed_glob"`
+		} `json:"compression"`
+		Apex_config struct {
+			Apex_embedded_apk_config []ApkConfig `json:"apex_embedded_apk_config,omitempty"`
+		} `json:"apex_config,omitempty"`
+	}{}
+
+	config.Compression.Uncompressed_glob = []string{
+		"apex_payload.img",
+		"apex_manifest.*",
+	}
+
+	// collect the manifest names and paths of android apps
+	// if their manifest names are overridden
+	for _, fi := range a.filesInfo {
+		if fi.class != app {
+			continue
+		}
+		packageName := fi.overriddenPackageName
+		if packageName != "" {
+			config.Apex_config.Apex_embedded_apk_config = append(
+				config.Apex_config.Apex_embedded_apk_config,
+				ApkConfig{
+					Package_name: packageName,
+					Apk_path:     fi.Path(),
+				})
+		}
+	}
+
+	j, err := json.Marshal(config)
+	if err != nil {
+		panic(fmt.Errorf("error while marshalling to %q: %#v", output, err))
+	}
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Output:      output,
+		Description: "Bundle Config " + output.String(),
+		Args: map[string]string{
+			"content": string(j),
+		},
+	})
+
+	return output.OutputPath
+}
+
 func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
 	var abis []string
 	for _, target := range ctx.MultiTargets() {
@@ -384,21 +443,18 @@
 		targetSdkVersion := ctx.Config().DefaultAppTargetSdk()
 		minSdkVersion := ctx.Config().DefaultAppTargetSdk()
 
+		// TODO: this should be based on min_sdk_version property of an APEX.
 		if proptools.Bool(a.properties.Legacy_android10_support) {
-			if !java.UseApiFingerprint(ctx, targetSdkVersion) {
-				targetSdkVersion = "29"
-			}
-			if !java.UseApiFingerprint(ctx, minSdkVersion) {
-				minSdkVersion = "29"
-			}
+			targetSdkVersion = "29"
+			minSdkVersion = "29"
 		}
 
-		if java.UseApiFingerprint(ctx, targetSdkVersion) {
-			targetSdkVersion += fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
+		if java.UseApiFingerprint(ctx) {
+			targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
 			implicitInputs = append(implicitInputs, java.ApiFingerprintPath(ctx))
 		}
-		if java.UseApiFingerprint(ctx, minSdkVersion) {
-			minSdkVersion += fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
+		if java.UseApiFingerprint(ctx) {
+			minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
 			implicitInputs = append(implicitInputs, java.ApiFingerprintPath(ctx))
 		}
 		optFlags = append(optFlags, "--target_sdk_version "+targetSdkVersion)
@@ -465,13 +521,17 @@
 			Description: "apex proto convert",
 		})
 
+		bundleConfig := a.buildBundleConfig(ctx)
+
 		ctx.Build(pctx, android.BuildParams{
 			Rule:        apexBundleRule,
 			Input:       apexProtoFile,
+			Implicit:    bundleConfig,
 			Output:      a.bundleModuleFile,
 			Description: "apex bundle module",
 			Args: map[string]string{
-				"abi": strings.Join(abis, "."),
+				"abi":    strings.Join(abis, "."),
+				"config": bundleConfig.String(),
 			},
 		})
 	} else {
@@ -587,7 +647,7 @@
 		}
 		return ""
 	}
-	manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(a.Name())
+	manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
 	if overridden {
 		return manifestPackageName
 	}
diff --git a/cc/cc.go b/cc/cc.go
index 5af8459..836de0a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1465,6 +1465,13 @@
 			c.Properties.HideFromMake = false // unhide
 			// Note: this is still non-installable
 		}
+
+		// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current.
+		if i, ok := c.linker.(snapshotLibraryInterface); ok && ctx.DeviceConfig().VndkVersion() == "current" {
+			if isSnapshotAware(ctx, c) {
+				i.collectHeadersForSnapshot(ctx)
+			}
+		}
 	}
 
 	if c.installable() {
@@ -2734,19 +2741,18 @@
 
 	if vndkdep := m.vndkdep; vndkdep != nil {
 		if vndkdep.isVndk() {
-			if productSpecific {
-				mctx.PropertyErrorf("product_specific",
-					"product_specific must not be true when `vndk: {enabled: true}`")
-			}
-			if vendorSpecific {
+			if vendorSpecific || productSpecific {
 				if !vndkdep.isVndkExt() {
 					mctx.PropertyErrorf("vndk",
 						"must set `extends: \"...\"` to vndk extension")
+				} else if m.VendorProperties.Vendor_available != nil {
+					mctx.PropertyErrorf("vendor_available",
+						"must not set at the same time as `vndk: {extends: \"...\"}`")
 				}
 			} else {
 				if vndkdep.isVndkExt() {
 					mctx.PropertyErrorf("vndk",
-						"must set `vendor: true` to set `extends: %q`",
+						"must set `vendor: true` or `product_specific: true` to set `extends: %q`",
 						m.getVndkExtendsModuleName())
 				}
 				if m.VendorProperties.Vendor_available == nil {
@@ -2819,7 +2825,7 @@
 		} else {
 			mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
 		}
-	} else if m.HasVendorVariant() && !vendorSpecific {
+	} else if m.HasVendorVariant() && !m.isVndkExt() {
 		// This will be available in /system, /vendor and /product
 		// or a /system directory that is available to vendor and product.
 		coreVariantNeeded = true
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 30ba733..8acc817 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -218,13 +218,13 @@
 }
 
 func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
-	isVndkSp bool, extends string) {
+	isVndkSp bool, extends string, variant string) {
 
 	t.Helper()
 
-	mod := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
+	mod := ctx.ModuleForTests(name, variant).Module().(*Module)
 	if !mod.HasVendorVariant() {
-		t.Errorf("%q must have vendor variant", name)
+		t.Errorf("%q must have variant %q", name, variant)
 	}
 
 	// Check library properties.
@@ -375,10 +375,10 @@
 
 	ctx := testCcWithConfig(t, config)
 
-	checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
-	checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "")
-	checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
-	checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "")
+	checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "", vendorVariant)
+	checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "", vendorVariant)
+	checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "", vendorVariant)
+	checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "", vendorVariant)
 
 	// Check VNDK snapshot output.
 
@@ -1001,24 +1001,9 @@
 	`)
 }
 
-func TestVndkMustNotBeProductSpecific(t *testing.T) {
-	// Check whether an error is emitted when a vndk lib has 'product_specific: true'.
-	testCcError(t, "product_specific must not be true when `vndk: {enabled: true}`", `
-		cc_library {
-			name: "libvndk",
-			product_specific: true,  // Cause error
-			vendor_available: true,
-			vndk: {
-				enabled: true,
-			},
-			nocrt: true,
-		}
-	`)
-}
-
 func TestVndkExt(t *testing.T) {
 	// This test checks the VNDK-Ext properties.
-	ctx := testCc(t, `
+	bp := `
 		cc_library {
 			name: "libvndk",
 			vendor_available: true,
@@ -1060,12 +1045,42 @@
 			},
 			nocrt: true,
 		}
-	`)
 
-	checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk")
+		cc_library {
+			name: "libvndk_ext_product",
+			product_specific: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk",
+			},
+			nocrt: true,
+		}
 
-	mod := ctx.ModuleForTests("libvndk2_ext", vendorVariant).Module().(*Module)
-	assertString(t, mod.outputFile.Path().Base(), "libvndk2-suffix.so")
+		cc_library {
+			name: "libvndk2_ext_product",
+			product_specific: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk2",
+			},
+			nocrt: true,
+		}
+	`
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+	ctx := testCcWithConfig(t, config)
+
+	checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk", vendorVariant)
+	checkVndkModule(t, ctx, "libvndk_ext_product", "vndk", false, "libvndk", productVariant)
+
+	mod_vendor := ctx.ModuleForTests("libvndk2_ext", vendorVariant).Module().(*Module)
+	assertString(t, mod_vendor.outputFile.Path().Base(), "libvndk2-suffix.so")
+
+	mod_product := ctx.ModuleForTests("libvndk2_ext_product", productVariant).Module().(*Module)
+	assertString(t, mod_product.outputFile.Path().Base(), "libvndk2-suffix.so")
 }
 
 func TestVndkExtWithoutBoardVndkVersion(t *testing.T) {
@@ -1098,9 +1113,39 @@
 	}
 }
 
+func TestVndkExtWithoutProductVndkVersion(t *testing.T) {
+	// This test checks the VNDK-Ext properties when PRODUCT_PRODUCT_VNDK_VERSION is not set.
+	ctx := testCc(t, `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_ext_product",
+			product_specific: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk",
+			},
+			nocrt: true,
+		}
+	`)
+
+	// Ensures that the core variant of "libvndk_ext_product" can be found.
+	mod := ctx.ModuleForTests("libvndk_ext_product", coreVariant).Module().(*Module)
+	if extends := mod.getVndkExtendsModuleName(); extends != "libvndk" {
+		t.Errorf("\"libvndk_ext_product\" must extend from \"libvndk\" but get %q", extends)
+	}
+}
+
 func TestVndkExtError(t *testing.T) {
 	// This test ensures an error is emitted in ill-formed vndk-ext definition.
-	testCcError(t, "must set `vendor: true` to set `extends: \".*\"`", `
+	testCcError(t, "must set `vendor: true` or `product_specific: true` to set `extends: \".*\"`", `
 		cc_library {
 			name: "libvndk",
 			vendor_available: true,
@@ -1139,6 +1184,48 @@
 			nocrt: true,
 		}
 	`)
+
+	testCcErrorProductVndk(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_ext_product",
+			product_specific: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+	`)
+
+	testCcErrorProductVndk(t, "must not set at the same time as `vndk: {extends: \"\\.\\.\\.\"}`", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_ext_product",
+			product_specific: true,
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk",
+			},
+			nocrt: true,
+		}
+	`)
 }
 
 func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
@@ -1211,6 +1298,27 @@
 			nocrt: true,
 		}
 	`)
+
+	testCcErrorProductVndk(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: false,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_ext_product",
+			product_specific: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk",
+			},
+			nocrt: true,
+		}
+	`)
 }
 
 func TestVendorModuleUseVndkExt(t *testing.T) {
@@ -1236,7 +1344,6 @@
 		}
 
 		cc_library {
-
 			name: "libvndk_sp",
 			vendor_available: true,
 			vndk: {
@@ -1328,6 +1435,71 @@
 	`)
 }
 
+func TestProductVndkExtDependency(t *testing.T) {
+	bp := `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_ext_product",
+			product_specific: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk",
+			},
+			shared_libs: ["libproduct_for_vndklibs"],
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_sp_ext_product",
+			product_specific: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk_sp",
+				support_system_process: true,
+			},
+			shared_libs: ["libproduct_for_vndklibs"],
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libproduct",
+			product_specific: true,
+			shared_libs: ["libvndk_ext_product", "libvndk_sp_ext_product"],
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libproduct_for_vndklibs",
+			product_specific: true,
+			nocrt: true,
+		}
+	`
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+	testCcWithConfig(t, config)
+}
+
 func TestVndkSpExtUseVndkError(t *testing.T) {
 	// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK
 	// library.
@@ -1619,8 +1791,8 @@
 
 	ctx := testCcWithConfig(t, config)
 
-	checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
-	checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
+	checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "", productVariant)
+	checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "", productVariant)
 }
 
 func TestEnforceProductVndkVersionErrors(t *testing.T) {
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 1ca1656..19aedd9 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -39,6 +39,7 @@
 	arm64Ldflags = []string{
 		"-Wl,-m,aarch64_elf64_le_vec",
 		"-Wl,--hash-style=gnu",
+		"-Wl,-z,separate-code",
 		"-fuse-ld=gold",
 		"-Wl,--icf=safe",
 	}
diff --git a/cc/library.go b/cc/library.go
index bca9a96..68d7a5f 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -390,6 +390,68 @@
 	*baseCompiler
 	*baseLinker
 	*baseInstaller
+
+	collectedSnapshotHeaders android.Paths
+}
+
+// collectHeadersForSnapshot collects all exported headers from library.
+// It globs header files in the source tree for exported include directories,
+// and tracks generated header files separately.
+//
+// This is to be called from GenerateAndroidBuildActions, and then collected
+// header files can be retrieved by snapshotHeaders().
+func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext) {
+	ret := android.Paths{}
+
+	// Headers in the source tree should be globbed. On the contrast, generated headers
+	// can't be globbed, and they should be manually collected.
+	// So, we first filter out intermediate directories (which contains generated headers)
+	// from exported directories, and then glob headers under remaining directories.
+	for _, path := range append(l.exportedDirs(), l.exportedSystemDirs()...) {
+		dir := path.String()
+		// Skip if dir is for generated headers
+		if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
+			continue
+		}
+		exts := headerExts
+		// Glob all files under this special directory, because of C++ headers.
+		if strings.HasPrefix(dir, "external/libcxx/include") {
+			exts = []string{""}
+		}
+		for _, ext := range exts {
+			glob, err := ctx.GlobWithDeps(dir+"/**/*"+ext, nil)
+			if err != nil {
+				ctx.ModuleErrorf("glob failed: %#v", err)
+				return
+			}
+			for _, header := range glob {
+				if strings.HasSuffix(header, "/") {
+					continue
+				}
+				ret = append(ret, android.PathForSource(ctx, header))
+			}
+		}
+	}
+
+	// Collect generated headers
+	for _, header := range append(l.exportedGeneratedHeaders(), l.exportedDeps()...) {
+		// TODO(b/148123511): remove exportedDeps after cleaning up genrule
+		if strings.HasSuffix(header.Base(), "-phony") {
+			continue
+		}
+		ret = append(ret, header)
+	}
+
+	l.collectedSnapshotHeaders = ret
+}
+
+// This returns all exported header files, both generated ones and headers from source tree.
+// collectHeadersForSnapshot() must be called before calling this.
+func (l *libraryDecorator) snapshotHeaders() android.Paths {
+	if l.collectedSnapshotHeaders == nil {
+		panic("snapshotHeaders() must be called after collectHeadersForSnapshot()")
+	}
+	return l.collectedSnapshotHeaders
 }
 
 func (library *libraryDecorator) linkerProps() []interface{} {
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 8f48f86..26e7c8d 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -14,8 +14,6 @@
 package cc
 
 import (
-	"strings"
-
 	"android/soong/android"
 )
 
@@ -26,6 +24,8 @@
 type snapshotLibraryInterface interface {
 	exportedFlagsProducer
 	libraryInterface
+	collectHeadersForSnapshot(ctx android.ModuleContext)
+	snapshotHeaders() android.Paths
 }
 
 var _ snapshotLibraryInterface = (*prebuiltLibraryLinker)(nil)
@@ -58,49 +58,13 @@
 	return snapshot, found
 }
 
-func exportedHeaders(ctx android.SingletonContext, l exportedFlagsProducer) android.Paths {
-	var ret android.Paths
-
-	// Headers in the source tree should be globbed. On the contrast, generated headers
-	// can't be globbed, and they should be manually collected.
-	// So, we first filter out intermediate directories (which contains generated headers)
-	// from exported directories, and then glob headers under remaining directories.
-	for _, path := range append(l.exportedDirs(), l.exportedSystemDirs()...) {
-		dir := path.String()
-		// Skip if dir is for generated headers
-		if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
-			continue
-		}
-		exts := headerExts
-		// Glob all files under this special directory, because of C++ headers.
-		if strings.HasPrefix(dir, "external/libcxx/include") {
-			exts = []string{""}
-		}
-		for _, ext := range exts {
-			glob, err := ctx.GlobWithDeps(dir+"/**/*"+ext, nil)
-			if err != nil {
-				ctx.Errorf("%#v\n", err)
-				return nil
-			}
-			for _, header := range glob {
-				if strings.HasSuffix(header, "/") {
-					continue
-				}
-				ret = append(ret, android.PathForSource(ctx, header))
-			}
-		}
+func isSnapshotAware(ctx android.ModuleContext, m *Module) bool {
+	if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m); ok {
+		return ctx.Config().VndkSnapshotBuildArtifacts()
+	} else if isVendorSnapshotModule(m, ctx.ModuleDir()) {
+		return true
 	}
-
-	// Collect generated headers
-	for _, header := range append(l.exportedGeneratedHeaders(), l.exportedDeps()...) {
-		// TODO(b/148123511): remove exportedDeps after cleaning up genrule
-		if strings.HasSuffix(header.Base(), "-phony") {
-			continue
-		}
-		ret = append(ret, header)
-	}
-
-	return ret
+	return false
 }
 
 func copyFile(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index aed7918..c79a653 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -428,12 +428,12 @@
 // AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
 // depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
 // image and newer system image altogether.
-func isVendorSnapshotModule(ctx android.SingletonContext, m *Module) bool {
+func isVendorSnapshotModule(m *Module, moduleDir string) bool {
 	if !m.Enabled() {
 		return false
 	}
 	// skip proprietary modules, but include all VNDK (static)
-	if isVendorProprietaryPath(ctx.ModuleDir(m)) && !m.IsVndk() {
+	if isVendorProprietaryPath(moduleDir) && !m.IsVndk() {
 		return false
 	}
 	if m.Target().Os.Class != android.Device {
@@ -525,14 +525,6 @@
 
 	var headers android.Paths
 
-	type vendorSnapshotLibraryInterface interface {
-		exportedFlagsProducer
-		libraryInterface
-	}
-
-	var _ vendorSnapshotLibraryInterface = (*prebuiltLibraryLinker)(nil)
-	var _ vendorSnapshotLibraryInterface = (*libraryDecorator)(nil)
-
 	installSnapshot := func(m *Module) android.Paths {
 		targetArch := "arch-" + m.Target().Arch.ArchType.String()
 		if m.Target().Arch.ArchVariant != "" {
@@ -588,7 +580,7 @@
 
 		var propOut string
 
-		if l, ok := m.linker.(vendorSnapshotLibraryInterface); ok {
+		if l, ok := m.linker.(snapshotLibraryInterface); ok {
 			// library flags
 			prop.ExportedFlags = l.exportedFlags()
 			for _, dir := range l.exportedDirs() {
@@ -652,13 +644,18 @@
 
 	ctx.VisitAllModules(func(module android.Module) {
 		m, ok := module.(*Module)
-		if !ok || !isVendorSnapshotModule(ctx, m) {
+		if !ok {
+			return
+		}
+
+		moduleDir := ctx.ModuleDir(module)
+		if !isVendorSnapshotModule(m, moduleDir) {
 			return
 		}
 
 		snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...)
-		if l, ok := m.linker.(vendorSnapshotLibraryInterface); ok {
-			headers = append(headers, exportedHeaders(ctx, l)...)
+		if l, ok := m.linker.(snapshotLibraryInterface); ok {
+			headers = append(headers, l.snapshotHeaders()...)
 		}
 
 		if m.NoticeFile().Valid() {
diff --git a/cc/vndk.go b/cc/vndk.go
index 4578a7d..6fef699 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -496,6 +496,28 @@
 	vndkSnapshotZipFile android.OptionalPath
 }
 
+func isVndkSnapshotLibrary(config android.DeviceConfig, m *Module) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) {
+	if m.Target().NativeBridge == android.NativeBridgeEnabled {
+		return nil, "", false
+	}
+	if !m.inVendor() || !m.installable() || m.isSnapshotPrebuilt() {
+		return nil, "", false
+	}
+	l, ok := m.linker.(snapshotLibraryInterface)
+	if !ok || !l.shared() {
+		return nil, "", false
+	}
+	if m.VndkVersion() == config.PlatformVndkVersion() && m.IsVndk() && !m.isVndkExt() {
+		if m.isVndkSp() {
+			return l, "vndk-sp", true
+		} else {
+			return l, "vndk-core", true
+		}
+	}
+
+	return nil, "", false
+}
+
 func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 	// build these files even if PlatformVndkVersion or BoardVndkVersion is not set
 	c.buildVndkLibrariesTxtFiles(ctx)
@@ -598,35 +620,13 @@
 		return ret, true
 	}
 
-	isVndkSnapshotLibrary := func(m *Module) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) {
-		if m.Target().NativeBridge == android.NativeBridgeEnabled {
-			return nil, "", false
-		}
-		if !m.inVendor() || !m.installable() || m.isSnapshotPrebuilt() {
-			return nil, "", false
-		}
-		l, ok := m.linker.(snapshotLibraryInterface)
-		if !ok || !l.shared() {
-			return nil, "", false
-		}
-		if m.VndkVersion() == ctx.DeviceConfig().PlatformVndkVersion() && m.IsVndk() && !m.isVndkExt() {
-			if m.isVndkSp() {
-				return l, "vndk-sp", true
-			} else {
-				return l, "vndk-core", true
-			}
-		}
-
-		return nil, "", false
-	}
-
 	ctx.VisitAllModules(func(module android.Module) {
 		m, ok := module.(*Module)
 		if !ok || !m.Enabled() {
 			return
 		}
 
-		l, vndkType, ok := isVndkSnapshotLibrary(m)
+		l, vndkType, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m)
 		if !ok {
 			return
 		}
@@ -655,7 +655,7 @@
 		}
 
 		if ctx.Config().VndkSnapshotBuildArtifacts() {
-			headers = append(headers, exportedHeaders(ctx, l)...)
+			headers = append(headers, l.snapshotHeaders()...)
 		}
 	})
 
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 9a71be2..8280cb1 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -99,8 +99,8 @@
 	if err != nil {
 		ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
 	}
-	if UseApiFingerprint(ctx, targetSdkVersion) {
-		targetSdkVersion += fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
+	if UseApiFingerprint(ctx) {
+		targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
 		deps = append(deps, ApiFingerprintPath(ctx))
 	}
 
@@ -108,8 +108,8 @@
 	if err != nil {
 		ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
 	}
-	if UseApiFingerprint(ctx, minSdkVersion) {
-		minSdkVersion += fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
+	if UseApiFingerprint(ctx) {
+		minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
 		deps = append(deps, ApiFingerprintPath(ctx))
 	}
 
diff --git a/java/app.go b/java/app.go
index bcf08a7..bfa25a2 100755
--- a/java/app.go
+++ b/java/app.go
@@ -147,6 +147,8 @@
 	additionalAaptFlags []string
 
 	noticeOutputs android.NoticeOutputs
+
+	overriddenManifestPackageName string
 }
 
 func (a *AndroidApp) IsInstallable() bool {
@@ -271,6 +273,10 @@
 		!a.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
 }
 
+func (a *AndroidApp) OverriddenManifestPackageName() string {
+	return a.overriddenManifestPackageName
+}
+
 func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
 	a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
 
@@ -304,6 +310,7 @@
 			manifestPackageName = *a.overridableAppProperties.Package_name
 		}
 		aaptLinkFlags = append(aaptLinkFlags, "--rename-manifest-package "+manifestPackageName)
+		a.overriddenManifestPackageName = manifestPackageName
 	}
 
 	aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
diff --git a/java/config/config.go b/java/config/config.go
index 03588dc..487dc04 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -50,7 +50,7 @@
 		"updatable-media",
 		"framework-mediaprovider",
 		"framework-sdkextensions",
-		"ike",
+		"android.net.ipsec.ike",
 	}
 )
 
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 6020aba..8f34714 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -159,9 +159,21 @@
 		tmpOutput = android.PathForModuleOut(ctx, "hiddenapi", "unaligned", "unaligned.jar")
 		tmpDir = android.PathForModuleOut(ctx, "hiddenapi", "unaligned")
 	}
+
+	enforceHiddenApiFlagsToAllMembers := true
 	// If frameworks/base doesn't exist we must be building with the 'master-art' manifest.
 	// Disable assertion that all methods/fields have hidden API flags assigned.
 	if !ctx.Config().FrameworksBaseDirExists(ctx) {
+		enforceHiddenApiFlagsToAllMembers = false
+	}
+	// b/149353192: when a module is instrumented, jacoco adds synthetic members
+	// $jacocoData and $jacocoInit. Since they don't exist when building the hidden API flags,
+	// don't complain when we don't find hidden API flags for the synthetic members.
+	if j, ok := ctx.Module().(*Library); ok && j.shouldInstrument(ctx) {
+		enforceHiddenApiFlagsToAllMembers = false
+	}
+
+	if !enforceHiddenApiFlagsToAllMembers {
 		hiddenapiFlags = "--no-force-assign-all"
 	}
 
diff --git a/java/java.go b/java/java.go
index c89784a..8d58a90 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1521,6 +1521,14 @@
 		j.headerJarFile = j.implementationJarFile
 	}
 
+	// Force enable the instrumentation for java code that is built for APEXes ...
+	// except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
+	// doesn't make sense)
+	isJacocoAgent := ctx.ModuleName() == "jacocoagent"
+	if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() {
+		j.properties.Instrument = true
+	}
+
 	if j.shouldInstrument(ctx) {
 		outputFile = j.instrument(ctx, flags, outputFile, jarName)
 	}
diff --git a/java/sdk.go b/java/sdk.go
index 1e60d67..20a0772 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -50,9 +50,8 @@
 	targetSdkVersion() sdkSpec
 }
 
-func UseApiFingerprint(ctx android.BaseModuleContext, v string) bool {
-	if v == ctx.Config().PlatformSdkCodename() &&
-		ctx.Config().UnbundledBuild() &&
+func UseApiFingerprint(ctx android.BaseModuleContext) bool {
+	if ctx.Config().UnbundledBuild() &&
 		!ctx.Config().UnbundledBuildUsePrebuiltSdks() &&
 		ctx.Config().IsEnvTrue("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT") {
 		return true