Merge "Make prebuilt_sdk support module-lib and system-server"
diff --git a/android/apex.go b/android/apex.go
index f9350d1..9056c3d 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"sort"
 	"strconv"
+	"strings"
 	"sync"
 
 	"github.com/google/blueprint"
@@ -403,3 +404,85 @@
 
 	m.AddProperties(&base.ApexProperties)
 }
+
+// A dependency info for a single ApexModule, either direct or transitive.
+type ApexModuleDepInfo struct {
+	// Name of the dependency
+	To string
+	// List of dependencies To belongs to. Includes APEX itself, if a direct dependency.
+	From []string
+	// Whether the dependency belongs to the final compiled APEX.
+	IsExternal bool
+	// min_sdk_version of the ApexModule
+	MinSdkVersion string
+}
+
+// A map of a dependency name to its ApexModuleDepInfo
+type DepNameToDepInfoMap map[string]ApexModuleDepInfo
+
+type ApexBundleDepsInfo struct {
+	minSdkVersion string
+	flatListPath  OutputPath
+	fullListPath  OutputPath
+}
+
+type ApexDepsInfoIntf interface {
+	MinSdkVersion() string
+	FlatListPath() Path
+	FullListPath() Path
+}
+
+func (d *ApexBundleDepsInfo) MinSdkVersion() string {
+	return d.minSdkVersion
+}
+
+func (d *ApexBundleDepsInfo) FlatListPath() Path {
+	return d.flatListPath
+}
+
+func (d *ApexBundleDepsInfo) FullListPath() Path {
+	return d.fullListPath
+}
+
+var _ ApexDepsInfoIntf = (*ApexBundleDepsInfo)(nil)
+
+// Generate two module out files:
+// 1. FullList with transitive deps and their parents in the dep graph
+// 2. FlatList with a flat list of transitive deps
+func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) {
+	d.minSdkVersion = minSdkVersion
+
+	var fullContent strings.Builder
+	var flatContent strings.Builder
+
+	fmt.Fprintf(&flatContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion)
+	for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) {
+		info := depInfos[key]
+		toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion)
+		if info.IsExternal {
+			toName = toName + " (external)"
+		}
+		fmt.Fprintf(&fullContent, "%s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", "))
+		fmt.Fprintf(&flatContent, "  %s\\n", toName)
+	}
+
+	d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath
+	ctx.Build(pctx, BuildParams{
+		Rule:        WriteFile,
+		Description: "Full Dependency Info",
+		Output:      d.fullListPath,
+		Args: map[string]string{
+			"content": fullContent.String(),
+		},
+	})
+
+	d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
+	ctx.Build(pctx, BuildParams{
+		Rule:        WriteFile,
+		Description: "Flat Dependency Info",
+		Output:      d.flatListPath,
+		Args: map[string]string{
+			"content": flatContent.String(),
+		},
+	})
+}
diff --git a/android/defaults.go b/android/defaults.go
index fd707a4..6a908ea 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -176,18 +176,18 @@
 	defaultsVisibility := module.defaultsVisibility()
 	module.AddProperties(&base.nameProperties, defaultsVisibility)
 
-	// The defaults_visibility property controls the visibility of a defaults module.
-	base.primaryVisibilityProperty =
-		newVisibilityProperty("defaults_visibility", &defaultsVisibility.Defaults_visibility)
-
 	// Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
-	// Instead it is stored in a separate instance of commonProperties created above so use that.
+	// Instead it is stored in a separate instance of commonProperties created above so clear the
+	// existing list of properties.
+	clearVisibilityProperties(module)
+
+	// The defaults_visibility property controls the visibility of a defaults module so it must be
+	// set as the primary property, which also adds it to the list.
+	setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility)
+
 	// The visibility property needs to be checked (but not parsed) by the visibility module during
-	// its checking phase and parsing phase.
-	base.visibilityPropertyInfo = []visibilityProperty{
-		base.primaryVisibilityProperty,
-		newVisibilityProperty("visibility", &commonProperties.Visibility),
-	}
+	// its checking phase and parsing phase so add it to the list as a normal property.
+	AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
 
 	base.module = module
 }
diff --git a/android/module.go b/android/module.go
index 02b2c89..f5cfe66 100644
--- a/android/module.go
+++ b/android/module.go
@@ -611,10 +611,8 @@
 	base.customizableProperties = m.GetProperties()
 
 	// The default_visibility property needs to be checked and parsed by the visibility module during
-	// its checking and parsing phases.
-	base.primaryVisibilityProperty =
-		newVisibilityProperty("visibility", &base.commonProperties.Visibility)
-	base.visibilityPropertyInfo = []visibilityProperty{base.primaryVisibilityProperty}
+	// its checking and parsing phases so make it the primary visibility property.
+	setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility)
 }
 
 func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
diff --git a/android/package.go b/android/package.go
index 077c4a4..bb5f4e7 100644
--- a/android/package.go
+++ b/android/package.go
@@ -101,10 +101,8 @@
 	module.AddProperties(&module.properties)
 
 	// The default_visibility property needs to be checked and parsed by the visibility module during
-	// its checking and parsing phases.
-	module.primaryVisibilityProperty =
-		newVisibilityProperty("default_visibility", &module.properties.Default_visibility)
-	module.visibilityPropertyInfo = []visibilityProperty{module.primaryVisibilityProperty}
+	// its checking and parsing phases so make it the primary visibility property.
+	setPrimaryVisibilityProperty(module, "default_visibility", &module.properties.Default_visibility)
 
 	return module
 }
diff --git a/android/visibility.go b/android/visibility.go
index 3f04123..1e3b91d 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -246,14 +246,8 @@
 	}
 
 	for _, v := range visibility {
-		ok, pkg, name := splitRule(v, currentPkg)
+		ok, pkg, name := splitRule(ctx, v, currentPkg, property)
 		if !ok {
-			// Visibility rule is invalid so ignore it. Keep going rather than aborting straight away to
-			// ensure all the rules on this module are checked.
-			ctx.PropertyErrorf(property,
-				"invalid visibility pattern %q must match"+
-					" //<package>:<module>, //<package> or :<module>",
-				v)
 			continue
 		}
 
@@ -301,21 +295,24 @@
 
 	// Parse the visibility rules that control access to the module and store them by id
 	// for use when enforcing the rules.
-	if visibility := m.visibility(); visibility != nil {
-		rule := parseRules(ctx, currentPkg, m.visibility())
-		if rule != nil {
-			moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, rule)
+	primaryProperty := m.base().primaryVisibilityProperty
+	if primaryProperty != nil {
+		if visibility := primaryProperty.getStrings(); visibility != nil {
+			rule := parseRules(ctx, currentPkg, primaryProperty.getName(), visibility)
+			if rule != nil {
+				moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, rule)
+			}
 		}
 	}
 }
 
-func parseRules(ctx BaseModuleContext, currentPkg string, visibility []string) compositeRule {
+func parseRules(ctx BaseModuleContext, currentPkg, property string, visibility []string) compositeRule {
 	rules := make(compositeRule, 0, len(visibility))
 	hasPrivateRule := false
 	hasPublicRule := false
 	hasNonPrivateRule := false
 	for _, v := range visibility {
-		ok, pkg, name := splitRule(v, currentPkg)
+		ok, pkg, name := splitRule(ctx, v, currentPkg, property)
 		if !ok {
 			continue
 		}
@@ -376,10 +373,16 @@
 	return !isAncestor("vendor", pkg)
 }
 
-func splitRule(ruleExpression string, currentPkg string) (bool, string, string) {
+func splitRule(ctx BaseModuleContext, ruleExpression string, currentPkg, property string) (bool, string, string) {
 	// Make sure that the rule is of the correct format.
 	matches := visibilityRuleRegexp.FindStringSubmatch(ruleExpression)
 	if ruleExpression == "" || matches == nil {
+		// Visibility rule is invalid so ignore it. Keep going rather than aborting straight away to
+		// ensure all the rules on this module are checked.
+		ctx.PropertyErrorf(property,
+			"invalid visibility pattern %q must match"+
+				" //<package>:<module>, //<package> or :<module>",
+			ruleExpression)
 		return false, "", ""
 	}
 
@@ -480,3 +483,28 @@
 
 	return rule.Strings()
 }
+
+// Clear the default visibility properties so they can be replaced.
+func clearVisibilityProperties(module Module) {
+	module.base().visibilityPropertyInfo = nil
+}
+
+// Add a property that contains visibility rules so that they are checked for
+// correctness.
+func AddVisibilityProperty(module Module, name string, stringsProperty *[]string) {
+	addVisibilityProperty(module, name, stringsProperty)
+}
+
+func addVisibilityProperty(module Module, name string, stringsProperty *[]string) visibilityProperty {
+	base := module.base()
+	property := newVisibilityProperty(name, stringsProperty)
+	base.visibilityPropertyInfo = append(base.visibilityPropertyInfo, property)
+	return property
+}
+
+// Set the primary visibility property.
+//
+// Also adds the property to the list of properties to be validated.
+func setPrimaryVisibilityProperty(module Module, name string, stringsProperty *[]string) {
+	module.base().primaryVisibilityProperty = addVisibilityProperty(module, name, stringsProperty)
+}
diff --git a/apex/apex.go b/apex/apex.go
index 7b4f8ff..d196e95 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1276,12 +1276,6 @@
 	return false
 }
 
-type depInfo struct {
-	to         string
-	from       []string
-	isExternal bool
-}
-
 type apexBundle struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
@@ -1316,7 +1310,7 @@
 	requiredDeps []string
 
 	// list of module names that this APEX is including (to be shown via *-deps-info target)
-	depInfos map[string]depInfo
+	android.ApexBundleDepsInfo
 
 	testApex        bool
 	vndkApex        bool
@@ -1885,38 +1879,11 @@
 		if String(a.properties.Min_sdk_version) == "" {
 			ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
 		}
+
+		a.checkJavaStableSdkVersion(ctx)
 	}
 }
 
-// Collects the list of module names that directly or indirectly contributes to the payload of this APEX
-func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
-	a.depInfos = make(map[string]depInfo)
-	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
-		if from.Name() == to.Name() {
-			// This can happen for cc.reuseObjTag. We are not interested in tracking this.
-			// As soon as the dependency graph crosses the APEX boundary, don't go further.
-			return !externalDep
-		}
-
-		if info, exists := a.depInfos[to.Name()]; exists {
-			if !android.InList(from.Name(), info.from) {
-				info.from = append(info.from, from.Name())
-			}
-			info.isExternal = info.isExternal && externalDep
-			a.depInfos[to.Name()] = info
-		} else {
-			a.depInfos[to.Name()] = depInfo{
-				to:         to.Name(),
-				from:       []string{from.Name()},
-				isExternal: externalDep,
-			}
-		}
-
-		// As soon as the dependency graph crosses the APEX boundary, don't go further.
-		return !externalDep
-	})
-}
-
 func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
 	switch a.properties.ApexType {
@@ -1955,8 +1922,6 @@
 	a.checkApexAvailability(ctx)
 	a.checkUpdatable(ctx)
 
-	a.collectDepsInfo(ctx)
-
 	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
 
 	// native lib dependencies
@@ -2274,6 +2239,23 @@
 	a.buildApexDependencyInfo(ctx)
 }
 
+// Enforce that Java deps of the apex are using stable SDKs to compile
+func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
+	// Visit direct deps only. As long as we guarantee top-level deps are using
+	// stable SDKs, java's checkLinkType guarantees correct usage for transitive deps
+	ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+		tag := ctx.OtherModuleDependencyTag(module)
+		switch tag {
+		case javaLibTag, androidAppTag:
+			if m, ok := module.(interface{ CheckStableSdkVersion() error }); ok {
+				if err := m.CheckStableSdkVersion(); err != nil {
+					ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err)
+				}
+			}
+		}
+	})
+}
+
 func whitelistedApexAvailable(apex, moduleName string) bool {
 	key := apex
 	moduleName = normalizeModuleName(moduleName)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ec5268f..ce39b39 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -504,12 +504,19 @@
 	ensureListContains(t, noticeInputs, "custom_notice")
 	ensureListContains(t, noticeInputs, "custom_notice_for_static_lib")
 
-	depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("myapex-deps-info.txt").Args["content"], "\\n")
-	ensureListContains(t, depsInfo, "myjar <- myapex")
-	ensureListContains(t, depsInfo, "mylib <- myapex")
-	ensureListContains(t, depsInfo, "mylib2 <- mylib")
-	ensureListContains(t, depsInfo, "myotherjar <- myjar")
-	ensureListContains(t, depsInfo, "mysharedjar (external) <- myjar")
+	fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
+	ensureListContains(t, fullDepsInfo, "myjar(minSdkVersion:(no version)) <- myapex")
+	ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex")
+	ensureListContains(t, fullDepsInfo, "mylib2(minSdkVersion:(no version)) <- mylib")
+	ensureListContains(t, fullDepsInfo, "myotherjar(minSdkVersion:(no version)) <- myjar")
+	ensureListContains(t, fullDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external) <- myjar")
+
+	flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
+	ensureListContains(t, flatDepsInfo, "  myjar(minSdkVersion:(no version))")
+	ensureListContains(t, flatDepsInfo, "  mylib(minSdkVersion:(no version))")
+	ensureListContains(t, flatDepsInfo, "  mylib2(minSdkVersion:(no version))")
+	ensureListContains(t, flatDepsInfo, "  myotherjar(minSdkVersion:(no version))")
+	ensureListContains(t, flatDepsInfo, "  mysharedjar(minSdkVersion:(no version)) (external)")
 }
 
 func TestDefaults(t *testing.T) {
@@ -818,11 +825,15 @@
 	// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
 	ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
 
-	depsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("myapex2-deps-info.txt").Args["content"], "\\n")
+	fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
+	ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex2")
+	ensureListContains(t, fullDepsInfo, "libbaz(minSdkVersion:(no version)) <- mylib")
+	ensureListContains(t, fullDepsInfo, "libfoo(minSdkVersion:(no version)) (external) <- mylib")
 
-	ensureListContains(t, depsInfo, "mylib <- myapex2")
-	ensureListContains(t, depsInfo, "libbaz <- mylib")
-	ensureListContains(t, depsInfo, "libfoo (external) <- mylib")
+	flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
+	ensureListContains(t, flatDepsInfo, "  mylib(minSdkVersion:(no version))")
+	ensureListContains(t, flatDepsInfo, "  libbaz(minSdkVersion:(no version))")
+	ensureListContains(t, flatDepsInfo, "  libfoo(minSdkVersion:(no version)) (external)")
 }
 
 func TestApexWithRuntimeLibsDependency(t *testing.T) {
@@ -1411,6 +1422,122 @@
 	`)
 }
 
+func TestJavaStableSdkVersion(t *testing.T) {
+	testCases := []struct {
+		name          string
+		expectedError string
+		bp            string
+	}{
+		{
+			name: "Non-updatable apex with non-stable dep",
+			bp: `
+				apex {
+					name: "myapex",
+					java_libs: ["myjar"],
+					key: "myapex.key",
+				}
+				apex_key {
+					name: "myapex.key",
+					public_key: "testkey.avbpubkey",
+					private_key: "testkey.pem",
+				}
+				java_library {
+					name: "myjar",
+					srcs: ["foo/bar/MyClass.java"],
+					sdk_version: "core_platform",
+					apex_available: ["myapex"],
+				}
+			`,
+		},
+		{
+			name: "Updatable apex with stable dep",
+			bp: `
+				apex {
+					name: "myapex",
+					java_libs: ["myjar"],
+					key: "myapex.key",
+					updatable: true,
+					min_sdk_version: "29",
+				}
+				apex_key {
+					name: "myapex.key",
+					public_key: "testkey.avbpubkey",
+					private_key: "testkey.pem",
+				}
+				java_library {
+					name: "myjar",
+					srcs: ["foo/bar/MyClass.java"],
+					sdk_version: "current",
+					apex_available: ["myapex"],
+				}
+			`,
+		},
+		{
+			name:          "Updatable apex with non-stable dep",
+			expectedError: "cannot depend on \"myjar\"",
+			bp: `
+				apex {
+					name: "myapex",
+					java_libs: ["myjar"],
+					key: "myapex.key",
+					updatable: true,
+				}
+				apex_key {
+					name: "myapex.key",
+					public_key: "testkey.avbpubkey",
+					private_key: "testkey.pem",
+				}
+				java_library {
+					name: "myjar",
+					srcs: ["foo/bar/MyClass.java"],
+					sdk_version: "core_platform",
+					apex_available: ["myapex"],
+				}
+			`,
+		},
+		{
+			name:          "Updatable apex with non-stable transitive dep",
+			expectedError: "compiles against Android API, but dependency \"transitive-jar\" is compiling against non-public Android API.",
+			bp: `
+				apex {
+					name: "myapex",
+					java_libs: ["myjar"],
+					key: "myapex.key",
+					updatable: true,
+				}
+				apex_key {
+					name: "myapex.key",
+					public_key: "testkey.avbpubkey",
+					private_key: "testkey.pem",
+				}
+				java_library {
+					name: "myjar",
+					srcs: ["foo/bar/MyClass.java"],
+					sdk_version: "current",
+					apex_available: ["myapex"],
+					static_libs: ["transitive-jar"],
+				}
+				java_library {
+					name: "transitive-jar",
+					srcs: ["foo/bar/MyClass.java"],
+					sdk_version: "core_platform",
+					apex_available: ["myapex"],
+				}
+			`,
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			if test.expectedError == "" {
+				testApex(t, test.bp)
+			} else {
+				testApexError(t, test.expectedError, test.bp)
+			}
+		})
+	}
+}
+
 func TestFilesInSubDir(t *testing.T) {
 	ctx, _ := testApex(t, `
 		apex {
@@ -4458,6 +4585,7 @@
 		java_library {
 			name: "some-updatable-apex-lib",
 			srcs: ["a.java"],
+			sdk_version: "current",
 			apex_available: [
 				"some-updatable-apex",
 			],
@@ -4474,12 +4602,14 @@
 		java_library {
 			name: "some-platform-lib",
 			srcs: ["a.java"],
+			sdk_version: "current",
 			installable: true,
 		}
 
 		java_library {
 			name: "some-art-lib",
 			srcs: ["a.java"],
+			sdk_version: "current",
 			apex_available: [
 				"com.android.art.something",
 			],
diff --git a/apex/builder.go b/apex/builder.go
index fba6b94..ca24f2c 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -688,29 +688,48 @@
 		return
 	}
 
-	var content strings.Builder
-	for _, key := range android.SortedStringKeys(a.depInfos) {
-		info := a.depInfos[key]
-		toName := info.to
-		if info.isExternal {
-			toName = toName + " (external)"
+	depInfos := android.DepNameToDepInfoMap{}
+	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+		if from.Name() == to.Name() {
+			// This can happen for cc.reuseObjTag. We are not interested in tracking this.
+			// As soon as the dependency graph crosses the APEX boundary, don't go further.
+			return !externalDep
 		}
-		fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(android.SortedUniqueStrings(info.from), ", "))
-	}
 
-	depsInfoFile := android.PathForOutput(ctx, a.Name()+"-deps-info.txt")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.WriteFile,
-		Description: "Dependency Info",
-		Output:      depsInfoFile,
-		Args: map[string]string{
-			"content": content.String(),
-		},
+		if info, exists := depInfos[to.Name()]; exists {
+			if !android.InList(from.Name(), info.From) {
+				info.From = append(info.From, from.Name())
+			}
+			info.IsExternal = info.IsExternal && externalDep
+			depInfos[to.Name()] = info
+		} else {
+			toMinSdkVersion := "(no version)"
+			if m, ok := to.(interface{ MinSdkVersion() string }); ok {
+				if v := m.MinSdkVersion(); v != "" {
+					toMinSdkVersion = v
+				}
+			}
+
+			depInfos[to.Name()] = android.ApexModuleDepInfo{
+				To:            to.Name(),
+				From:          []string{from.Name()},
+				IsExternal:    externalDep,
+				MinSdkVersion: toMinSdkVersion,
+			}
+		}
+
+		// As soon as the dependency graph crosses the APEX boundary, don't go further.
+		return !externalDep
 	})
 
+	a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, proptools.String(a.properties.Min_sdk_version), depInfos)
+
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   android.Phony,
 		Output: android.PathForPhony(ctx, a.Name()+"-deps-info"),
-		Inputs: []android.Path{depsInfoFile},
+		Inputs: []android.Path{
+			a.ApexBundleDepsInfo.FullListPath(),
+			a.ApexBundleDepsInfo.FlatListPath(),
+		},
 	})
 }
diff --git a/cc/cc.go b/cc/cc.go
index 082816e..49605cc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -581,6 +581,10 @@
 	return String(c.Properties.Sdk_version)
 }
 
+func (c *Module) MinSdkVersion() string {
+	return String(c.Properties.Min_sdk_version)
+}
+
 func (c *Module) AlwaysSdk() bool {
 	return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
 }
diff --git a/cmd/path_interposer/main.go b/cmd/path_interposer/main.go
index cd28b96..a4fe3e4 100644
--- a/cmd/path_interposer/main.go
+++ b/cmd/path_interposer/main.go
@@ -53,14 +53,7 @@
 		os.Exit(1)
 	}
 
-	disableError := false
-	if e, ok := os.LookupEnv("TEMPORARY_DISABLE_PATH_RESTRICTIONS"); ok {
-		disableError = e == "1" || e == "y" || e == "yes" || e == "on" || e == "true"
-	}
-
 	exitCode, err := Main(os.Stdout, os.Stderr, interposer, os.Args, mainOpts{
-		disableError: disableError,
-
 		sendLog:       paths.SendLog,
 		config:        paths.GetConfig,
 		lookupParents: lookupParents,
@@ -79,8 +72,6 @@
 socket at <interposer>_log.`)
 
 type mainOpts struct {
-	disableError bool
-
 	sendLog       func(logSocket string, entry *paths.LogEntry, done chan interface{})
 	config        func(name string) paths.PathConfig
 	lookupParents func() []paths.LogProcess
@@ -131,7 +122,7 @@
 			}, waitForLog)
 			defer func() { <-waitForLog }()
 		}
-		if config.Error && !opts.disableError {
+		if config.Error {
 			return 1, fmt.Errorf("%q is not allowed to be used. See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.", base)
 		}
 	}
diff --git a/java/app.go b/java/app.go
index d535c5a..d25575c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1392,7 +1392,8 @@
 	})
 
 	android.InitApexModule(module)
-	InitJavaModule(module, android.DeviceSupported)
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 	android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
 
 	return module
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index d849dc2..92c96e2 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -117,7 +117,7 @@
 		artModules := global.ArtApexJars
 		// With EMMA_INSTRUMENT_FRAMEWORK=true the Core libraries depend on jacoco.
 		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
-			artModules = append(artModules, "jacocoagent")
+			artModules = append(artModules, "com.android.art:jacocoagent")
 		}
 		frameworkModules := android.RemoveListFromList(global.BootJars, artModules)
 
diff --git a/java/droiddoc.go b/java/droiddoc.go
index a9b5d5f..eba7766 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1505,20 +1505,37 @@
 		updatedBaselineOutput := android.PathForModuleOut(ctx, "api_lint_baseline.txt")
 		d.apiLintTimestamp = android.PathForModuleOut(ctx, "api_lint.timestamp")
 
+		msg := `` +
+			`************************************************************\n` +
+			`Your API changes are triggering API Lint warnings or errors.\n` +
+			`To make these errors go away, fix the code according to the\n` +
+			`error and/or warning messages above.\n` +
+			`\n` +
+			`If it's not possible to do so, there are workarounds:\n` +
+			`\n` +
+			`1. You can suppress the errors with @SuppressLint(\"<id>\")\n`
+
 		if baselineFile.Valid() {
 			cmd.FlagWithInput("--baseline ", baselineFile.Path())
 			cmd.FlagWithOutput("--update-baseline ", updatedBaselineOutput)
+
+			msg += fmt.Sprintf(``+
+				`2. You can update the baseline by executing the following\n`+
+				`   command:\n`+
+				`       cp \\ \n`+
+				`       \"$PWD/%s\" \\ \n`+
+				`       \"$PWD/%s\" \n`+
+				`   To submit the revised baseline.txt to the main Android\n`+
+				`   repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
+		} else {
+			msg += fmt.Sprintf(``+
+				`2. You can add a baseline file of existing lint failures\n`+
+				`   to the build rule of %s.\n`, d.Name())
 		}
+		msg += `************************************************************\n`
 
 		zipSyncCleanupCmd(rule, srcJarDir)
 
-		msg := fmt.Sprintf(`\n******************************\n`+
-			`Your API changes are triggering API Lint warnings or errors.\n\n`+
-			`To make these errors go away, you have two choices:\n`+
-			`   1. You can suppress the errors with @SuppressLint(\"<id>\").\n\n`+
-			`   2. You can update the baseline by executing the following command:\n`+
-			`         cp \"$PWD/%s\" \"$PWD/%s\"\n\n`+
-			`******************************\n`, updatedBaselineOutput, baselineFile.Path())
 		rule.Command().
 			Text("touch").Output(d.apiLintTimestamp).
 			Text(") || (").
diff --git a/java/java.go b/java/java.go
index 7f3ba98..472d3da 100644
--- a/java/java.go
+++ b/java/java.go
@@ -86,6 +86,14 @@
 	ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
 }
 
+func (j *Module) CheckStableSdkVersion() error {
+	sdkVersion := j.sdkVersion()
+	if sdkVersion.stable() {
+		return nil
+	}
+	return fmt.Errorf("non stable SDK %v", sdkVersion)
+}
+
 func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
 	if j.SocSpecific() || j.DeviceSpecific() ||
 		(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
@@ -592,6 +600,10 @@
 	return j.sdkVersion()
 }
 
+func (j *Module) MinSdkVersion() string {
+	return j.minSdkVersion().version.String()
+}
+
 func (j *Module) AvailableFor(what string) bool {
 	if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) {
 		// Exception: for hostdex: true libraries, the platform variant is created
@@ -2390,6 +2402,10 @@
 	return j.sdkVersion()
 }
 
+func (j *Import) MinSdkVersion() string {
+	return j.minSdkVersion().version.String()
+}
+
 func (j *Import) Prebuilt() *android.Prebuilt {
 	return &j.prebuilt
 }
diff --git a/java/sdk.go b/java/sdk.go
index 92076f4..690451c 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -169,9 +169,12 @@
 		return false
 	}
 	switch s.kind {
+	case sdkNone:
+		// there is nothing to manage and version in this case; de facto stable API.
+		return true
 	case sdkCore, sdkPublic, sdkSystem, sdkModule, sdkSystemServer:
 		return true
-	case sdkNone, sdkCorePlatform, sdkTest, sdkPrivate:
+	case sdkCorePlatform, sdkTest, sdkPrivate:
 		return false
 	default:
 		panic(fmt.Errorf("unknown sdkKind=%v", s.kind))
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 0932873..9f27647 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -494,11 +494,13 @@
 		})
 	}
 
-	syspropLibrariesLock.Lock()
-	defer syspropLibrariesLock.Unlock()
+	if m.ExportedToMake() {
+		syspropLibrariesLock.Lock()
+		defer syspropLibrariesLock.Unlock()
 
-	libraries := syspropLibraries(ctx.Config())
-	*libraries = append(*libraries, ctx.ModuleName())
+		libraries := syspropLibraries(ctx.Config())
+		*libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName())
+	}
 }
 
 func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
diff --git a/ui/build/path.go b/ui/build/path.go
index c34ba1b..7122927 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -177,9 +177,12 @@
 		execs = append(execs, parsePathDir(pathEntry)...)
 	}
 
-	allowAllSymlinks := config.Environment().IsEnvTrue("TEMPORARY_DISABLE_PATH_RESTRICTIONS")
+	if config.Environment().IsEnvTrue("TEMPORARY_DISABLE_PATH_RESTRICTIONS") {
+		ctx.Fatalln("TEMPORARY_DISABLE_PATH_RESTRICTIONS was a temporary migration method, and is now obsolete.")
+	}
+
 	for _, name := range execs {
-		if !paths.GetConfig(name).Symlink && !allowAllSymlinks {
+		if !paths.GetConfig(name).Symlink {
 			continue
 		}
 
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 98eb028..dab0e75 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -181,15 +181,15 @@
 		// For now, just map everything. Make most things readonly.
 		"-R", "/",
 
+		// Mount a writable tmp dir
+		"-B", "/tmp",
+
 		// Mount source are read-write
 		"-B", sandboxConfig.srcDir,
 
 		//Mount out dir as read-write
 		"-B", sandboxConfig.outDir,
 
-		// Mount a writable tmp dir
-		"-B", "/tmp",
-
 		// Disable newcgroup for now, since it may require newer kernels
 		// TODO: try out cgroups
 		"--disable_clone_newcgroup",