Merge "apex: file_contexts for override_apex flattened" into rvc-dev
diff --git a/android/androidmk.go b/android/androidmk.go
index c296a5b..6ba68af 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -198,6 +198,10 @@
 	a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
 	a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
 
+	if am, ok := mod.(ApexModule); ok {
+		a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
+	}
+
 	archStr := amod.Arch().ArchType.String()
 	host := false
 	switch amod.Os().Class {
diff --git a/android/apex.go b/android/apex.go
index 9bf6fc7..1a43ce4 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -100,6 +100,16 @@
 	// Tests if this module is available for the specified APEX or ":platform"
 	AvailableFor(what string) bool
 
+	// Return true if this module is not available to platform (i.e. apex_available
+	// property doesn't have "//apex_available:platform"), or shouldn't be available
+	// to platform, which is the case when this module depends on other module that
+	// isn't available to platform.
+	NotAvailableForPlatform() bool
+
+	// Mark that this module is not available to platform. Set by the
+	// check-platform-availability mutator in the apex package.
+	SetNotAvailableForPlatform()
+
 	// Returns the highest version which is <= maxSdkVersion.
 	// For example, with maxSdkVersion is 10 and versionList is [9,11]
 	// it returns 9 as string
@@ -117,6 +127,8 @@
 	Apex_available []string
 
 	Info ApexInfo `blueprint:"mutated"`
+
+	NotAvailableForPlatform bool `blueprint:"mutated"`
 }
 
 // Marker interface that identifies dependencies that are excluded from APEX
@@ -201,6 +213,14 @@
 	return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
 }
 
+func (m *ApexModuleBase) NotAvailableForPlatform() bool {
+	return m.ApexProperties.NotAvailableForPlatform
+}
+
+func (m *ApexModuleBase) SetNotAvailableForPlatform() {
+	m.ApexProperties.NotAvailableForPlatform = true
+}
+
 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.
diff --git a/apex/apex.go b/apex/apex.go
index 82e2442..ec87f5b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -561,7 +561,6 @@
 		"libnativebridge_lazy",
 		"libnativeloader_lazy",
 		"libnativewindow_headers",
-		"libopus",
 		"libpdx_headers",
 		"libprocessgroup",
 		"libprocessgroup_headers",
@@ -833,6 +832,7 @@
 	ctx.BottomUp("apex", apexMutator).Parallel()
 	ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
 	ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
+	ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
 }
 
 // Mark the direct and transitive dependencies of apex bundles so that they
@@ -870,6 +870,60 @@
 	})
 }
 
+// mark if a module cannot be available to platform. A module cannot be available
+// to platform if 1) it is explicitly marked as not available (i.e. "//apex_available:platform"
+// is absent) or 2) it depends on another module that isn't (or can't be) available to platform
+func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
+	// Host and recovery are not considered as platform
+	if mctx.Host() || mctx.Module().InstallInRecovery() {
+		return
+	}
+
+	if am, ok := mctx.Module().(android.ApexModule); ok {
+		availableToPlatform := am.AvailableFor(android.AvailableToPlatform)
+
+		// In a rare case when a lib is marked as available only to an apex
+		// but the apex doesn't exist. This can happen in a partial manifest branch
+		// like master-art. Currently, libstatssocket in the stats APEX is causing
+		// this problem.
+		// Include the lib in platform because the module SDK that ought to provide
+		// it doesn't exist, so it would otherwise be left out completely.
+		// TODO(b/154888298) remove this by adding those libraries in module SDKS and skipping
+		// this check for libraries provided by SDKs.
+		if !availableToPlatform && !android.InAnyApex(am.Name()) {
+			availableToPlatform = true
+		}
+
+		// If any of the dep is not available to platform, this module is also considered
+		// as being not available to platform even if it has "//apex_available:platform"
+		mctx.VisitDirectDeps(func(child android.Module) {
+			if !am.DepIsInSameApex(mctx, child) {
+				// if the dependency crosses apex boundary, don't consider it
+				return
+			}
+			if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() {
+				availableToPlatform = false
+				// TODO(b/154889534) trigger an error when 'am' has "//apex_available:platform"
+			}
+		})
+
+		// Exception 1: stub libraries and native bridge libraries are always available to platform
+		if cc, ok := mctx.Module().(*cc.Module); ok &&
+			(cc.IsStubs() || cc.Target().NativeBridge == android.NativeBridgeEnabled) {
+			availableToPlatform = true
+		}
+
+		// Exception 2: bootstrap bionic libraries are also always available to platform
+		if cc.InstallToBootstrap(mctx.ModuleName(), mctx.Config()) {
+			availableToPlatform = true
+		}
+
+		if !availableToPlatform {
+			am.SetNotAvailableForPlatform()
+		}
+	}
+}
+
 // If a module in an APEX depends on a module from an SDK then it needs an APEX
 // specific variant created for it. Refer to sdk.sdkDepsReplaceMutator.
 func inAnySdk(module android.Module) bool {
@@ -1111,8 +1165,10 @@
 	IsCoverageVariant bool `blueprint:"mutated"`
 
 	// Whether this APEX is considered updatable or not. When set to true, this will enforce additional
-	// 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.
+	// rules for making sure that the APEX is truly updatable.
+	// - To be updatable, min_sdk_version should be set as well
+	// 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.
@@ -1885,6 +1941,14 @@
 	})
 }
 
+func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
+	if proptools.Bool(a.properties.Updatable) {
+		if String(a.properties.Min_sdk_version) == "" {
+			ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
+		}
+	}
+}
+
 // 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)
@@ -1950,6 +2014,7 @@
 	}
 
 	a.checkApexAvailability(ctx)
+	a.checkUpdatable(ctx)
 
 	a.collectDepsInfo(ctx)
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index eed0d72..91ad6e8 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3668,22 +3668,12 @@
 	}`)
 }
 
-func TestApexAvailable_CreatedForPlatform(t *testing.T) {
-	// check that libfoo and libbar are created only for myapex, but not for the platform
-	// TODO(jiyong) the checks for the platform variant are removed because we now create
-	// the platform variant regardless of the apex_availability. Instead, we will make sure that
-	// the platform variants are not used from other platform modules. When that is done,
-	// these checks will be replaced by expecting a specific error message that will be
-	// emitted when the platform variant is used.
-	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
-	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
-	//	ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
-	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")
-
+func TestApexAvailable_CheckForPlatform(t *testing.T) {
 	ctx, _ := testApex(t, `
 	apex {
 		name: "myapex",
 		key: "myapex.key",
+		native_shared_libs: ["libbar", "libbaz"],
 	}
 
 	apex_key {
@@ -3696,16 +3686,52 @@
 		name: "libfoo",
 		stl: "none",
 		system_shared_libs: [],
+		shared_libs: ["libbar"],
 		apex_available: ["//apex_available:platform"],
+	}
+
+	cc_library {
+		name: "libfoo2",
+		stl: "none",
+		system_shared_libs: [],
+		shared_libs: ["libbaz"],
+		apex_available: ["//apex_available:platform"],
+	}
+
+	cc_library {
+		name: "libbar",
+		stl: "none",
+		system_shared_libs: [],
+		apex_available: ["myapex"],
+	}
+
+	cc_library {
+		name: "libbaz",
+		stl: "none",
+		system_shared_libs: [],
+		apex_available: ["myapex"],
+		stubs: {
+			versions: ["1"],
+		},
 	}`)
 
-	// check that libfoo is created only for the platform
-	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
+	// libfoo shouldn't be available to platform even though it has "//apex_available:platform",
+	// because it depends on libbar which isn't available to platform
+	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+	if libfoo.NotAvailableForPlatform() != true {
+		t.Errorf("%q shouldn't be available to platform", libfoo.String())
+	}
+
+	// libfoo2 however can be available to platform because it depends on libbaz which provides
+	// stubs
+	libfoo2 := ctx.ModuleForTests("libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+	if libfoo2.NotAvailableForPlatform() == true {
+		t.Errorf("%q should be available to platform", libfoo2.String())
+	}
 }
 
 func TestApexAvailable_CreatedForApex(t *testing.T) {
-	testApex(t, `
+	ctx, _ := testApex(t, `
 	apex {
 		name: "myapex",
 		key: "myapex.key",
@@ -3728,17 +3754,14 @@
 		},
 	}`)
 
-	// shared variant of libfoo is only available to myapex
-	// TODO(jiyong) the checks for the platform variant are removed because we now create
-	// the platform variant regardless of the apex_availability. Instead, we will make sure that
-	// the platform variants are not used from other platform modules. When that is done,
-	// these checks will be replaced by expecting a specific error message that will be
-	// emitted when the platform variant is used.
-	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
-	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
-	//	// but the static variant is available to both myapex and the platform
-	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static_myapex")
-	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static")
+	libfooShared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+	if libfooShared.NotAvailableForPlatform() != true {
+		t.Errorf("%q shouldn't be available to platform", libfooShared.String())
+	}
+	libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
+	if libfooStatic.NotAvailableForPlatform() != false {
+		t.Errorf("%q should be available to platform", libfooStatic.String())
+	}
 }
 
 func TestOverrideApex(t *testing.T) {
@@ -4017,6 +4040,7 @@
 			native_shared_libs: ["mylib"],
 			java_libs: ["myjar"],
 			updatable: true,
+			min_sdk_version: "current",
 		}
 
 		apex_key {
@@ -4242,6 +4266,22 @@
 	}
 }
 
+func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
+	testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			updatable: true,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+	`)
+}
+
 func TestNoUpdatableJarsInBootImage(t *testing.T) {
 	bp := `
 		java_library {
diff --git a/java/app_test.go b/java/app_test.go
index b1c8b63..39460dc 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2540,3 +2540,62 @@
 		t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides)
 	}
 }
+
+func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
+	ctx, config := testJava(t, `
+		java_defaults {
+			name: "rro_defaults",
+			theme: "default_theme",
+			product_specific: true,
+			aaptflags: ["--keep-raw-values"],
+		}
+
+		runtime_resource_overlay {
+			name: "foo_with_defaults",
+			defaults: ["rro_defaults"],
+		}
+
+		runtime_resource_overlay {
+			name: "foo_barebones",
+		}
+		`)
+
+	//
+	// RRO module with defaults
+	//
+	m := ctx.ModuleForTests("foo_with_defaults", "android_common")
+
+	// Check AAPT2 link flags.
+	aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ")
+	expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
+	absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags)
+	if len(absentFlags) > 0 {
+		t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
+	}
+
+	// Check device location.
+	path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
+	expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"}
+	if !reflect.DeepEqual(path, expectedPath) {
+		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath)
+	}
+
+	//
+	// RRO module without defaults
+	//
+	m = ctx.ModuleForTests("foo_barebones", "android_common")
+
+	// Check AAPT2 link flags.
+	aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ")
+	unexpectedFlags := "--keep-raw-values"
+	if inList(unexpectedFlags, aapt2Flags) {
+		t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags)
+	}
+
+	// Check device location.
+	path = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
+	expectedPath = []string{"/tmp/target/product/test_device/system/overlay"}
+	if !reflect.DeepEqual(path, expectedPath) {
+		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
+	}
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 8f08f1f..7ac71a4 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1524,40 +1524,35 @@
 		apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
 		removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
 		baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
-		updatedBaselineOutput := android.PathForModuleOut(ctx, "current_baseline.txt")
+
+		if baselineFile.Valid() {
+			ctx.PropertyErrorf("current API check can't have a baseline file. (module %s)", ctx.ModuleName())
+		}
 
 		d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
 
 		rule := android.NewRuleBuilder()
 
+		// Diff command line.
+		// -F matches the closest "opening" line, such as "package xxx{"
+		// and "  public class Yyy {".
+		diff := `diff -u -F '{ *$'`
+
 		rule.Command().Text("( true")
+		rule.Command().
+			Text(diff).
+			Input(apiFile).Input(d.apiFile)
 
-		srcJarDir := android.PathForModuleOut(ctx, "current-apicheck", "srcjars")
-		srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
-
-		cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
-			deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
-
-		cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles).
-			FlagWithInput("--check-compatibility:api:current ", apiFile).
-			FlagWithInput("--check-compatibility:removed:current ", removedApiFile)
-
-		d.inclusionAnnotationsFlags(ctx, cmd)
-		d.mergeAnnoDirFlags(ctx, cmd)
-
-		if baselineFile.Valid() {
-			cmd.FlagWithInput("--baseline ", baselineFile.Path())
-			cmd.FlagWithOutput("--update-baseline ", updatedBaselineOutput)
-		}
-
-		zipSyncCleanupCmd(rule, srcJarDir)
+		rule.Command().
+			Text(diff).
+			Input(removedApiFile).Input(d.removedApiFile)
 
 		msg := fmt.Sprintf(`\n******************************\n`+
 			`You have tried to change the API from what has been previously approved.\n\n`+
 			`To make these errors go away, you have two choices:\n`+
-			`   1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
-			`      errors above.\n\n`+
-			`   2. You can update current.txt by executing the following command:\n`+
+			`   1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
+			`      to the new methods, etc. shown in the above diff.\n\n`+
+			`   2. You can update current.txt and/or removed.txt by executing the following command:\n`+
 			`         make %s-update-current-api\n\n`+
 			`      To submit the revised current.txt to the main Android repository,\n`+
 			`      you will need approval.\n`+
@@ -1570,7 +1565,7 @@
 			Text("; exit 38").
 			Text(")")
 
-		rule.Build(pctx, ctx, "metalavaCurrentApiCheck", "metalava check current API")
+		rule.Build(pctx, ctx, "metalavaCurrentApiCheck", "check current API")
 
 		d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
 
diff --git a/java/java.go b/java/java.go
index 1c2e22a..5d77807 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2745,6 +2745,7 @@
 		&sdkLibraryProperties{},
 		&DexImportProperties{},
 		&android.ApexProperties{},
+		&RuntimeResourceOverlayProperties{},
 	)
 
 	android.InitDefaultsModule(module)