Merge "Add helper functions for getting output files from modules"
diff --git a/Android.bp b/Android.bp
index d469f41..7576102 100644
--- a/Android.bp
+++ b/Android.bp
@@ -298,6 +298,7 @@
         "java/sdk.go",
         "java/sdk_library.go",
         "java/support_libraries.go",
+        "java/sysprop.go",
         "java/system_modules.go",
         "java/testing.go",
         "java/tradefed.go",
diff --git a/android/register.go b/android/register.go
index d79982a..86943f2 100644
--- a/android/register.go
+++ b/android/register.go
@@ -114,3 +114,43 @@
 	}
 	return ret
 }
+
+// Interface for registering build components.
+//
+// Provided to allow registration of build components to be shared between the runtime
+// and test environments.
+type RegistrationContext interface {
+	RegisterModuleType(name string, factory ModuleFactory)
+	RegisterSingletonType(name string, factory SingletonFactory)
+}
+
+// Used to register build components from an init() method, e.g.
+//
+// init() {
+//   RegisterBuildComponents(android.InitRegistrationContext)
+// }
+//
+// func RegisterBuildComponents(ctx android.RegistrationContext) {
+//   ctx.RegisterModuleType(...)
+//   ...
+// }
+//
+// Extracting the actual registration into a separate RegisterBuildComponents(ctx) function
+// allows it to be used to initialize test context, e.g.
+//
+//   ctx := android.NewTestContext()
+//   RegisterBuildComponents(ctx)
+var InitRegistrationContext RegistrationContext = initRegistrationContext{}
+
+// Make sure the TestContext implements RegistrationContext.
+var _ RegistrationContext = (*TestContext)(nil)
+
+type initRegistrationContext struct{}
+
+func (ctx initRegistrationContext) RegisterModuleType(name string, factory ModuleFactory) {
+	RegisterModuleType(name, factory)
+}
+
+func (ctx initRegistrationContext) RegisterSingletonType(name string, factory SingletonFactory) {
+	RegisterSingletonType(name, factory)
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index b2d891d..bb6e026 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -303,14 +303,10 @@
 	ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
 	ctx.RegisterModuleType("prebuilt_etc", android.PrebuiltEtcFactory)
 	ctx.RegisterModuleType("sh_binary", android.ShBinaryFactory)
-	ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
-	ctx.RegisterModuleType("java_library", java.LibraryFactory)
-	ctx.RegisterModuleType("java_import", java.ImportFactory)
-	ctx.RegisterModuleType("java_system_modules", java.SystemModulesFactory)
-	ctx.RegisterModuleType("android_app", java.AndroidAppFactory)
-	ctx.RegisterModuleType("android_app_import", java.AndroidAppImportFactory)
-	ctx.RegisterModuleType("override_android_app", java.OverrideAndroidAppModuleFactory)
+	java.RegisterJavaBuildComponents(ctx)
+	java.RegisterSystemModulesBuildComponents(ctx)
+	java.RegisterAppBuildComponents(ctx)
 
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
diff --git a/cc/cc.go b/cc/cc.go
index 949e671..4c9d42b 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -42,7 +42,7 @@
 		ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("version", VersionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
-		ctx.BottomUp("sysprop", SyspropMutator).Parallel()
+		ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
 	})
 
 	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 0d3cc74..8b84be8 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -27,9 +27,10 @@
 type FuzzConfig struct {
 	// Email address of people to CC on bugs or contact about this fuzz target.
 	Cc []string `json:"cc,omitempty"`
-	// Boolean specifying whether to disable the fuzz target from running
-	// automatically in continuous fuzzing infrastructure.
-	Disable *bool `json:"disable,omitempty"`
+	// Specify whether to enable continuous fuzzing on devices. Defaults to true.
+	Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
+	// Specify whether to enable continuous fuzzing on host. Defaults to true.
+	Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
 	// Component in Google's bug tracking system that bugs should be filed to.
 	Componentid *int64 `json:"componentid,omitempty"`
 	// Hotlists in Google's bug tracking system that bugs should be marked with.
diff --git a/java/aar.go b/java/aar.go
index e0bea5d..201e590 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -34,8 +34,12 @@
 }
 
 func init() {
-	android.RegisterModuleType("android_library_import", AARImportFactory)
-	android.RegisterModuleType("android_library", AndroidLibraryFactory)
+	RegisterAARBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterAARBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("android_library_import", AARImportFactory)
+	ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
 }
 
 //
diff --git a/java/app.go b/java/app.go
index ae637fd..94f6bb1 100755
--- a/java/app.go
+++ b/java/app.go
@@ -33,18 +33,22 @@
 var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
 
 func init() {
-	android.RegisterModuleType("android_app", AndroidAppFactory)
-	android.RegisterModuleType("android_test", AndroidTestFactory)
-	android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
-	android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
-	android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
-	android.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory)
-	android.RegisterModuleType("android_app_import", AndroidAppImportFactory)
-	android.RegisterModuleType("android_test_import", AndroidTestImportFactory)
+	RegisterAppBuildComponents(android.InitRegistrationContext)
 
 	initAndroidAppImportVariantGroupTypes()
 }
 
+func RegisterAppBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("android_app", AndroidAppFactory)
+	ctx.RegisterModuleType("android_test", AndroidTestFactory)
+	ctx.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
+	ctx.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
+	ctx.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
+	ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory)
+	ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory)
+	ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory)
+}
+
 // AndroidManifest.xml merging
 // package splits
 
diff --git a/java/config/config.go b/java/config/config.go
index 06c99f1..9738454 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -29,7 +29,7 @@
 
 	DefaultBootclasspathLibraries = []string{"core.platform.api.stubs", "core-lambda-stubs"}
 	DefaultSystemModules          = "core-platform-api-stubs-system-modules"
-	DefaultLibraries              = []string{"ext", "framework", "updatable_media_stubs"}
+	DefaultLibraries              = []string{"ext", "framework"}
 	DefaultLambdaStubsLibrary     = "core-lambda-stubs"
 	SdkLambdaStubsPath            = "prebuilts/sdk/tools/core-lambda-stubs.jar"
 
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 92f9246..3b7f772 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -27,19 +27,8 @@
 )
 
 func init() {
-	android.RegisterModuleType("doc_defaults", DocDefaultsFactory)
-	android.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
-
-	android.RegisterModuleType("droiddoc", DroiddocFactory)
-	android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
-	android.RegisterModuleType("droiddoc_exported_dir", ExportedDroiddocDirFactory)
-	android.RegisterModuleType("javadoc", JavadocFactory)
-	android.RegisterModuleType("javadoc_host", JavadocHostFactory)
-
-	android.RegisterModuleType("droidstubs", DroidstubsFactory)
-	android.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
-
-	android.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
+	RegisterDocsBuildComponents(android.InitRegistrationContext)
+	RegisterStubsBuildComponents(android.InitRegistrationContext)
 
 	// Register sdk member type.
 	android.RegisterSdkMemberType(&droidStubsSdkMemberType{
@@ -49,6 +38,25 @@
 	})
 }
 
+func RegisterDocsBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("doc_defaults", DocDefaultsFactory)
+
+	ctx.RegisterModuleType("droiddoc", DroiddocFactory)
+	ctx.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
+	ctx.RegisterModuleType("droiddoc_exported_dir", ExportedDroiddocDirFactory)
+	ctx.RegisterModuleType("javadoc", JavadocFactory)
+	ctx.RegisterModuleType("javadoc_host", JavadocHostFactory)
+}
+
+func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
+
+	ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
+	ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
+
+	ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
+}
+
 var (
 	srcsLibTag = dependencyTag{name: "sources from javalib"}
 )
@@ -782,7 +790,7 @@
 		if t, ok := m.(*ExportedDroiddocDir); ok {
 			cmd.FlagWithArg("-templatedir ", t.dir.String()).Implicits(t.deps)
 		} else {
-			ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
+			ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_exported_dir", ctx.OtherModuleName(m))
 		}
 	})
 
diff --git a/java/genrule.go b/java/genrule.go
index 25494ec..e0a9c8f 100644
--- a/java/genrule.go
+++ b/java/genrule.go
@@ -20,8 +20,12 @@
 )
 
 func init() {
-	android.RegisterModuleType("java_genrule", genRuleFactory)
-	android.RegisterModuleType("java_genrule_host", genRuleFactoryHost)
+	RegisterGenRuleBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterGenRuleBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("java_genrule", genRuleFactory)
+	ctx.RegisterModuleType("java_genrule_host", genRuleFactoryHost)
 }
 
 // java_genrule is a genrule that can depend on other java_* objects.
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index e9e4a45..ad84cde 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -16,7 +16,6 @@
 
 import (
 	"fmt"
-	"strings"
 
 	"android/soong/android"
 )
@@ -153,23 +152,11 @@
 		// Collect dex jar paths for modules that had hiddenapi encode called on them.
 		if h, ok := module.(hiddenAPIIntf); ok {
 			if jar := h.bootDexJar(); jar != nil {
-				// Don't add multiple variants of the same library to bootDexJars, otherwise
-				// hiddenapi tool will complain about duplicated classes. Such multiple variants
-				// of the same library can happen when the library is included in one or more APEXes.
-				// TODO(b/146308764): remove this heuristic
-				if a, ok := module.(android.ApexModule); ok && android.InAnyApex(module.Name()) {
-					if a.AvailableFor("//apex_available:platform") && !a.IsForPlatform() {
-						// skip the apex variants if the jar is available for the platform
-						return
-					}
-					apexName := a.ApexName()
-					if strings.Contains(apexName, "test") {
-						// skip the if the jar is in test APEX
-						return
-					}
-
-					if strings.Contains(apexName, "com.android.art") && apexName != "com.android.art.release" {
-						// skip the ART APEX variants other than com.android.art.release
+				// For a java lib included in an APEX, only take the one built for
+				// the platform variant, and skip the variants for APEXes.
+				// Otherwise, the hiddenapi tool will complain about duplicated classes
+				if a, ok := module.(android.ApexModule); ok {
+					if android.InAnyApex(module.Name()) && !a.IsForPlatform() {
 						return
 					}
 				}
diff --git a/java/java.go b/java/java.go
index 9745da4..4c80ba7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -34,24 +34,7 @@
 )
 
 func init() {
-	android.RegisterModuleType("java_defaults", DefaultsFactory)
-
-	android.RegisterModuleType("java_library", LibraryFactory)
-	android.RegisterModuleType("java_library_static", LibraryStaticFactory)
-	android.RegisterModuleType("java_library_host", LibraryHostFactory)
-	android.RegisterModuleType("java_binary", BinaryFactory)
-	android.RegisterModuleType("java_binary_host", BinaryHostFactory)
-	android.RegisterModuleType("java_test", TestFactory)
-	android.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
-	android.RegisterModuleType("java_test_host", TestHostFactory)
-	android.RegisterModuleType("java_import", ImportFactory)
-	android.RegisterModuleType("java_import_host", ImportFactoryHost)
-	android.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
-	android.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
-	android.RegisterModuleType("dex_import", DexImportFactory)
-
-	android.RegisterSingletonType("logtags", LogtagsSingleton)
-	android.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
+	RegisterJavaBuildComponents(android.InitRegistrationContext)
 
 	// Register sdk member types.
 	android.RegisterSdkMemberType(&headerLibrarySdkMemberType{
@@ -71,6 +54,27 @@
 	})
 }
 
+func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("java_defaults", DefaultsFactory)
+
+	ctx.RegisterModuleType("java_library", LibraryFactory)
+	ctx.RegisterModuleType("java_library_static", LibraryStaticFactory)
+	ctx.RegisterModuleType("java_library_host", LibraryHostFactory)
+	ctx.RegisterModuleType("java_binary", BinaryFactory)
+	ctx.RegisterModuleType("java_binary_host", BinaryHostFactory)
+	ctx.RegisterModuleType("java_test", TestFactory)
+	ctx.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
+	ctx.RegisterModuleType("java_test_host", TestHostFactory)
+	ctx.RegisterModuleType("java_import", ImportFactory)
+	ctx.RegisterModuleType("java_import_host", ImportFactoryHost)
+	ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
+	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
+	ctx.RegisterModuleType("dex_import", DexImportFactory)
+
+	ctx.RegisterSingletonType("logtags", LogtagsSingleton)
+	ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
+}
+
 func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
 	if j.SocSpecific() || j.DeviceSpecific() ||
 		(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
@@ -594,8 +598,36 @@
 		}
 	}
 
-	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
-	ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
+	syspropPublicStubs := syspropPublicStubs(ctx.Config())
+
+	// rewriteSyspropLibs validates if a java module can link against platform's sysprop_library,
+	// and redirects dependency to public stub depending on the link type.
+	rewriteSyspropLibs := func(libs []string, prop string) []string {
+		// make a copy
+		ret := android.CopyOf(libs)
+
+		for idx, lib := range libs {
+			stub, ok := syspropPublicStubs[lib]
+
+			if !ok {
+				continue
+			}
+
+			linkType, _ := j.getLinkType(ctx.ModuleName())
+			if linkType == javaSystem {
+				ret[idx] = stub
+			} else if linkType != javaPlatform {
+				ctx.PropertyErrorf("sdk_version",
+					"can't link against sysprop_library %q from a module using public or core API",
+					lib)
+			}
+		}
+
+		return ret
+	}
+
+	ctx.AddVariationDependencies(nil, libTag, rewriteSyspropLibs(j.properties.Libs, "libs")...)
+	ctx.AddVariationDependencies(nil, staticLibTag, rewriteSyspropLibs(j.properties.Static_libs, "static_libs")...)
 
 	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
 	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
diff --git a/java/java_test.go b/java/java_test.go
index 49838c7..adc5ad1 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -63,37 +63,17 @@
 func testContext() *android.TestContext {
 
 	ctx := android.NewTestArchContext()
-	ctx.RegisterModuleType("android_app", AndroidAppFactory)
-	ctx.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
-	ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory)
-	ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
-	ctx.RegisterModuleType("android_test", AndroidTestFactory)
-	ctx.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
-	ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory)
-	ctx.RegisterModuleType("java_binary", BinaryFactory)
-	ctx.RegisterModuleType("java_binary_host", BinaryHostFactory)
-	ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
-	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
-	ctx.RegisterModuleType("java_library", LibraryFactory)
-	ctx.RegisterModuleType("java_library_host", LibraryHostFactory)
-	ctx.RegisterModuleType("java_test", TestFactory)
-	ctx.RegisterModuleType("java_import", ImportFactory)
-	ctx.RegisterModuleType("java_import_host", ImportFactoryHost)
-	ctx.RegisterModuleType("java_defaults", DefaultsFactory)
-	ctx.RegisterModuleType("java_system_modules", SystemModulesFactory)
-	ctx.RegisterModuleType("java_genrule", genRuleFactory)
+	RegisterJavaBuildComponents(ctx)
+	RegisterAppBuildComponents(ctx)
+	RegisterAARBuildComponents(ctx)
+	RegisterGenRuleBuildComponents(ctx)
+	RegisterSystemModulesBuildComponents(ctx)
 	ctx.RegisterModuleType("java_plugin", PluginFactory)
-	ctx.RegisterModuleType("dex_import", DexImportFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
-	ctx.RegisterModuleType("droiddoc", DroiddocFactory)
-	ctx.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
-	ctx.RegisterModuleType("droiddoc_template", ExportedDroiddocDirFactory)
-	ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
-	ctx.RegisterModuleType("java_sdk_library", SdkLibraryFactory)
-	ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory)
-	ctx.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
-	ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory)
+	RegisterDocsBuildComponents(ctx)
+	RegisterStubsBuildComponents(ctx)
+	RegisterSdkLibraryBuildComponents(ctx)
 	ctx.RegisterModuleType("prebuilt_apis", PrebuiltApisFactory)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
@@ -892,7 +872,7 @@
 
 func TestDroiddoc(t *testing.T) {
 	ctx, _ := testJava(t, `
-		droiddoc_template {
+		droiddoc_exported_dir {
 		    name: "droiddoc-templates-sdk",
 		    path: ".",
 		}
@@ -1038,7 +1018,7 @@
 
 func TestJavaSdkLibrary(t *testing.T) {
 	ctx, _ := testJava(t, `
-		droiddoc_template {
+		droiddoc_exported_dir {
 			name: "droiddoc-templates-sdk",
 			path: ".",
 		}
@@ -1244,7 +1224,7 @@
 		checkPatchModuleFlag(t, ctx, "foo", "")
 		expected := "java.base=.:" + buildDir
 		checkPatchModuleFlag(t, ctx, "bar", expected)
-		expected = "java.base=" + strings.Join([]string{".", buildDir, moduleToPath("ext"), moduleToPath("framework"), moduleToPath("updatable_media_stubs")}, ":")
+		expected = "java.base=" + strings.Join([]string{".", buildDir, moduleToPath("ext"), moduleToPath("framework")}, ":")
 		checkPatchModuleFlag(t, ctx, "baz", expected)
 	})
 }
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 7801634..bf6043a 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -41,30 +41,11 @@
 	p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath
 	path := android.PathForModuleSrc(ctx, String(p.properties.Src))
 
-	// Use the empty config if the compat config file idoesn't exist (can happen if @ChangeId
-	// annotation is not used).
-	emptyConfig := `'<?xml version="1.0" encoding="UTF-8" standalone="no"?><config/>'`
-	configPath := `compat/compat_config.xml`
-
 	rule.Command().
-		Text(`unzip`).
-		Flag(`-l`).
+		BuiltTool(ctx, "process-compat-config").
 		Input(path).
-		Text(`| grep`).
-		Flag(`-q`).
-		Text(configPath).
-		Text(`; if [ "$?" = "0" ] ; then`).
-		Text(`unzip`).
-		Flag(`-qp`).
-		Input(path).
-		Text(configPath).
 		Text(`>`).
-		Output(p.configFile).
-		Text(`; else echo `).
-		Text(emptyConfig).
-		Text(`>`).
-		Output(p.configFile).
-		Text(`; fi`)
+		Output(p.configFile)
 
 	p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig")
 	rule.Build(pctx, ctx, configFileName, "Extract compat/compat_config.xml and install it")
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e204659..32b2d1a 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -68,8 +68,7 @@
 // 2) HTML generation
 
 func init() {
-	android.RegisterModuleType("java_sdk_library", SdkLibraryFactory)
-	android.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory)
+	RegisterSdkLibraryBuildComponents(android.InitRegistrationContext)
 
 	android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
 		javaSdkLibraries := javaSdkLibraries(ctx.Config())
@@ -78,6 +77,11 @@
 	})
 }
 
+func RegisterSdkLibraryBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("java_sdk_library", SdkLibraryFactory)
+	ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory)
+}
+
 type sdkLibraryProperties struct {
 	// List of Java libraries that will be in the classpath when building stubs
 	Stub_only_libs []string `android:"arch_variant"`
diff --git a/java/sysprop.go b/java/sysprop.go
new file mode 100644
index 0000000..1a70499
--- /dev/null
+++ b/java/sysprop.go
@@ -0,0 +1,60 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+	"sync"
+
+	"android/soong/android"
+)
+
+type syspropLibraryInterface interface {
+	BaseModuleName() string
+	Owner() string
+	HasPublicStub() bool
+	JavaPublicStubName() string
+}
+
+var (
+	syspropPublicStubsKey  = android.NewOnceKey("syspropPublicStubsJava")
+	syspropPublicStubsLock sync.Mutex
+)
+
+func init() {
+	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("sysprop_java", SyspropMutator).Parallel()
+	})
+}
+
+func syspropPublicStubs(config android.Config) map[string]string {
+	return config.Once(syspropPublicStubsKey, func() interface{} {
+		return make(map[string]string)
+	}).(map[string]string)
+}
+
+// gather list of sysprop libraries owned by platform.
+func SyspropMutator(mctx android.BottomUpMutatorContext) {
+	if m, ok := mctx.Module().(syspropLibraryInterface); ok {
+		if m.Owner() != "Platform" || !m.HasPublicStub() {
+			return
+		}
+
+		syspropPublicStubs := syspropPublicStubs(mctx.Config())
+		syspropPublicStubsLock.Lock()
+		defer syspropPublicStubsLock.Unlock()
+
+		syspropPublicStubs[m.BaseModuleName()] = m.JavaPublicStubName()
+	}
+}
diff --git a/java/system_modules.go b/java/system_modules.go
index b56a401..ed2fc18 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -28,11 +28,15 @@
 // system modules in a runtime image using the jmod and jlink tools.
 
 func init() {
-	android.RegisterModuleType("java_system_modules", SystemModulesFactory)
+	RegisterSystemModulesBuildComponents(android.InitRegistrationContext)
 
 	pctx.SourcePathVariable("moduleInfoJavaPath", "build/soong/scripts/jars-to-module-info-java.sh")
 }
 
+func RegisterSystemModulesBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("java_system_modules", SystemModulesFactory)
+}
+
 var (
 	jarsTosystemModules = pctx.AndroidStaticRule("jarsTosystemModules", blueprint.RuleParams{
 		Command: `rm -rf ${outDir} ${workDir} && mkdir -p ${workDir}/jmod && ` +
diff --git a/java/testing.go b/java/testing.go
index c9f5905..e157dd0 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -138,7 +138,6 @@
 	extraModules := []string{
 		"core-lambda-stubs",
 		"ext",
-		"updatable_media_stubs",
 		"android_stubs_current",
 		"android_system_stubs_current",
 		"android_test_stubs_current",
diff --git a/sdk/testing.go b/sdk/testing.go
index 77ba2e6..0aac1a4 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -78,12 +78,9 @@
 	ctx.RegisterModuleType("package", android.PackageFactory)
 
 	// from java package
-	ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
-	ctx.RegisterModuleType("java_defaults", java.DefaultsFactory)
-	ctx.RegisterModuleType("java_library", java.LibraryFactory)
-	ctx.RegisterModuleType("java_import", java.ImportFactory)
-	ctx.RegisterModuleType("droidstubs", java.DroidstubsFactory)
-	ctx.RegisterModuleType("prebuilt_stubs_sources", java.PrebuiltStubsSourcesFactory)
+	java.RegisterJavaBuildComponents(ctx)
+	java.RegisterAppBuildComponents(ctx)
+	java.RegisterStubsBuildComponents(ctx)
 
 	// from cc package
 	ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 1fc94db..ce404f8 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -35,6 +35,7 @@
 type syspropGenProperties struct {
 	Srcs  []string `android:"path"`
 	Scope string
+	Name  *string
 }
 
 type syspropJavaGenRule struct {
@@ -142,6 +143,9 @@
 
 	// list of .sysprop files which defines the properties.
 	Srcs []string `android:"path"`
+
+	// Whether public stub exists or not.
+	Public_stub *bool `blueprint:"mutated"`
 }
 
 var (
@@ -157,18 +161,37 @@
 	return m.BaseModuleName() + "_sysprop_library"
 }
 
+func (m *syspropLibrary) Owner() string {
+	return m.properties.Property_owner
+}
+
 func (m *syspropLibrary) CcModuleName() string {
 	return "lib" + m.BaseModuleName()
 }
 
+func (m *syspropLibrary) JavaPublicStubName() string {
+	if proptools.Bool(m.properties.Public_stub) {
+		return m.BaseModuleName() + "_public"
+	}
+	return ""
+}
+
 func (m *syspropLibrary) javaGenModuleName() string {
 	return m.BaseModuleName() + "_java_gen"
 }
 
+func (m *syspropLibrary) javaGenPublicStubName() string {
+	return m.BaseModuleName() + "_java_gen_public"
+}
+
 func (m *syspropLibrary) BaseModuleName() string {
 	return m.ModuleBase.Name()
 }
 
+func (m *syspropLibrary) HasPublicStub() bool {
+	return proptools.Bool(m.properties.Public_stub)
+}
+
 func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	baseModuleName := m.BaseModuleName()
 
@@ -274,6 +297,36 @@
 	return m
 }
 
+type ccLibraryProperties struct {
+	Name             *string
+	Srcs             []string
+	Soc_specific     *bool
+	Device_specific  *bool
+	Product_specific *bool
+	Sysprop          struct {
+		Platform *bool
+	}
+	Header_libs        []string
+	Shared_libs        []string
+	Required           []string
+	Recovery           *bool
+	Recovery_available *bool
+	Vendor_available   *bool
+}
+
+type javaLibraryProperties struct {
+	Name             *string
+	Srcs             []string
+	Soc_specific     *bool
+	Device_specific  *bool
+	Product_specific *bool
+	Required         []string
+	Sdk_version      *string
+	Installable      *bool
+	Libs             []string
+	Stem             *string
+}
+
 func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
 	if len(m.properties.Srcs) == 0 {
 		ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
@@ -304,120 +357,107 @@
 		return
 	}
 
-	socSpecific := ctx.SocSpecific()
-	deviceSpecific := ctx.DeviceSpecific()
-	productSpecific := ctx.ProductSpecific()
-
-	owner := m.properties.Property_owner
+	// ctx's Platform or Specific functions represent where this sysprop_library installed.
+	installedInSystem := ctx.Platform() || ctx.SystemExtSpecific()
+	installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific()
+	isOwnerPlatform := false
 	stub := "sysprop-library-stub-"
 
-	switch owner {
+	switch m.Owner() {
 	case "Platform":
 		// Every partition can access platform-defined properties
 		stub += "platform"
+		isOwnerPlatform = true
 	case "Vendor":
 		// System can't access vendor's properties
-		if !socSpecific && !deviceSpecific && !productSpecific {
+		if installedInSystem {
 			ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
 				"System can't access sysprop_library owned by Vendor")
 		}
 		stub += "vendor"
 	case "Odm":
 		// Only vendor can access Odm-defined properties
-		if !socSpecific && !deviceSpecific {
+		if !installedInVendorOrOdm {
 			ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
 				"Odm-defined properties should be accessed only in Vendor or Odm")
 		}
 		stub += "vendor"
 	default:
 		ctx.PropertyErrorf("property_owner",
-			"Unknown value %s: must be one of Platform, Vendor or Odm", owner)
+			"Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner())
 	}
 
-	ccProps := struct {
-		Name             *string
-		Srcs             []string
-		Soc_specific     *bool
-		Device_specific  *bool
-		Product_specific *bool
-		Sysprop          struct {
-			Platform *bool
-		}
-		Header_libs        []string
-		Shared_libs        []string
-		Required           []string
-		Recovery           *bool
-		Recovery_available *bool
-		Vendor_available   *bool
-	}{}
-
+	ccProps := ccLibraryProperties{}
 	ccProps.Name = proptools.StringPtr(m.CcModuleName())
 	ccProps.Srcs = m.properties.Srcs
-	ccProps.Soc_specific = proptools.BoolPtr(socSpecific)
-	ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
-	ccProps.Product_specific = proptools.BoolPtr(productSpecific)
-	ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
+	ccProps.Soc_specific = proptools.BoolPtr(ctx.SocSpecific())
+	ccProps.Device_specific = proptools.BoolPtr(ctx.DeviceSpecific())
+	ccProps.Product_specific = proptools.BoolPtr(ctx.ProductSpecific())
+	ccProps.Sysprop.Platform = proptools.BoolPtr(isOwnerPlatform)
 	ccProps.Header_libs = []string{"libbase_headers"}
 	ccProps.Shared_libs = []string{"liblog"}
 	ccProps.Recovery_available = m.properties.Recovery_available
 	ccProps.Vendor_available = m.properties.Vendor_available
-
 	ctx.CreateModule(cc.LibraryFactory, &ccProps)
 
-	// internal scope contains all properties
-	// public scope only contains public properties
-	// use public if the owner is different from client
 	scope := "internal"
-	isProduct := ctx.ProductSpecific()
-	isVendor := ctx.SocSpecific()
-	isOwnerPlatform := owner == "Platform"
 
-	if isProduct {
-		// product can't own any sysprop_library now, so product must use public scope
+	// We need to only use public version, if the partition where sysprop_library will be installed
+	// is different from owner.
+
+	if ctx.ProductSpecific() {
+		// Currently product partition can't own any sysprop_library.
 		scope = "public"
-	} else if isVendor && isOwnerPlatform {
-		// vendor and odm can only use the public properties from the platform
+	} else if isOwnerPlatform && installedInVendorOrOdm {
+		// Vendor or Odm should use public version of Platform's sysprop_library.
 		scope = "public"
 	}
 
-	javaGenProps := struct {
-		Srcs  []string
-		Scope string
-		Name  *string
-	}{
+	ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
 		Srcs:  m.properties.Srcs,
 		Scope: scope,
 		Name:  proptools.StringPtr(m.javaGenModuleName()),
+	})
+
+	ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
+		Name:             proptools.StringPtr(m.BaseModuleName()),
+		Srcs:             []string{":" + m.javaGenModuleName()},
+		Soc_specific:     proptools.BoolPtr(ctx.SocSpecific()),
+		Device_specific:  proptools.BoolPtr(ctx.DeviceSpecific()),
+		Product_specific: proptools.BoolPtr(ctx.ProductSpecific()),
+		Installable:      m.properties.Installable,
+		Sdk_version:      proptools.StringPtr("core_current"),
+		Libs:             []string{stub},
+	})
+
+	// if platform sysprop_library is installed in /system or /system-ext, we regard it as an API
+	// and allow any modules (even from different partition) to link against the sysprop_library.
+	// To do that, we create a public stub and expose it to modules with sdk_version: system_*.
+	if isOwnerPlatform && installedInSystem {
+		m.properties.Public_stub = proptools.BoolPtr(true)
+		ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
+			Srcs:  m.properties.Srcs,
+			Scope: "public",
+			Name:  proptools.StringPtr(m.javaGenPublicStubName()),
+		})
+
+		ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
+			Name:        proptools.StringPtr(m.JavaPublicStubName()),
+			Srcs:        []string{":" + m.javaGenPublicStubName()},
+			Installable: proptools.BoolPtr(false),
+			Sdk_version: proptools.StringPtr("core_current"),
+			Libs:        []string{stub},
+			Stem:        proptools.StringPtr(m.BaseModuleName()),
+		})
 	}
-
-	ctx.CreateModule(syspropJavaGenFactory, &javaGenProps)
-
-	javaProps := struct {
-		Name             *string
-		Srcs             []string
-		Soc_specific     *bool
-		Device_specific  *bool
-		Product_specific *bool
-		Required         []string
-		Sdk_version      *string
-		Installable      *bool
-		Libs             []string
-	}{}
-
-	javaProps.Name = proptools.StringPtr(m.BaseModuleName())
-	javaProps.Srcs = []string{":" + *javaGenProps.Name}
-	javaProps.Soc_specific = proptools.BoolPtr(socSpecific)
-	javaProps.Device_specific = proptools.BoolPtr(deviceSpecific)
-	javaProps.Product_specific = proptools.BoolPtr(productSpecific)
-	javaProps.Installable = m.properties.Installable
-	javaProps.Sdk_version = proptools.StringPtr("core_current")
-	javaProps.Libs = []string{stub}
-
-	ctx.CreateModule(java.LibraryFactory, &javaProps)
 }
 
 func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
 	if m, ok := ctx.Module().(*syspropLibrary); ok {
 		ctx.AddReverseDependency(m, nil, m.javaGenModuleName())
+
+		if proptools.Bool(m.properties.Public_stub) {
+			ctx.AddReverseDependency(m, nil, m.javaGenPublicStubName())
+		}
 	}
 }
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 9d4c1aa..d24262d 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -24,6 +24,7 @@
 	"strings"
 	"testing"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -55,9 +56,10 @@
 func testContext(config android.Config) *android.TestContext {
 
 	ctx := android.NewTestArchContext()
-	ctx.RegisterModuleType("android_app", java.AndroidAppFactory)
-	ctx.RegisterModuleType("java_library", java.LibraryFactory)
-	ctx.RegisterModuleType("java_system_modules", java.SystemModulesFactory)
+	java.RegisterJavaBuildComponents(ctx)
+	java.RegisterAppBuildComponents(ctx)
+	java.RegisterSystemModulesBuildComponents(ctx)
+
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@@ -76,7 +78,8 @@
 		ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
 		ctx.BottomUp("version", cc.VersionMutator).Parallel()
 		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
-		ctx.BottomUp("sysprop", cc.SyspropMutator).Parallel()
+		ctx.BottomUp("sysprop_cc", cc.SyspropMutator).Parallel()
+		ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel()
 	})
 
 	ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
@@ -205,6 +208,13 @@
 		}
 
 		java_library {
+			name: "java-platform-private",
+			srcs: ["c.java"],
+			platform_apis: true,
+			libs: ["sysprop-platform"],
+		}
+
+		java_library {
 			name: "java-product",
 			srcs: ["c.java"],
 			sdk_version: "system_current",
@@ -302,6 +312,7 @@
 	}
 
 	ctx.ModuleForTests("sysprop-platform", "android_common")
+	ctx.ModuleForTests("sysprop-platform_public", "android_common")
 	ctx.ModuleForTests("sysprop-vendor", "android_common")
 
 	// Check for exported includes
@@ -354,4 +365,17 @@
 		t.Errorf("flags for vendor must contain %#v and %#v, but was %#v.",
 			platformPublicVendorPath, vendorInternalPath, vendorFlags)
 	}
+
+	// Java modules linking against system API should use public stub
+	javaSystemApiClient := ctx.ModuleForTests("java-platform", "android_common")
+	publicStubFound := false
+	ctx.VisitDirectDeps(javaSystemApiClient.Module(), func(dep blueprint.Module) {
+		if dep.Name() == "sysprop-platform_public" {
+			publicStubFound = true
+		}
+	})
+	if !publicStubFound {
+		t.Errorf("system api client should use public stub")
+	}
+
 }