Merge "Re-plumb fuzz corpora."
diff --git a/android/apex.go b/android/apex.go
index d3c0710..5118a0a 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -77,6 +77,10 @@
 
 	// Tests if this module is available for the specified APEX or ":platform"
 	AvailableFor(what string) bool
+
+	// DepIsInSameApex tests if the other module 'dep' is installed to the same
+	// APEX as this module
+	DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
 }
 
 type ApexProperties struct {
@@ -154,6 +158,13 @@
 	return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
 }
 
+func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
+	// By default, if there is a dependency from A to B, we try to include both in the same APEX,
+	// unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning true.
+	// This is overridden by some module types like apex.ApexBundle, cc.Module, java.Module, etc.
+	return true
+}
+
 func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
 	for _, n := range m.ApexProperties.Apex_available {
 		if n == availableToPlatform || n == availableToAnyApex {
diff --git a/android/sdk.go b/android/sdk.go
index 616fbe1..8e1e106 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -44,6 +44,17 @@
 	return s.Version == ""
 }
 
+// String returns string representation of this SdkRef for debugging purpose
+func (s SdkRef) String() string {
+	if s.Name == "" {
+		return "(No Sdk)"
+	}
+	if s.Unversioned() {
+		return s.Name
+	}
+	return s.Name + string(SdkVersionSeparator) + s.Version
+}
+
 // SdkVersionSeparator is a character used to separate an sdk name and its version
 const SdkVersionSeparator = '@'
 
diff --git a/apex/apex.go b/apex/apex.go
index 8a29ef0..c9b989a 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -786,6 +786,11 @@
 	}
 }
 
+func (a *apexBundle) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	// direct deps of an APEX bundle are all part of the APEX bundle
+	return true
+}
+
 func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
 	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
 	if overridden {
@@ -967,7 +972,11 @@
 }
 
 func getCopyManifestForAndroidApp(app *java.AndroidApp, pkgName string) (fileToCopy android.Path, dirInApex string) {
-	dirInApex = filepath.Join("app", pkgName)
+	appDir := "app"
+	if app.Privileged() {
+		appDir = "priv-app"
+	}
+	dirInApex = filepath.Join(appDir, pkgName)
 	fileToCopy = app.OutputFile()
 	return
 }
diff --git a/apex/apex_test.go b/apex/apex_test.go
index d1cd969..7a51bb6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2232,6 +2232,7 @@
 			key: "myapex.key",
 			apps: [
 				"AppFoo",
+				"AppFooPriv",
 			],
 		}
 
@@ -2247,6 +2248,14 @@
 			sdk_version: "none",
 			system_modules: "none",
 		}
+
+		android_app {
+			name: "AppFooPriv",
+			srcs: ["foo/bar/MyClass.java"],
+			sdk_version: "none",
+			system_modules: "none",
+			privileged: true,
+		}
 	`)
 
 	module := ctx.ModuleForTests("myapex", "android_common_myapex")
@@ -2254,6 +2263,7 @@
 	copyCmds := apexRule.Args["copy_commands"]
 
 	ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
+	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
 
 }
 
diff --git a/cc/cc.go b/cc/cc.go
index c432239..806a6ed 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2194,6 +2194,16 @@
 	}
 }
 
+func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	if depTag, ok := ctx.OtherModuleDependencyTag(dep).(dependencyTag); ok {
+		if cc, ok := dep.(*Module); ok && cc.IsStubs() && depTag.shared {
+			// dynamic dep to a stubs lib crosses APEX boundary
+			return false
+		}
+	}
+	return true
+}
+
 //
 // Defaults
 //
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index d7d8955..3e8abac 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -65,6 +65,7 @@
 	"android.hardware.neuralnetworks@1.0",
 	"android.hardware.neuralnetworks@1.1",
 	"android.hardware.neuralnetworks@1.2",
+	"android.hardware.neuralnetworks@1.3",
 	"android.hardware.nfc@1.0",
 	"android.hardware.nfc@1.1",
 	"android.hardware.nfc@1.2",
diff --git a/cc/testing.go b/cc/testing.go
index 11a5e3b..6fa6ea7 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -190,6 +190,7 @@
 			name: "crtbegin_so",
 			recovery_available: true,
 			vendor_available: true,
+			stl: "none",
 		}
 
 		cc_object {
@@ -208,6 +209,7 @@
 			name: "crtend_so",
 			recovery_available: true,
 			vendor_available: true,
+			stl: "none",
 		}
 
 		cc_object {
diff --git a/java/androidmk.go b/java/androidmk.go
index 955f22b..7927acf 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -317,7 +317,7 @@
 
 				entries.SetPath("LOCAL_FULL_MANIFEST_FILE", app.manifestPath)
 
-				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", Bool(app.appProperties.Privileged))
+				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", app.Privileged())
 
 				entries.SetPath("LOCAL_CERTIFICATE", app.certificate.Pem)
 				entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", app.getOverriddenPackages()...)
@@ -630,7 +630,7 @@
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(entries *android.AndroidMkEntries) {
-				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", Bool(a.properties.Privileged))
+				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", a.Privileged())
 				if a.certificate != nil {
 					entries.SetPath("LOCAL_CERTIFICATE", a.certificate.Pem)
 				} else {
diff --git a/java/app.go b/java/app.go
index 6b640f1..3dbcbf4 100644
--- a/java/app.go
+++ b/java/app.go
@@ -228,7 +228,7 @@
 
 	// Uncompress dex in APKs of privileged apps (even for unbundled builds, they may
 	// be preinstalled as prebuilts).
-	if ctx.Config().UncompressPrivAppDex() && Bool(a.appProperties.Privileged) {
+	if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
 		return true
 	}
 
@@ -316,7 +316,7 @@
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
 		installDir = "framework"
-	} else if Bool(a.appProperties.Privileged) {
+	} else if a.Privileged() {
 		installDir = filepath.Join("priv-app", a.installApkName)
 	} else {
 		installDir = filepath.Join("app", a.installApkName)
@@ -442,7 +442,7 @@
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
 		a.installDir = android.PathForModuleInstall(ctx, "framework")
-	} else if Bool(a.appProperties.Privileged) {
+	} else if a.Privileged() {
 		a.installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
 	} else if ctx.InstallInTestcases() {
 		a.installDir = android.PathForModuleInstall(ctx, a.installApkName)
@@ -555,6 +555,10 @@
 	return a.Library.OutputFiles(tag)
 }
 
+func (a *AndroidApp) Privileged() bool {
+	return Bool(a.appProperties.Privileged)
+}
+
 // android_app compiles sources and Android resources into an Android application package `.apk` file.
 func AndroidAppFactory() android.Module {
 	module := &AndroidApp{}
@@ -872,7 +876,7 @@
 	}
 
 	// Uncompress dex in APKs of privileged apps
-	if ctx.Config().UncompressPrivAppDex() && Bool(a.properties.Privileged) {
+	if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
 		return true
 	}
 
@@ -1003,6 +1007,10 @@
 	a.AddProperties(a.archVariants)
 }
 
+func (a *AndroidAppImport) Privileged() bool {
+	return Bool(a.properties.Privileged)
+}
+
 func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
 	props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
 
diff --git a/java/java.go b/java/java.go
index 3b95f1e..0aef69e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1565,6 +1565,12 @@
 	return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
 }
 
+func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	depTag := ctx.OtherModuleDependencyTag(dep)
+	// dependencies other than the static linkage are all considered crossing APEX boundary
+	return depTag == staticLibTag
+}
+
 //
 // Java libraries (.jar file)
 //
diff --git a/sdk/sdk.go b/sdk/sdk.go
index e4d520b..d189043 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -122,6 +122,7 @@
 	// should have been mutated for the apex before the SDK requirements are set.
 	ctx.TopDown("SdkDepsMutator", sdkDepsMutator).Parallel()
 	ctx.BottomUp("SdkDepsReplaceMutator", sdkDepsReplaceMutator).Parallel()
+	ctx.TopDown("SdkRequirementCheck", sdkRequirementsMutator).Parallel()
 }
 
 type dependencyTag struct {
@@ -228,3 +229,31 @@
 		}
 	}
 }
+
+// Step 6: ensure that the dependencies from outside of the APEX are all from the required SDKs
+func sdkRequirementsMutator(mctx android.TopDownMutatorContext) {
+	if m, ok := mctx.Module().(interface {
+		DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool
+		RequiredSdks() android.SdkRefs
+	}); ok {
+		requiredSdks := m.RequiredSdks()
+		if len(requiredSdks) == 0 {
+			return
+		}
+		mctx.VisitDirectDeps(func(dep android.Module) {
+			if mctx.OtherModuleDependencyTag(dep) == android.DefaultsDepTag {
+				// dependency to defaults is always okay
+				return
+			}
+
+			// If the dep is from outside of the APEX, but is not in any of the
+			// required SDKs, we know that the dep is a violation.
+			if sa, ok := dep.(android.SdkAware); ok {
+				if !m.DepIsInSameApex(mctx, dep) && !requiredSdks.Contains(sa.ContainingSdk()) {
+					mctx.ModuleErrorf("depends on %q (in SDK %q) that isn't part of the required SDKs: %v",
+						sa.Name(), sa.ContainingSdk(), requiredSdks)
+				}
+			}
+		})
+	}
+}
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 942556a..664bb7c 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -115,6 +115,23 @@
 	return ctx, config
 }
 
+func testSdkError(t *testing.T, pattern, bp string) {
+	t.Helper()
+	ctx, config := testSdkContext(t, bp)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+	_, errs = ctx.PrepareBuildActions(config)
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+
+	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+}
+
 // ensure that 'result' contains 'expected'
 func ensureContains(t *testing.T, result string, expected string) {
 	t.Helper()
@@ -303,6 +320,63 @@
 	ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
 }
 
+func TestDepNotInRequiredSdks(t *testing.T) {
+	testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
+		sdk {
+			name: "mysdk",
+			java_libs: ["sdkmember"],
+		}
+
+		sdk_snapshot {
+			name: "mysdk@1",
+			java_libs: ["sdkmember_mysdk_1"],
+		}
+
+		java_import {
+			name: "sdkmember",
+			prefer: false,
+			host_supported: true,
+		}
+
+		java_import {
+			name: "sdkmember_mysdk_1",
+			sdk_member_name: "sdkmember",
+			host_supported: true,
+		}
+
+		java_library {
+			name: "myjavalib",
+			srcs: ["Test.java"],
+			libs: [
+				"sdkmember",
+				"otherlib",
+			],
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+			host_supported: true,
+		}
+
+		// this lib is no in mysdk
+		java_library {
+			name: "otherlib",
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+			host_supported: true,
+		}
+
+		apex {
+			name: "myapex",
+			java_libs: ["myjavalib"],
+			uses_sdks: ["mysdk@1"],
+			key: "myapex.key",
+			certificate: ":myapex.cert",
+		}
+	`)
+}
+
 var buildDir string
 
 func setUp() {