Merge "Add double_loadable property and checks for it"
diff --git a/Android.bp b/Android.bp
index ad2ad47..5396664 100644
--- a/Android.bp
+++ b/Android.bp
@@ -46,6 +46,7 @@
         "android/defaults.go",
         "android/defs.go",
         "android/expand.go",
+        "android/filegroup.go",
         "android/hooks.go",
         "android/makevars.go",
         "android/module.go",
@@ -56,6 +57,7 @@
         "android/package_ctx.go",
         "android/paths.go",
         "android/prebuilt.go",
+        "android/prebuilt_etc.go",
         "android/proto.go",
         "android/register.go",
         "android/singleton.go",
@@ -186,7 +188,6 @@
         "soong-shared",
     ],
     srcs: [
-        "genrule/filegroup.go",
         "genrule/genrule.go",
     ],
     pluginFor: ["soong_build"],
@@ -232,6 +233,7 @@
         "java/java.go",
         "java/java_resources.go",
         "java/proto.go",
+        "java/sdk_library.go",
         "java/system_modules.go",
     ],
     testSrcs: [
diff --git a/android/config.go b/android/config.go
index 7122f48..40ba8c1 100644
--- a/android/config.go
+++ b/android/config.go
@@ -476,6 +476,10 @@
 	return strconv.Itoa(c.PlatformSdkVersionInt())
 }
 
+func (c *config) PlatformSdkCodename() string {
+	return String(c.productVariables.Platform_sdk_codename)
+}
+
 func (c *config) MinSupportedSdkVersion() int {
 	return 14
 }
@@ -488,6 +492,14 @@
 	}
 }
 
+func (c *config) DefaultAppTargetSdk() string {
+	if Bool(c.productVariables.Platform_sdk_final) {
+		return c.PlatformSdkVersion()
+	} else {
+		return c.PlatformSdkCodename()
+	}
+}
+
 func (c *config) AppsDefaultVersionName() string {
 	return String(c.productVariables.AppsDefaultVersionName)
 }
diff --git a/genrule/filegroup.go b/android/filegroup.go
similarity index 75%
rename from genrule/filegroup.go
rename to android/filegroup.go
index 2cff5fe..b284ce0 100644
--- a/genrule/filegroup.go
+++ b/android/filegroup.go
@@ -12,17 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package genrule
+package android
 
 import (
-	"android/soong/android"
 	"io"
 	"strings"
 	"text/template"
 )
 
 func init() {
-	android.RegisterModuleType("filegroup", FileGroupFactory)
+	RegisterModuleType("filegroup", FileGroupFactory)
 }
 
 type fileGroupProperties struct {
@@ -43,34 +42,34 @@
 }
 
 type fileGroup struct {
-	android.ModuleBase
+	ModuleBase
 	properties fileGroupProperties
-	srcs       android.Paths
+	srcs       Paths
 }
 
-var _ android.SourceFileProducer = (*fileGroup)(nil)
+var _ SourceFileProducer = (*fileGroup)(nil)
 
 // filegroup modules contain a list of files, and can be used to export files across package
 // boundaries.  filegroups (and genrules) can be referenced from srcs properties of other modules
 // using the syntax ":module".
-func FileGroupFactory() android.Module {
+func FileGroupFactory() Module {
 	module := &fileGroup{}
 	module.AddProperties(&module.properties)
-	android.InitAndroidModule(module)
+	InitAndroidModule(module)
 	return module
 }
 
-func (fg *fileGroup) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ExtractSourcesDeps(ctx, fg.properties.Srcs)
-	android.ExtractSourcesDeps(ctx, fg.properties.Exclude_srcs)
+func (fg *fileGroup) DepsMutator(ctx BottomUpMutatorContext) {
+	ExtractSourcesDeps(ctx, fg.properties.Srcs)
+	ExtractSourcesDeps(ctx, fg.properties.Exclude_srcs)
 }
 
-func (fg *fileGroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
 	fg.srcs = ctx.ExpandSourcesSubDir(fg.properties.Srcs, fg.properties.Exclude_srcs, String(fg.properties.Path))
 }
 
-func (fg *fileGroup) Srcs() android.Paths {
-	return append(android.Paths{}, fg.srcs...)
+func (fg *fileGroup) Srcs() Paths {
+	return append(Paths{}, fg.srcs...)
 }
 
 var androidMkTemplate = template.Must(template.New("filegroup").Parse(`
@@ -81,9 +80,9 @@
 .KATI_READONLY := {{.makeVar}}
 `))
 
-func (fg *fileGroup) AndroidMk() android.AndroidMkData {
-	return android.AndroidMkData{
-		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+func (fg *fileGroup) AndroidMk() AndroidMkData {
+	return AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
 			if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
 				androidMkTemplate.Execute(w, map[string]string{
 					"makeVar": makeVar,
diff --git a/android/module.go b/android/module.go
index a011f57..552d165 100644
--- a/android/module.go
+++ b/android/module.go
@@ -323,6 +323,7 @@
 		&base.nameProperties,
 		&base.commonProperties,
 		&base.variableProperties)
+	base.customizableProperties = m.GetProperties()
 }
 
 func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
@@ -500,6 +501,22 @@
 				*a.hostAndDeviceProperties.Device_supported)
 }
 
+func (a *ModuleBase) Platform() bool {
+	return !a.DeviceSpecific() && !a.SocSpecific() && !a.ProductSpecific()
+}
+
+func (a *ModuleBase) DeviceSpecific() bool {
+	return Bool(a.commonProperties.Device_specific)
+}
+
+func (a *ModuleBase) SocSpecific() bool {
+	return Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
+}
+
+func (a *ModuleBase) ProductSpecific() bool {
+	return Bool(a.commonProperties.Product_specific)
+}
+
 func (a *ModuleBase) Enabled() bool {
 	if a.commonProperties.Enabled == nil {
 		return !a.Os().DefaultDisabled
diff --git a/android/paths.go b/android/paths.go
index 87efe53..91dd9a6 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -308,6 +308,18 @@
 	return list[totalSkip:]
 }
 
+// ReversePaths returns a copy of a Paths in reverse order.
+func ReversePaths(list Paths) Paths {
+	if list == nil {
+		return nil
+	}
+	ret := make(Paths, len(list))
+	for i := range list {
+		ret[i] = list[len(list)-1-i]
+	}
+	return ret
+}
+
 func indexPathList(s Path, list []Path) int {
 	for i, l := range list {
 		if l == s {
diff --git a/android/paths_test.go b/android/paths_test.go
index 0075798..cd9fbfd 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -474,10 +474,7 @@
 	}
 
 	paths := makePaths()
-	reversePaths := make(Paths, len(paths))
-	for i, v := range paths {
-		reversePaths[len(paths)-i-1] = v
-	}
+	reversePaths := ReversePaths(paths)
 
 	sortedPaths := PathsToDirectorySortedPaths(paths)
 	reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 9356aab..47c5cf5 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -59,7 +59,9 @@
 		return nil
 	}
 
-	return PathForModuleSrc(ctx, (*p.srcs)[0])
+	// Return the singleton source after expanding any filegroup in the
+	// sources.
+	return ctx.ExpandSource((*p.srcs)[0], "")
 }
 
 func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
@@ -79,7 +81,7 @@
 
 func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
 	ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
-	ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
+	ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
 }
 
 // prebuiltMutator ensures that there is always a module with an undecorated name, and marks
@@ -119,10 +121,12 @@
 	}
 }
 
-// PrebuiltReplaceMutator replaces dependencies on the source module with dependencies on the
-// prebuilt when both modules exist and the prebuilt should be used.  When the prebuilt should not
-// be used, disable installing it.
-func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) {
+// PrebuiltPostDepsMutator does two operations.  It replace dependencies on the
+// source module with dependencies on the prebuilt when both modules exist and
+// the prebuilt should be used.  When the prebuilt should not be used, disable
+// installing it.  Secondly, it also adds a sourcegroup to any filegroups found
+// in the prebuilt's 'Srcs' property.
+func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
 	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
 		p := m.Prebuilt()
 		name := m.base().BaseModuleName()
@@ -133,6 +137,9 @@
 		} else {
 			m.SkipInstall()
 		}
+		if len(*p.srcs) > 0 {
+			ExtractSourceDeps(ctx, &(*p.srcs)[0])
+		}
 	}
 }
 
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
new file mode 100644
index 0000000..fee2c49
--- /dev/null
+++ b/android/prebuilt_etc.go
@@ -0,0 +1,91 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 android
+
+import (
+	"fmt"
+	"io"
+)
+
+// prebuilt_etc is for prebuilts that will be installed to
+// <partition>/etc/<subdir>
+
+func init() {
+	RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
+}
+
+type prebuiltEtcProperties struct {
+	// Source file of this prebuilt.
+	Srcs []string `android:"arch_variant"`
+
+	// optional subdirectory under which this file is installed into
+	Sub_dir *string `android:"arch_variant"`
+}
+
+type prebuiltEtc struct {
+	ModuleBase
+	prebuilt Prebuilt
+
+	properties prebuiltEtcProperties
+
+	sourceFilePath Path
+	installDirPath OutputPath
+}
+
+func (p *prebuiltEtc) Prebuilt() *Prebuilt {
+	return &p.prebuilt
+}
+
+func (p *prebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
+	if len(p.properties.Srcs) == 0 {
+		ctx.PropertyErrorf("srcs", "missing prebuilt source file")
+	}
+
+	if len(p.properties.Srcs) > 1 {
+		ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
+	}
+
+	// To support ":modulename" in src
+	ExtractSourceDeps(ctx, &(p.properties.Srcs)[0])
+}
+
+func (p *prebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
+	p.sourceFilePath = ctx.ExpandSource(p.properties.Srcs[0], "srcs")
+	p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir))
+}
+
+func (p *prebuiltEtc) AndroidMk() AndroidMkData {
+	return AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
+			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
+			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+			fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+			fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
+			fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
+			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.sourceFilePath.String())
+			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
+			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
+		},
+	}
+}
+
+func PrebuiltEtcFactory() Module {
+	module := &prebuiltEtc{}
+	module.AddProperties(&module.properties)
+
+	InitPrebuiltModule(module, &(module.properties.Srcs))
+	InitAndroidModule(module)
+	return module
+}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 69ce16a..cd1ffae 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -109,6 +109,19 @@
 			}`,
 		prebuilt: false,
 	},
+	{
+		name: "prebuilt file from filegroup preferred",
+		modules: `
+			filegroup {
+				name: "fg",
+			}
+			prebuilt {
+				name: "bar",
+				prefer: true,
+				srcs: [":fg"],
+			}`,
+		prebuilt: true,
+	},
 }
 
 func TestPrebuilts(t *testing.T) {
@@ -125,6 +138,7 @@
 			ctx := NewTestContext()
 			ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators)
 			ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators)
+			ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory))
 			ctx.RegisterModuleType("prebuilt", ModuleFactoryAdaptor(newPrebuiltModule))
 			ctx.RegisterModuleType("source", ModuleFactoryAdaptor(newSourceModule))
 			ctx.Register()
diff --git a/android/variable.go b/android/variable.go
index 3eee988..2057903 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -110,6 +110,7 @@
 	DateFromFile        *string `json:",omitempty"`
 
 	Platform_sdk_version              *int     `json:",omitempty"`
+	Platform_sdk_codename             *string  `json:",omitempty"`
 	Platform_sdk_final                *bool    `json:",omitempty"`
 	Platform_version_active_codenames []string `json:",omitempty"`
 	Platform_version_future_codenames []string `json:",omitempty"`
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 9bcb783..5824168 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -243,6 +243,7 @@
 			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
 				strings.Join(benchmark.Properties.Test_suites, " "))
 		}
+		fmt.Fprintln(w, "LOCAL_NATIVE_BENCHMARK := true")
 	})
 
 	androidMkWriteTestData(benchmark.data, ctx, ret)
diff --git a/cc/builder.go b/cc/builder.go
index cec0056..cb09d09 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -203,7 +203,7 @@
 
 			commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -check-all-apis -o ${out} -new $in -old $referenceDump)"
 			distAbiDiffDir := android.PathForDist(ctx, "abidiffs")
-			commandStr += "|| (echo ' ---- Please update abi references by running platform/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'"
+			commandStr += "|| (echo ' ---- Please update abi references by running $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'"
 			if distAbiDiffDir.Valid() {
 				commandStr += " && (mkdir -p " + distAbiDiffDir.String() + " && cp ${out} " + distAbiDiffDir.String() + ")"
 			}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 10c1aba..9b4cc0f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -16,7 +16,6 @@
 
 import (
 	"android/soong/android"
-	"android/soong/genrule"
 
 	"fmt"
 	"io/ioutil"
@@ -62,7 +61,7 @@
 	ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
 	ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
-	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
+	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("image", vendorMutator).Parallel()
 		ctx.BottomUp("link", linkageMutator).Parallel()
diff --git a/cc/config/global.go b/cc/config/global.go
index 051eba5..d998ca2 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -99,7 +99,7 @@
 
 	hostGlobalLdflags = []string{}
 
-	hostGlobalLldflags = []string{}
+	hostGlobalLldflags = []string{"-fuse-ld=lld"}
 
 	commonGlobalCppflags = []string{
 		"-Wsign-promo",
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 4aa8242..4ec2b31 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -73,10 +73,16 @@
 
 	darwinClangLdflags = ClangFilterUnknownCflags(darwinLdflags)
 
+	darwinClangLldflags = ClangFilterUnknownLldflags(darwinClangLdflags)
+
 	darwinX86ClangLdflags = ClangFilterUnknownCflags(darwinX86Ldflags)
 
+	darwinX86ClangLldflags = ClangFilterUnknownLldflags(darwinX86ClangLdflags)
+
 	darwinX8664ClangLdflags = ClangFilterUnknownCflags(darwinX8664Ldflags)
 
+	darwinX8664ClangLldflags = ClangFilterUnknownLldflags(darwinX8664ClangLdflags)
+
 	darwinSupportedSdkVersions = []string{
 		"10.10",
 		"10.11",
@@ -141,6 +147,7 @@
 
 	pctx.StaticVariable("DarwinClangCflags", strings.Join(darwinClangCflags, " "))
 	pctx.StaticVariable("DarwinClangLdflags", strings.Join(darwinClangLdflags, " "))
+	pctx.StaticVariable("DarwinClangLldflags", strings.Join(darwinClangLldflags, " "))
 
 	// Extended cflags
 	pctx.StaticVariable("DarwinX86Cflags", strings.Join(darwinX86Cflags, " "))
@@ -152,7 +159,9 @@
 	pctx.StaticVariable("DarwinX8664ClangCflags",
 		strings.Join(ClangFilterUnknownCflags(darwinX8664Cflags), " "))
 	pctx.StaticVariable("DarwinX86ClangLdflags", strings.Join(darwinX86ClangLdflags, " "))
+	pctx.StaticVariable("DarwinX86ClangLldflags", strings.Join(darwinX86ClangLldflags, " "))
 	pctx.StaticVariable("DarwinX8664ClangLdflags", strings.Join(darwinX8664ClangLdflags, " "))
+	pctx.StaticVariable("DarwinX8664ClangLldflags", strings.Join(darwinX8664ClangLldflags, " "))
 	pctx.StaticVariable("DarwinX86YasmFlags", "-f macho -m x86")
 	pctx.StaticVariable("DarwinX8664YasmFlags", "-f macho -m amd64")
 }
@@ -274,8 +283,7 @@
 }
 
 func (t *toolchainDarwinX86) ClangLldflags() string {
-	// TODO: define and use Darwin*ClangLldflags
-	return "${config.DarwinClangLdflags} ${config.DarwinX86ClangLdflags}"
+	return "${config.DarwinClangLldflags} ${config.DarwinX86ClangLldflags}"
 }
 
 func (t *toolchainDarwinX8664) ClangLdflags() string {
@@ -283,8 +291,7 @@
 }
 
 func (t *toolchainDarwinX8664) ClangLldflags() string {
-	// TODO: define and use Darwin*ClangLldflags
-	return "${config.DarwinClangLdflags} ${config.DarwinX8664ClangLdflags}"
+	return "${config.DarwinClangLldflags} ${config.DarwinX8664ClangLldflags}"
 }
 
 func (t *toolchainDarwinX86) YasmFlags() string {
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 057e905..a9fb1f6 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -61,11 +61,14 @@
 		// Use the device gcc toolchain
 		"--gcc-toolchain=${LinuxBionicGccRoot}",
 	})
+
+	linuxBionicLldflags = ClangFilterUnknownLldflags(linuxBionicLdflags)
 )
 
 func init() {
 	pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
 	pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
+	pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLldflags, " "))
 
 	pctx.StaticVariable("LinuxBionicIncludeFlags", bionicHeaders("x86"))
 
@@ -127,8 +130,7 @@
 }
 
 func (t *toolchainLinuxBionic) ClangLldflags() string {
-	// TODO: define and use LinuxBionicLldflags
-	return "${config.LinuxBionicLdflags}"
+	return "${config.LinuxBionicLldflags}"
 }
 
 func (t *toolchainLinuxBionic) ToolchainClangCflags() string {
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 6144fc2..354500e 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -78,18 +78,24 @@
 		"--sysroot ${LinuxGccRoot}/sysroot",
 	}...)
 
+	linuxClangLldflags = ClangFilterUnknownLldflags(linuxClangLdflags)
+
 	linuxX86ClangLdflags = append(ClangFilterUnknownCflags(linuxX86Ldflags), []string{
 		"-B${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}/32",
 		"-L${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}/32",
 		"-L${LinuxGccRoot}/${LinuxGccTriple}/lib32",
 	}...)
 
+	linuxX86ClangLldflags = ClangFilterUnknownLldflags(linuxX86ClangLdflags)
+
 	linuxX8664ClangLdflags = append(ClangFilterUnknownCflags(linuxX8664Ldflags), []string{
 		"-B${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}",
 		"-L${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}",
 		"-L${LinuxGccRoot}/${LinuxGccTriple}/lib64",
 	}...)
 
+	linuxX8664ClangLldflags = ClangFilterUnknownLldflags(linuxX8664ClangLdflags)
+
 	linuxClangCppflags = []string{
 		"-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}",
 		"-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}/backward",
@@ -134,6 +140,7 @@
 
 	pctx.StaticVariable("LinuxClangCflags", strings.Join(linuxClangCflags, " "))
 	pctx.StaticVariable("LinuxClangLdflags", strings.Join(linuxClangLdflags, " "))
+	pctx.StaticVariable("LinuxClangLldflags", strings.Join(linuxClangLldflags, " "))
 	pctx.StaticVariable("LinuxClangCppflags", strings.Join(linuxClangCppflags, " "))
 
 	// Extended cflags
@@ -147,7 +154,9 @@
 	pctx.StaticVariable("LinuxX8664ClangCflags",
 		strings.Join(ClangFilterUnknownCflags(linuxX8664Cflags), " "))
 	pctx.StaticVariable("LinuxX86ClangLdflags", strings.Join(linuxX86ClangLdflags, " "))
+	pctx.StaticVariable("LinuxX86ClangLldflags", strings.Join(linuxX86ClangLldflags, " "))
 	pctx.StaticVariable("LinuxX8664ClangLdflags", strings.Join(linuxX8664ClangLdflags, " "))
+	pctx.StaticVariable("LinuxX8664ClangLldflags", strings.Join(linuxX8664ClangLldflags, " "))
 	pctx.StaticVariable("LinuxX86ClangCppflags", strings.Join(linuxX86ClangCppflags, " "))
 	pctx.StaticVariable("LinuxX8664ClangCppflags", strings.Join(linuxX8664ClangCppflags, " "))
 	// Yasm flags
@@ -242,8 +251,7 @@
 }
 
 func (t *toolchainLinuxX86) ClangLldflags() string {
-	// TODO: define and use Linux*ClangLldflags
-	return "${config.LinuxClangLdflags} ${config.LinuxX86ClangLdflags}"
+	return "${config.LinuxClangLldflags} ${config.LinuxX86ClangLldflags}"
 }
 
 func (t *toolchainLinuxX8664) ClangLdflags() string {
@@ -251,8 +259,7 @@
 }
 
 func (t *toolchainLinuxX8664) ClangLldflags() string {
-	// TODO: define and use Linux*ClangLldflags
-	return "${config.LinuxClangLdflags} ${config.LinuxX8664ClangLdflags}"
+	return "${config.LinuxClangLldflags} ${config.LinuxX8664ClangLldflags}"
 }
 
 func (t *toolchainLinuxX86) YasmFlags() string {
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index fea6291..6fbff9f 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -64,7 +64,8 @@
 	windowsLdflags = []string{
 		"--enable-stdcall-fixup",
 	}
-	windowsClangLdflags = append(ClangFilterUnknownCflags(windowsLdflags), []string{}...)
+	windowsClangLdflags  = append(ClangFilterUnknownCflags(windowsLdflags), []string{}...)
+	windowsClangLldflags = ClangFilterUnknownLldflags(windowsClangLdflags)
 
 	windowsX86Cflags = []string{
 		"-m32",
@@ -84,6 +85,7 @@
 		"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/lib32",
 	}...)
+	windowsX86ClangLldflags = ClangFilterUnknownLldflags(windowsX86ClangLdflags)
 
 	windowsX8664Ldflags = []string{
 		"-m64",
@@ -94,6 +96,7 @@
 		"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/lib64",
 	}...)
+	windowsX8664ClangLldflags = ClangFilterUnknownLldflags(windowsX8664ClangLdflags)
 
 	windowsAvailableLibraries = addPrefix([]string{
 		"gdi32",
@@ -128,6 +131,7 @@
 
 	pctx.StaticVariable("WindowsClangCflags", strings.Join(windowsClangCflags, " "))
 	pctx.StaticVariable("WindowsClangLdflags", strings.Join(windowsClangLdflags, " "))
+	pctx.StaticVariable("WindowsClangLldflags", strings.Join(windowsClangLldflags, " "))
 	pctx.StaticVariable("WindowsClangCppflags", strings.Join(windowsClangCppflags, " "))
 
 	pctx.StaticVariable("WindowsX86Cflags", strings.Join(windowsX86Cflags, " "))
@@ -140,7 +144,9 @@
 	pctx.StaticVariable("WindowsX8664ClangCflags",
 		strings.Join(ClangFilterUnknownCflags(windowsX8664Cflags), " "))
 	pctx.StaticVariable("WindowsX86ClangLdflags", strings.Join(windowsX86ClangLdflags, " "))
+	pctx.StaticVariable("WindowsX86ClangLldflags", strings.Join(windowsX86ClangLldflags, " "))
 	pctx.StaticVariable("WindowsX8664ClangLdflags", strings.Join(windowsX8664ClangLdflags, " "))
+	pctx.StaticVariable("WindowsX8664ClangLldflags", strings.Join(windowsX8664ClangLldflags, " "))
 	pctx.StaticVariable("WindowsX86ClangCppflags", strings.Join(windowsX86ClangCppflags, " "))
 	pctx.StaticVariable("WindowsX8664ClangCppflags", strings.Join(windowsX8664ClangCppflags, " "))
 
@@ -246,8 +252,7 @@
 }
 
 func (t *toolchainWindowsX86) ClangLldflags() string {
-	// TODO: define and use Windows*ClangLldflags
-	return "${config.WindowsClangLdflags} ${config.WindowsX86ClangLdflags}"
+	return "${config.WindowsClangLldflags} ${config.WindowsX86ClangLldflags}"
 }
 
 func (t *toolchainWindowsX8664) ClangLdflags() string {
@@ -255,8 +260,7 @@
 }
 
 func (t *toolchainWindowsX8664) ClangLldflags() string {
-	// TODO: define and use Windows*ClangLldflags
-	return "${config.WindowsClangLdflags} ${config.WindowsX8664ClangLdflags}"
+	return "${config.WindowsClangLldflags} ${config.WindowsX8664ClangLldflags}"
 }
 
 func (t *toolchainWindows) ShlibSuffix() string {
diff --git a/cc/linker.go b/cc/linker.go
index 2176306..d9da404 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -59,7 +59,7 @@
 	No_libgcc *bool
 
 	// Use clang lld instead of gnu ld.
-	Use_clang_lld *bool
+	Use_clang_lld *bool `android:"arch_variant"`
 
 	// -l arguments to pass to linker for host-provided shared libraries
 	Host_ldlibs []string `android:"arch_variant"`
diff --git a/cc/test_data_test.go b/cc/test_data_test.go
index 4a7b0f7..56c3e38 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -22,7 +22,6 @@
 	"testing"
 
 	"android/soong/android"
-	"android/soong/genrule"
 )
 
 type dataFile struct {
@@ -129,7 +128,7 @@
 				"dir/bar/baz":    nil,
 			})
 			ctx.RegisterModuleType("filegroup",
-				android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
+				android.ModuleFactoryAdaptor(android.FileGroupFactory))
 			ctx.RegisterModuleType("test",
 				android.ModuleFactoryAdaptor(newTest))
 			ctx.Register()
diff --git a/java/aar.go b/java/aar.go
index 57c752c..13c5369 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -76,14 +76,11 @@
 
 	hasVersionCode := false
 	hasVersionName := false
-	hasProduct := false
 	for _, f := range a.aaptProperties.Aaptflags {
 		if strings.HasPrefix(f, "--version-code") {
 			hasVersionCode = true
 		} else if strings.HasPrefix(f, "--version-name") {
 			hasVersionName = true
-		} else if strings.HasPrefix(f, "--product") {
-			hasProduct = true
 		}
 	}
 
@@ -134,27 +131,12 @@
 	// SDK version flags
 	switch sdkVersion {
 	case "", "current", "system_current", "test_current":
-		sdkVersion = proptools.NinjaEscape([]string{ctx.Config().AppsDefaultVersionName()})[0]
+		sdkVersion = proptools.NinjaEscape([]string{ctx.Config().DefaultAppTargetSdk()})[0]
 	}
 
 	linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion)
 	linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion)
 
-	// Product characteristics
-	if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
-		linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
-	}
-
-	// Product AAPT config
-	for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
-		linkFlags = append(linkFlags, "-c", aaptConfig)
-	}
-
-	// Product AAPT preferred config
-	if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
-		linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
-	}
-
 	// Version code
 	if !hasVersionCode {
 		linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
diff --git a/java/androidmk.go b/java/androidmk.go
index dfbe7fa..8bde716 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -206,7 +206,9 @@
 				}
 
 				if len(app.rroDirs) > 0 {
-					fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(app.rroDirs.Strings(), " "))
+					// Reverse the order, Soong stores rroDirs in aapt2 order (low to high priority), but Make
+					// expects it in LOCAL_RESOURCE_DIRS order (high to low priority).
+					fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(android.ReversePaths(app.rroDirs).Strings(), " "))
 				}
 
 				if Bool(app.appProperties.Export_package_resources) {
diff --git a/java/app.go b/java/app.go
index 3e24ebc..dd83a0a 100644
--- a/java/app.go
+++ b/java/app.go
@@ -86,6 +86,28 @@
 		a.properties.Instrument = true
 	}
 
+	hasProduct := false
+	for _, f := range a.aaptProperties.Aaptflags {
+		if strings.HasPrefix(f, "--product") {
+			hasProduct = true
+		}
+	}
+
+	// Product characteristics
+	if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
+		linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
+	}
+
+	// Product AAPT config
+	for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
+		linkFlags = append(linkFlags, "-c", aaptConfig)
+	}
+
+	// Product AAPT preferred config
+	if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
+		linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+	}
+
 	// TODO: LOCAL_PACKAGE_OVERRIDES
 	//    $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
 
diff --git a/java/app_test.go b/java/app_test.go
index 7a61771..6770119 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -16,8 +16,10 @@
 
 import (
 	"android/soong/android"
+	"fmt"
 	"reflect"
 	"sort"
+	"strings"
 	"testing"
 )
 
@@ -240,3 +242,96 @@
 		})
 	}
 }
+
+func TestAppSdkVersion(t *testing.T) {
+	testCases := []struct {
+		name                  string
+		sdkVersion            string
+		platformSdkInt        int
+		platformSdkCodename   string
+		platformSdkFinal      bool
+		expectedMinSdkVersion string
+	}{
+		{
+			name:                  "current final SDK",
+			sdkVersion:            "current",
+			platformSdkInt:        27,
+			platformSdkCodename:   "REL",
+			platformSdkFinal:      true,
+			expectedMinSdkVersion: "27",
+		},
+		{
+			name:                  "current non-final SDK",
+			sdkVersion:            "current",
+			platformSdkInt:        27,
+			platformSdkCodename:   "OMR1",
+			platformSdkFinal:      false,
+			expectedMinSdkVersion: "OMR1",
+		},
+		{
+			name:                  "default final SDK",
+			sdkVersion:            "",
+			platformSdkInt:        27,
+			platformSdkCodename:   "REL",
+			platformSdkFinal:      true,
+			expectedMinSdkVersion: "27",
+		},
+		{
+			name:                  "default non-final SDK",
+			sdkVersion:            "",
+			platformSdkInt:        27,
+			platformSdkCodename:   "OMR1",
+			platformSdkFinal:      false,
+			expectedMinSdkVersion: "OMR1",
+		},
+		{
+			name:                  "14",
+			sdkVersion:            "14",
+			expectedMinSdkVersion: "14",
+		},
+	}
+
+	for _, moduleType := range []string{"android_app", "android_library"} {
+		for _, test := range testCases {
+			t.Run(moduleType+" "+test.name, func(t *testing.T) {
+				bp := fmt.Sprintf(`%s {
+					name: "foo",
+					srcs: ["a.java"],
+					sdk_version: "%s",
+				}`, moduleType, test.sdkVersion)
+
+				config := testConfig(nil)
+				config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
+				config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
+				config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
+
+				ctx := testAppContext(config, bp, nil)
+
+				run(t, ctx, config)
+
+				foo := ctx.ModuleForTests("foo", "android_common")
+				link := foo.Output("package-res.apk")
+				linkFlags := strings.Split(link.Args["flags"], " ")
+				min := android.IndexList("--min-sdk-version", linkFlags)
+				target := android.IndexList("--target-sdk-version", linkFlags)
+
+				if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
+					t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
+				}
+
+				gotMinSdkVersion := linkFlags[min+1]
+				gotTargetSdkVersion := linkFlags[target+1]
+
+				if gotMinSdkVersion != test.expectedMinSdkVersion {
+					t.Errorf("incorrect --min-sdk-version, expected %q got %q",
+						test.expectedMinSdkVersion, gotMinSdkVersion)
+				}
+
+				if gotTargetSdkVersion != test.expectedMinSdkVersion {
+					t.Errorf("incorrect --target-sdk-version, expected %q got %q",
+						test.expectedMinSdkVersion, gotTargetSdkVersion)
+				}
+			})
+		}
+	}
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 0224da5..0700487 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -306,6 +306,20 @@
 			default:
 				panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
 			}
+		case SdkLibraryDependency:
+			switch tag {
+			case libTag:
+				sdkVersion := String(j.properties.Sdk_version)
+				linkType := javaSdk
+				if strings.HasPrefix(sdkVersion, "system_") || strings.HasPrefix(sdkVersion, "test_") {
+					linkType = javaSystem
+				} else if sdkVersion == "" {
+					linkType = javaPlatform
+				}
+				deps.classpath = append(deps.classpath, dep.HeaderJars(linkType)...)
+			default:
+				ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
+			}
 		case android.SourceFileProducer:
 			switch tag {
 			case libTag:
diff --git a/java/java.go b/java/java.go
index bc58df3..8c23124 100644
--- a/java/java.go
+++ b/java/java.go
@@ -292,6 +292,10 @@
 	AidlIncludeDirs() android.Paths
 }
 
+type SdkLibraryDependency interface {
+	HeaderJars(linkType linkType) android.Paths
+}
+
 type SrcDependency interface {
 	CompiledSrcs() android.Paths
 	CompiledSrcJars() android.Paths
@@ -387,24 +391,29 @@
 		}
 	}
 
-	toFile := func(v string) sdkDep {
-		isCore := strings.HasPrefix(v, "core_")
-		if isCore {
-			v = strings.TrimPrefix(v, "core_")
+	toPrebuilt := func(sdk string) sdkDep {
+		var api, v string
+		if strings.Contains(sdk, "_") {
+			t := strings.Split(sdk, "_")
+			api = t[0]
+			v = t[1]
+		} else {
+			api = "public"
+			v = sdk
 		}
-		dir := filepath.Join("prebuilts/sdk", v)
+		dir := filepath.Join("prebuilts", "sdk", v, api)
 		jar := filepath.Join(dir, "android.jar")
-		if isCore {
-			jar = filepath.Join(dir, "core.jar")
-		}
-		aidl := filepath.Join(dir, "framework.aidl")
+		// There's no aidl for other SDKs yet.
+		// TODO(77525052): Add aidl files for other SDKs too.
+		public_dir := filepath.Join("prebuilts", "sdk", v, "public")
+		aidl := filepath.Join(public_dir, "framework.aidl")
 		jarPath := android.ExistentPathForSource(ctx, jar)
 		aidlPath := android.ExistentPathForSource(ctx, aidl)
 
 		if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
 			return sdkDep{
 				invalidVersion: true,
-				module:         "sdk_v" + v,
+				module:         fmt.Sprintf("sdk_%s_%s_android", api, v),
 			}
 		}
 
@@ -439,7 +448,7 @@
 	}
 
 	if ctx.Config().UnbundledBuild() && v != "" {
-		return toFile(v)
+		return toPrebuilt(v)
 	}
 
 	switch v {
@@ -457,7 +466,7 @@
 	case "core_current":
 		return toModule("core.current.stubs", "")
 	default:
-		return toFile(v)
+		return toPrebuilt(v)
 	}
 }
 
@@ -724,6 +733,13 @@
 			}
 
 			deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
+		case SdkLibraryDependency:
+			switch tag {
+			case libTag:
+				deps.classpath = append(deps.classpath, dep.HeaderJars(getLinkType(j, ctx.ModuleName()))...)
+			default:
+				ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
+			}
 		case android.SourceFileProducer:
 			switch tag {
 			case libTag:
diff --git a/java/java_test.go b/java/java_test.go
index 0e7bb18..de514e0 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -78,14 +78,18 @@
 	ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
 	ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory))
 	ctx.RegisterModuleType("java_genrule", android.ModuleFactoryAdaptor(genRuleFactory))
-	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
+	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
 	ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory))
 	ctx.RegisterModuleType("droiddoc", android.ModuleFactoryAdaptor(DroiddocFactory))
 	ctx.RegisterModuleType("droiddoc_host", android.ModuleFactoryAdaptor(DroiddocHostFactory))
 	ctx.RegisterModuleType("droiddoc_template", android.ModuleFactoryAdaptor(DroiddocTemplateFactory))
+	ctx.RegisterModuleType("java_sdk_library", android.ModuleFactoryAdaptor(sdkLibraryFactory))
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
+	})
 	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
 	ctx.Register()
 
@@ -151,17 +155,14 @@
 		"java-fg/b.java": nil,
 		"java-fg/c.java": nil,
 
-		"prebuilts/sdk/14/android.jar":                nil,
-		"prebuilts/sdk/14/framework.aidl":             nil,
-		"prebuilts/sdk/current/android.jar":           nil,
-		"prebuilts/sdk/current/framework.aidl":        nil,
-		"prebuilts/sdk/current/core.jar":              nil,
-		"prebuilts/sdk/system_current/android.jar":    nil,
-		"prebuilts/sdk/system_current/framework.aidl": nil,
-		"prebuilts/sdk/system_14/android.jar":         nil,
-		"prebuilts/sdk/system_14/framework.aidl":      nil,
-		"prebuilts/sdk/test_current/android.jar":      nil,
-		"prebuilts/sdk/test_current/framework.aidl":   nil,
+		"prebuilts/sdk/14/public/android.jar":         nil,
+		"prebuilts/sdk/14/public/framework.aidl":      nil,
+		"prebuilts/sdk/14/system/android.jar":         nil,
+		"prebuilts/sdk/current/public/android.jar":    nil,
+		"prebuilts/sdk/current/public/framework.aidl": nil,
+		"prebuilts/sdk/current/public/core.jar":       nil,
+		"prebuilts/sdk/current/system/android.jar":    nil,
+		"prebuilts/sdk/current/test/android.jar":      nil,
 
 		// For framework-res, which is an implicit dependency for framework
 		"AndroidManifest.xml":                   nil,
@@ -340,7 +341,7 @@
 		properties:    `sdk_version: "14",`,
 		bootclasspath: []string{`""`},
 		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/14/android.jar"},
+		classpath:     []string{"prebuilts/sdk/14/public/android.jar"},
 	},
 	{
 
@@ -362,7 +363,7 @@
 		properties:    `sdk_version: "system_14",`,
 		bootclasspath: []string{`""`},
 		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/system_14/android.jar"},
+		classpath:     []string{"prebuilts/sdk/14/system/android.jar"},
 	},
 	{
 
@@ -864,9 +865,9 @@
 	if len(barTurbineCombined.Inputs) != 2 || barTurbineCombined.Inputs[1].String() != fooHeaderJar {
 		t.Errorf("bar turbine combineJar inputs %v does not contain %q", barTurbineCombined.Inputs, fooHeaderJar)
 	}
-	if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/android.jar") {
+	if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") {
 		t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"],
-			"prebuilts/sdk/14/android.jar")
+			"prebuilts/sdk/14/public/android.jar")
 	}
 }
 
@@ -1001,3 +1002,60 @@
 		t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs)
 	}
 }
+
+func TestJavaSdkLibrary(t *testing.T) {
+	ctx := testJava(t, `
+		droiddoc_template {
+			name: "droiddoc-templates-sdk",
+			path: ".",
+		}
+		java_library {
+			name: "conscrypt",
+		}
+		java_library {
+			name: "bouncycastle",
+		}
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java", "b.java"],
+			api_packages: ["foo"],
+		}
+		java_sdk_library {
+			name: "bar",
+			srcs: ["a.java", "b.java"],
+			api_packages: ["bar"],
+		}
+		java_library {
+			name: "baz",
+			srcs: ["c.java"],
+			libs: ["foo", "bar"],
+			sdk_version: "system_current",
+		}
+		`)
+
+	// check the existence of the internal modules
+	ctx.ModuleForTests("foo", "android_common")
+	ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix, "android_common")
+	ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkSystemApiSuffix, "android_common")
+	ctx.ModuleForTests("foo"+sdkDocsSuffix, "android_common")
+	ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkSystemApiSuffix, "android_common")
+	ctx.ModuleForTests("foo"+sdkImplLibrarySuffix, "android_common")
+	ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "")
+
+	bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
+	// tests if baz is actually linked to the stubs lib
+	if !strings.Contains(bazJavac.Args["classpath"], "foo.stubs.system.jar") {
+		t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"],
+			"foo.stubs.system.jar")
+	}
+	// ... and not to the impl lib
+	if strings.Contains(bazJavac.Args["classpath"], "foo.impl.jar") {
+		t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"],
+			"foo.impl.jar")
+	}
+	// test if baz is not linked to the system variant of foo
+	if strings.Contains(bazJavac.Args["classpath"], "foo.stubs.jar") {
+		t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"],
+			"foo.stubs.jar")
+	}
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
new file mode 100644
index 0000000..301ec61
--- /dev/null
+++ b/java/sdk_library.go
@@ -0,0 +1,425 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// 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 (
+	"android/soong/android"
+	"android/soong/genrule"
+	"fmt"
+	"path"
+	"strings"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+)
+
+var (
+	sdkStubsLibrarySuffix = ".stubs"
+	sdkSystemApiSuffix    = ".system"
+	sdkDocsSuffix         = ".docs"
+	sdkImplLibrarySuffix  = ".impl"
+	sdkXmlFileSuffix      = ".xml"
+)
+
+type stubsLibraryDependencyTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+var (
+	publicApiStubsTag = dependencyTag{name: "public"}
+	systemApiStubsTag = dependencyTag{name: "system"}
+)
+
+// java_sdk_library is to make a Java library that implements optional platform APIs to apps.
+// It is actually a wrapper of several modules: 1) stubs library that clients are linked against
+// to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime
+// shared library that implements the APIs, and 4) XML file for adding the runtime lib to the
+// classpath at runtime if requested via <uses-library>.
+//
+// TODO: these are big features that are currently missing
+// 1) check for API consistency
+// 2) install stubs libs as the dist artifacts
+// 3) ensuring that apps have appropriate <uses-library> tag
+// 4) disallowing linking to the runtime shared lib
+// 5) HTML generation
+
+func init() {
+	android.RegisterModuleType("java_sdk_library", sdkLibraryFactory)
+
+	android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
+	})
+}
+
+type sdkLibraryProperties struct {
+	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
+	// or .aidl files.
+	Srcs []string `android:"arch_variant"`
+
+	// list of of java libraries that will be in the classpath
+	Libs []string `android:"arch_variant"`
+
+	// list of java libraries that will be compiled into the resulting runtime jar.
+	// These libraries are not compiled into the stubs jar.
+	Static_libs []string `android:"arch_variant"`
+
+	// list of package names that will be documented and publicized as API
+	Api_packages []string
+
+	// TODO: determines whether to create HTML doc or not
+	//Html_doc *bool
+}
+
+type sdkLibrary struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties sdkLibraryProperties
+
+	publicApiStubsPath android.Paths
+	systemApiStubsPath android.Paths
+}
+
+func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// Add dependencies to the stubs library
+	ctx.AddDependency(ctx.Module(), publicApiStubsTag, module.stubsName(false))
+	ctx.AddDependency(ctx.Module(), systemApiStubsTag, module.stubsName(true))
+}
+
+func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Record the paths to the header jars of the stubs library.
+	// When this java_sdk_library is dependened from others via "libs" property,
+	// the recorded paths will be returned depending on the link type of the caller.
+	ctx.VisitDirectDeps(func(to android.Module) {
+		otherName := ctx.OtherModuleName(to)
+		tag := ctx.OtherModuleDependencyTag(to)
+
+		if stubs, ok := to.(Dependency); ok {
+			switch tag {
+			case publicApiStubsTag:
+				module.publicApiStubsPath = stubs.HeaderJars()
+			case systemApiStubsTag:
+				module.systemApiStubsPath = stubs.HeaderJars()
+			default:
+				ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
+			}
+		}
+	})
+}
+
+// Module name of the stubs library
+func (module *sdkLibrary) stubsName(forSystemApi bool) string {
+	stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix
+	if forSystemApi {
+		stubsName = stubsName + sdkSystemApiSuffix
+	}
+	return stubsName
+}
+
+// Module name of the docs
+func (module *sdkLibrary) docsName(forSystemApi bool) string {
+	docsName := module.BaseModuleName() + sdkDocsSuffix
+	if forSystemApi {
+		docsName = docsName + sdkSystemApiSuffix
+	}
+	return docsName
+}
+
+// Module name of the runtime implementation library
+func (module *sdkLibrary) implName() string {
+	return module.BaseModuleName() + sdkImplLibrarySuffix
+}
+
+// File path to the runtime implementation library
+func (module *sdkLibrary) implPath() string {
+	partition := "system"
+	if module.SocSpecific() {
+		partition = "vendor"
+	} else if module.DeviceSpecific() {
+		partition = "odm"
+	} else if module.ProductSpecific() {
+		partition = "product"
+	}
+	return "/" + partition + "/framework/" + module.implName() + ".jar"
+}
+
+// Module name of the XML file for the lib
+func (module *sdkLibrary) xmlFileName() string {
+	return module.BaseModuleName() + sdkXmlFileSuffix
+}
+
+// SDK version that the stubs library is built against. Note that this is always
+// *current. Older stubs library built with a numberd SDK version is created from
+// the prebuilt jar.
+func (module *sdkLibrary) sdkVersion(forSystemApi bool) string {
+	if forSystemApi {
+		return "system_current"
+	} else {
+		return "current"
+	}
+}
+
+// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
+// api file for the current source
+// TODO: remove this when apicheck is done in soong
+func (module *sdkLibrary) apiTagName(forSystemApi bool) string {
+	apiTagName := strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1)
+	if forSystemApi {
+		apiTagName = apiTagName + "_SYSTEM"
+	}
+	return apiTagName
+}
+
+// returns the path (relative to this module) to the API txt file. Files are located
+// ./<api_dir>/<api_level>.txt where <api_level> is either current, system-current, removed,
+// or system-removed.
+func (module *sdkLibrary) apiFilePath(apiLevel string, forSystemApi bool) string {
+	apiDir := "api"
+	apiFile := apiLevel
+	if forSystemApi {
+		apiFile = "system-" + apiFile
+	}
+	apiFile = apiFile + ".txt"
+
+	return path.Join(apiDir, apiFile)
+}
+
+// Creates a static java library that has API stubs
+func (module *sdkLibrary) createStubsLibrary(mctx android.TopDownMutatorContext, forSystemApi bool) {
+	props := struct {
+		Name              *string
+		Srcs              []string
+		Sdk_version       *string
+		Soc_specific      *bool
+		Device_specific   *bool
+		Product_specific  *bool
+		Product_variables struct {
+			Unbundled_build struct {
+				Enabled *bool
+			}
+		}
+	}{}
+
+	props.Name = proptools.StringPtr(module.stubsName(forSystemApi))
+	// sources are generated from the droiddoc
+	props.Srcs = []string{":" + module.docsName(forSystemApi)}
+	props.Sdk_version = proptools.StringPtr(module.sdkVersion(forSystemApi))
+	// Unbundled apps will use the prebult one from /prebuilts/sdk
+	props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
+
+	if module.SocSpecific() {
+		props.Soc_specific = proptools.BoolPtr(true)
+	} else if module.DeviceSpecific() {
+		props.Device_specific = proptools.BoolPtr(true)
+	} else if module.ProductSpecific() {
+		props.Product_specific = proptools.BoolPtr(true)
+	}
+
+	mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(false)), &props)
+}
+
+// Creates a droiddoc module that creates stubs source files from the given full source
+// files
+func (module *sdkLibrary) createDocs(mctx android.TopDownMutatorContext, forSystemApi bool) {
+	props := struct {
+		Name                    *string
+		Srcs                    []string
+		Custom_template         *string
+		Installable             *bool
+		Srcs_lib                *string
+		Srcs_lib_whitelist_dirs []string
+		Srcs_lib_whitelist_pkgs []string
+		Libs                    []string
+		Args                    *string
+		Api_tag_name            *string
+		Api_filename            *string
+		Removed_api_filename    *string
+	}{}
+
+	props.Name = proptools.StringPtr(module.docsName(forSystemApi))
+	props.Srcs = module.properties.Srcs
+	props.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
+	props.Installable = proptools.BoolPtr(false)
+	props.Libs = module.properties.Libs
+
+	droiddocArgs := " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128" +
+		" -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
+		" -nodocs"
+	if forSystemApi {
+		droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
+	}
+	props.Args = proptools.StringPtr(droiddocArgs)
+
+	// List of APIs identified from the provided source files are created. They are later
+	// compared against to the not-yet-released (a.k.a current) list of APIs and to the
+	// last-released (a.k.a numbered) list of API.
+	// TODO: If any incompatible change is detected, break the build
+	currentApiFileName := "current.txt"
+	removedApiFileName := "removed.txt"
+	if forSystemApi {
+		currentApiFileName = "system-" + currentApiFileName
+		removedApiFileName = "system-" + removedApiFileName
+	}
+	currentApiFileName = path.Join("api", currentApiFileName)
+	removedApiFileName = path.Join("api", removedApiFileName)
+	props.Api_tag_name = proptools.StringPtr(module.apiTagName(forSystemApi))
+	// Note: the exact names of these two are not important because they are always
+	// referenced by the make variable $(INTERNAL_PLATFORM_<TAG_NAME>_API_FILE)
+	props.Api_filename = proptools.StringPtr(currentApiFileName)
+	props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
+
+	// Includes the main framework source to ensure that doclava has access to the
+	// visibility information for the base classes of the mock classes. Without it
+	// otherwise hidden methods could be visible.
+	// TODO: remove the need for this
+	props.Srcs_lib = proptools.StringPtr("framework")
+	props.Srcs_lib_whitelist_dirs = []string{"core/java"}
+	props.Srcs_lib_whitelist_pkgs = []string{"android"}
+	// These libs are required by doclava to parse the sources from framework.
+	// If we don't add them to the classpath, errors messages are generated by doclava,
+	// though they don't break the build.
+	props.Libs = append(props.Libs, "conscrypt", "bouncycastle", "okhttp")
+
+	mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props)
+}
+
+// Creates the runtime library. This is not directly linkable from other modules.
+func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) {
+	props := struct {
+		Name             *string
+		Srcs             []string
+		Libs             []string
+		Static_libs      []string
+		Soc_specific     *bool
+		Device_specific  *bool
+		Product_specific *bool
+		Required         []string
+	}{}
+
+	props.Name = proptools.StringPtr(module.implName())
+	props.Srcs = module.properties.Srcs
+	props.Libs = module.properties.Libs
+	props.Static_libs = module.properties.Static_libs
+	// XML file is installed along with the impl lib
+	props.Required = []string{module.xmlFileName()}
+
+	if module.SocSpecific() {
+		props.Soc_specific = proptools.BoolPtr(true)
+	} else if module.DeviceSpecific() {
+		props.Device_specific = proptools.BoolPtr(true)
+	} else if module.ProductSpecific() {
+		props.Product_specific = proptools.BoolPtr(true)
+	}
+
+	mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(true)), &props)
+}
+
+// Creates the xml file that publicizes the runtime library
+func (module *sdkLibrary) createXmlFile(mctx android.TopDownMutatorContext) {
+	template := `
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<permissions>
+    <library name="%s" file="%s"/>
+</permissions>
+`
+	// genrule to generate the xml file content from the template above
+	// TODO: preserve newlines in the generate xml file. Newlines are being squashed
+	// in the ninja file. Do we need to have an external tool for this?
+	xmlContent := fmt.Sprintf(template, module.BaseModuleName(), module.implPath())
+	genruleProps := struct {
+		Name *string
+		Cmd  *string
+		Out  []string
+	}{}
+	genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
+	genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
+	genruleProps.Out = []string{module.xmlFileName()}
+	mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps)
+
+	// creates a prebuilt_etc module to actually place the xml file under
+	// <partition>/etc/permissions
+	etcProps := struct {
+		Name             *string
+		Srcs             []string
+		Sub_dir          *string
+		Soc_specific     *bool
+		Device_specific  *bool
+		Product_specific *bool
+	}{}
+	etcProps.Name = proptools.StringPtr(module.xmlFileName())
+	etcProps.Srcs = []string{":" + module.xmlFileName() + "-gen"}
+	etcProps.Sub_dir = proptools.StringPtr("permissions")
+	if module.SocSpecific() {
+		etcProps.Soc_specific = proptools.BoolPtr(true)
+	} else if module.DeviceSpecific() {
+		etcProps.Device_specific = proptools.BoolPtr(true)
+	} else if module.ProductSpecific() {
+		etcProps.Product_specific = proptools.BoolPtr(true)
+	}
+	mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
+}
+
+// to satisfy SdkLibraryDependency interface
+func (module *sdkLibrary) HeaderJars(linkType linkType) android.Paths {
+	// This module is just a wrapper for the stubs.
+	if linkType == javaSystem || linkType == javaPlatform {
+		return module.systemApiStubsPath
+	} else {
+		return module.publicApiStubsPath
+	}
+}
+
+// For a java_sdk_library module, create internal modules for stubs, docs,
+// runtime libs and xml file. If requested, the stubs and docs are created twice
+// once for public API level and once for system API level
+func sdkLibraryMutator(mctx android.TopDownMutatorContext) {
+	if module, ok := mctx.Module().(*sdkLibrary); ok {
+		// for public API stubs
+		module.createStubsLibrary(mctx, false)
+		module.createDocs(mctx, false)
+
+		// for system API stubs
+		module.createStubsLibrary(mctx, true)
+		module.createDocs(mctx, true)
+
+		// for runtime
+		module.createXmlFile(mctx)
+		module.createImplLibrary(mctx)
+	}
+}
+
+func sdkLibraryFactory() android.Module {
+	module := &sdkLibrary{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
+	return module
+}