Merge "Support prebuilt shared libs end with versions"
diff --git a/android/module.go b/android/module.go
index b58dd4b..ac7e606 100644
--- a/android/module.go
+++ b/android/module.go
@@ -294,11 +294,25 @@
 
 const (
 	_ HostOrDeviceSupported = iota
+
+	// Host and HostCross are built by default. Device is not supported.
 	HostSupported
+
+	// Host is built by default. HostCross and Device are not supported.
 	HostSupportedNoCross
+
+	// Device is built by default. Host and HostCross are not supported.
 	DeviceSupported
+
+	// Device is built by default. Host and HostCross are supported.
 	HostAndDeviceSupported
+
+	// Host, HostCross, and Device are built by default.
 	HostAndDeviceDefault
+
+	// Nothing is supported. This is not exposed to the user, but used to mark a
+	// host only module as unsupported when the module type is not supported on
+	// the host OS. E.g. benchmarks are supported on Linux but not Darwin.
 	NeitherHostNorDeviceSupported
 )
 
@@ -493,9 +507,11 @@
 		return []OsClass{Host}
 	case DeviceSupported:
 		return []OsClass{Device}
-	case HostAndDeviceSupported:
+	case HostAndDeviceSupported, HostAndDeviceDefault:
 		var supported []OsClass
-		if Bool(a.hostAndDeviceProperties.Host_supported) {
+		if Bool(a.hostAndDeviceProperties.Host_supported) ||
+			(a.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
+				a.hostAndDeviceProperties.Host_supported == nil) {
 			supported = append(supported, Host, HostCross)
 		}
 		if a.hostAndDeviceProperties.Device_supported == nil ||
diff --git a/cc/binary.go b/cc/binary.go
index 82e1941..be79032 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -31,9 +31,6 @@
 	// if set, add an extra objcopy --prefix-symbols= step
 	Prefix_symbols *string
 
-	// local file name to pass to the linker as --version_script
-	Version_script *string `android:"arch_variant"`
-
 	// if set, install a symlink to the preferred architecture
 	Symlink_preferred_arch *bool
 
@@ -163,8 +160,6 @@
 			"from static libs or set static_executable: true")
 	}
 
-	android.ExtractSourceDeps(ctx, binary.Properties.Version_script)
-
 	return deps
 }
 
@@ -175,7 +170,7 @@
 func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
 	module := newModule(hod, android.MultilibFirst)
 	binary := &binaryDecorator{
-		baseLinker:    NewBaseLinker(),
+		baseLinker:    NewBaseLinker(module.sanitize),
 		baseInstaller: NewBaseInstaller("bin", "", InstallInSystem),
 	}
 	module.compiler = NewBaseCompiler()
@@ -281,7 +276,6 @@
 func (binary *binaryDecorator) link(ctx ModuleContext,
 	flags Flags, deps PathDeps, objs Objects) android.Path {
 
-	versionScript := ctx.ExpandOptionalSource(binary.Properties.Version_script, "version_script")
 	fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
 	outputFile := android.PathForModuleOut(ctx, fileName)
 	ret := outputFile
@@ -291,15 +285,6 @@
 	sharedLibs := deps.SharedLibs
 	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
 
-	if versionScript.Valid() {
-		if ctx.Darwin() {
-			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
-		} else {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
-			linkerDeps = append(linkerDeps, versionScript.Path())
-		}
-	}
-
 	if deps.LinkerScript.Valid() {
 		flags.LdFlags = append(flags.LdFlags, "-Wl,-T,"+deps.LinkerScript.String())
 		linkerDeps = append(linkerDeps, deps.LinkerScript.Path())
diff --git a/cc/library.go b/cc/library.go
index 5da36dc..147dd8e 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -44,8 +44,6 @@
 		Shared_libs       []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 
-	// local file name to pass to the linker as --version_script
-	Version_script *string `android:"arch_variant"`
 	// local file name to pass to the linker as -unexported_symbols_list
 	Unexported_symbols_list *string `android:"arch_variant"`
 	// local file name to pass to the linker as -force_symbols_not_weak_list
@@ -65,12 +63,6 @@
 		// export headers generated from .proto sources
 		Export_proto_headers *bool
 	}
-	Target struct {
-		Vendor struct {
-			// version script for this vendor variant
-			Version_script *string `android:"arch_variant"`
-		}
-	}
 
 	Static_ndk_lib *bool
 }
@@ -231,8 +223,6 @@
 	// shlib suffix.
 	libName string
 
-	sanitize *sanitize
-
 	sabi *sabi
 
 	// Output archive of gcno coverage information files
@@ -432,7 +422,7 @@
 
 func (library *libraryDecorator) linkerInit(ctx BaseModuleContext) {
 	location := InstallInSystem
-	if library.sanitize.inSanitizerDir() {
+	if library.baseLinker.sanitize.inSanitizerDir() {
 		location = InstallInSanitizerDir
 	}
 	library.baseInstaller.location = location
@@ -483,11 +473,9 @@
 		deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
 	}
 
-	android.ExtractSourceDeps(ctx, library.Properties.Version_script)
 	android.ExtractSourceDeps(ctx, library.Properties.Unexported_symbols_list)
 	android.ExtractSourceDeps(ctx, library.Properties.Force_symbols_not_weak_list)
 	android.ExtractSourceDeps(ctx, library.Properties.Force_symbols_weak_list)
-	android.ExtractSourceDeps(ctx, library.Properties.Target.Vendor.Version_script)
 
 	return deps
 }
@@ -526,23 +514,10 @@
 	var linkerDeps android.Paths
 	linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
 
-	versionScript := ctx.ExpandOptionalSource(library.Properties.Version_script, "version_script")
 	unexportedSymbols := ctx.ExpandOptionalSource(library.Properties.Unexported_symbols_list, "unexported_symbols_list")
 	forceNotWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_not_weak_list, "force_symbols_not_weak_list")
 	forceWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_weak_list, "force_symbols_weak_list")
-	if ctx.useVndk() && library.Properties.Target.Vendor.Version_script != nil {
-		versionScript = ctx.ExpandOptionalSource(library.Properties.Target.Vendor.Version_script, "target.vendor.version_script")
-	}
 	if !ctx.Darwin() {
-		if versionScript.Valid() {
-			flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
-			linkerDeps = append(linkerDeps, versionScript.Path())
-			if library.sanitize.isSanitizerEnabled(cfi) {
-				cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
-				flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+cfiExportsMap.String())
-				linkerDeps = append(linkerDeps, cfiExportsMap)
-			}
-		}
 		if unexportedSymbols.Valid() {
 			ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
 		}
@@ -553,9 +528,6 @@
 			ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
 		}
 	} else {
-		if versionScript.Valid() {
-			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
-		}
 		if unexportedSymbols.Valid() {
 			flags.LdFlags = append(flags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
 			linkerDeps = append(linkerDeps, unexportedSymbols.Path())
@@ -768,7 +740,7 @@
 
 	if Bool(library.Properties.Static_ndk_lib) && library.static() &&
 		!ctx.useVndk() && !ctx.inRecovery() && ctx.Device() &&
-		library.sanitize.isUnsanitizedVariant() {
+		library.baseLinker.sanitize.isUnsanitizedVariant() {
 		installPath := getNdkSysrootBase(ctx).Join(
 			ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base())
 
@@ -827,9 +799,8 @@
 			BuildStatic: true,
 		},
 		baseCompiler:  NewBaseCompiler(),
-		baseLinker:    NewBaseLinker(),
+		baseLinker:    NewBaseLinker(module.sanitize),
 		baseInstaller: NewBaseInstaller("lib", "lib64", InstallInSystem),
-		sanitize:      module.sanitize,
 		sabi:          module.sabi,
 	}
 
diff --git a/cc/linker.go b/cc/linker.go
index 6bbf015..9911b16 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -103,6 +103,10 @@
 			// of the C/C++ module.
 			Exclude_static_libs []string
 
+			// list of header libs that should not be used to build the vendor variant
+			// of the C/C++ module.
+			Exclude_header_libs []string
+
 			// list of runtime libs that should not be installed along with the vendor
 			// variant of the C/C++ module.
 			Exclude_runtime_libs []string
@@ -115,6 +119,10 @@
 			// list of static libs that should not be used to build
 			// the recovery variant of the C/C++ module.
 			Exclude_static_libs []string
+
+			// list of header libs that should not be used to build the recovery variant
+			// of the C/C++ module.
+			Exclude_header_libs []string
 		}
 	}
 
@@ -127,10 +135,20 @@
 type MoreBaseLinkerProperties struct {
 	// Generate compact dynamic relocation table, default true.
 	Pack_relocations *bool `android:"arch_variant"`
+
+	// local file name to pass to the linker as --version_script
+	Version_script *string `android:"arch_variant"`
+
+	Target struct {
+		Vendor struct {
+			// version script for this vendor variant
+			Version_script *string `android:"arch_variant"`
+		}
+	}
 }
 
-func NewBaseLinker() *baseLinker {
-	return &baseLinker{}
+func NewBaseLinker(sanitize *sanitize) *baseLinker {
+	return &baseLinker{sanitize: sanitize}
 }
 
 // baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
@@ -140,6 +158,8 @@
 	dynamicProperties struct {
 		RunPaths []string `blueprint:"mutated"`
 	}
+
+	sanitize *sanitize
 }
 
 func (linker *baseLinker) appendLdflags(flags []string) {
@@ -158,7 +178,7 @@
 	return []interface{}{&linker.Properties, &linker.MoreProperties, &linker.dynamicProperties}
 }
 
-func (linker *baseLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
+func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
 	deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
 	deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
 	deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
@@ -178,6 +198,7 @@
 		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
 		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs)
 		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
+		deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Vendor.Exclude_header_libs)
 		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs)
 		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
 		deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs)
@@ -187,6 +208,8 @@
 		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
 		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs)
 		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
+		deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Recovery.Exclude_header_libs)
+		deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Recovery.Exclude_header_libs)
 		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
 		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
 	}
@@ -237,6 +260,10 @@
 		deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread")
 	}
 
+	android.ExtractSourceDeps(ctx, linker.MoreProperties.Version_script)
+	android.ExtractSourceDeps(ctx,
+		linker.MoreProperties.Target.Vendor.Version_script)
+
 	return deps
 }
 
@@ -345,6 +372,32 @@
 		flags.GroupStaticLibs = true
 	}
 
+	versionScript := ctx.ExpandOptionalSource(
+		linker.MoreProperties.Version_script, "version_script")
+
+	if ctx.useVndk() && linker.MoreProperties.Target.Vendor.Version_script != nil {
+		versionScript = ctx.ExpandOptionalSource(
+			linker.MoreProperties.Target.Vendor.Version_script,
+			"target.vendor.version_script")
+	}
+
+	if versionScript.Valid() {
+		if ctx.Darwin() {
+			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
+		} else {
+			flags.LdFlags = append(flags.LdFlags,
+				"-Wl,--version-script,"+versionScript.String())
+			flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
+
+			if linker.sanitize.isSanitizerEnabled(cfi) {
+				cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+				flags.LdFlags = append(flags.LdFlags,
+					"-Wl,--version-script,"+cfiExportsMap.String())
+				flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
+			}
+		}
+	}
+
 	return flags
 }
 
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index 4c633c2..258d6bd 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -68,7 +68,7 @@
 	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
 	module.linker = &ndkPrebuiltObjectLinker{
 		objectLinker: objectLinker{
-			baseLinker: NewBaseLinker(),
+			baseLinker: NewBaseLinker(nil),
 		},
 	}
 	module.Properties.HideFromMake = true
diff --git a/cc/object.go b/cc/object.go
index d0f4f20..b5fd835 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -36,7 +36,7 @@
 func objectFactory() android.Module {
 	module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth)
 	module.linker = &objectLinker{
-		baseLinker: NewBaseLinker(),
+		baseLinker: NewBaseLinker(nil),
 	}
 	module.compiler = NewBaseCompiler()
 	return module.Init()
diff --git a/java/androidmk.go b/java/androidmk.go
index 14e9fec..544322e 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -232,6 +232,9 @@
 				}
 
 				fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.pem.String())
+				if len(app.appProperties.Overrides) > 0 {
+					fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES := "+strings.Join(app.appProperties.Overrides, " "))
+				}
 			},
 		},
 	}
@@ -285,7 +288,7 @@
 	return android.AndroidMkData{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(jd.stubsSrcJar),
-		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
 		Extra: []android.AndroidMkExtraFunc{
 			func(w io.Writer, outputFile android.Path) {
 				if BoolDefault(jd.properties.Installable, true) {
@@ -303,7 +306,7 @@
 	return android.AndroidMkData{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(ddoc.stubsSrcJar),
-		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
 		Extra: []android.AndroidMkExtraFunc{
 			func(w io.Writer, outputFile android.Path) {
 				if BoolDefault(ddoc.Javadoc.properties.Installable, true) {
diff --git a/java/app.go b/java/app.go
index 9e7530e..ef591b7 100644
--- a/java/app.go
+++ b/java/app.go
@@ -51,6 +51,13 @@
 
 	// list of resource labels to generate individual resource packages
 	Package_splits []string
+
+	// Names of modules to be overridden. Listed modules can only be other binaries
+	// (in Make or Soong).
+	// This does not completely prevent installation of the overridden binaries, but if both
+	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
+	// from PRODUCT_PACKAGES.
+	Overrides []string
 }
 
 type AndroidApp struct {
diff --git a/java/config/config.go b/java/config/config.go
index 4863fec..fa8cb0f 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -121,6 +121,7 @@
 	pctx.HostJavaToolVariable("JsilverJar", "jsilver.jar")
 	pctx.HostJavaToolVariable("DoclavaJar", "doclava.jar")
 	pctx.HostJavaToolVariable("MetalavaJar", "metalava.jar")
+	pctx.HostJavaToolVariable("DokkaJar", "dokka.jar")
 
 	pctx.HostBinToolVariable("SoongJavacWrapper", "soong_javac_wrapper")
 
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 137eaaf..1945929 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -67,7 +67,8 @@
 
 	metalava = pctx.AndroidStaticRule("metalava",
 		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
+			Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" "$docStubsDir" && ` +
+				`mkdir -p "$outDir" "$srcJarDir" "$stubsDir" "$docStubsDir" && ` +
 				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 				`${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
 				`$bootclasspathArgs $classpathArgs -sourcepath $sourcepath --no-banner --color --quiet ` +
@@ -85,7 +86,7 @@
 			RspfileContent: "$in",
 			Restat:         true,
 		},
-		"outDir", "srcJarDir", "stubsDir", "srcJars", "javaVersion", "bootclasspathArgs",
+		"outDir", "srcJarDir", "stubsDir", "docStubsDir", "srcJars", "javaVersion", "bootclasspathArgs",
 		"classpathArgs", "sourcepath", "opts", "docZip")
 )
 
@@ -264,26 +265,31 @@
 
 	// a list of top-level directories containing files to merge annotations from.
 	Metalava_merge_annotations_dirs []string
+
+	// if set to true, generate docs through Dokka instead of Doclava. Valid only when
+	// metalava_enabled is set to true.
+	Dokka_enabled *bool
 }
 
 //
 // Common flags passed down to build rule
 //
 type droiddocBuilderFlags struct {
-	args              string
-	bootClasspathArgs string
-	classpathArgs     string
-	aidlFlags         string
+	args               string
+	bootClasspathArgs  string
+	classpathArgs      string
+	dokkaClasspathArgs string
+	aidlFlags          string
 
-	doclavaDocsFlags  string
 	doclavaStubsFlags string
+	doclavaDocsFlags  string
 	postDoclavaCmds   string
 
-	metalavaAnnotationsFlags string
-	metalavaDocsFlags        string
 	metalavaStubsFlags       string
+	metalavaAnnotationsFlags string
+	metalavaJavadocFlags     string
 
-	dokkaFlags string
+	metalavaDokkaFlags string
 }
 
 func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
@@ -572,9 +578,9 @@
 		Inputs:         j.srcFiles,
 		Implicits:      implicits,
 		Args: map[string]string{
-			"outDir":            android.PathForModuleOut(ctx, "docs", "out").String(),
-			"srcJarDir":         android.PathForModuleOut(ctx, "docs", "srcjars").String(),
-			"stubsDir":          android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
+			"outDir":            android.PathForModuleOut(ctx, "out").String(),
+			"srcJarDir":         android.PathForModuleOut(ctx, "srcjars").String(),
+			"stubsDir":          android.PathForModuleOut(ctx, "stubsDir").String(),
 			"srcJars":           strings.Join(j.srcJars.Strings(), " "),
 			"opts":              opts,
 			"bootclasspathArgs": bootClasspathArgs,
@@ -719,6 +725,11 @@
 		flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
 	}
 	flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath")
+	// Dokka doesn't support boocClasspath, so combine these two classpath vars for Dokka.
+	dokkaClasspath := classpath{}
+	dokkaClasspath = append(dokkaClasspath, deps.bootClasspath...)
+	dokkaClasspath = append(dokkaClasspath, deps.classpath...)
+	flags.dokkaClasspathArgs = dokkaClasspath.FormJavaClassPath("-classpath")
 
 	argFiles := ctx.ExpandSources(d.properties.Arg_files, nil)
 	argFilesMap := map[string]android.Path{}
@@ -899,11 +910,11 @@
 	}
 
 	if BoolDefault(d.properties.Create_stubs, true) {
-		doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "docs", "stubsDir").String()
+		doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "stubsDir").String()
 	}
 
 	if Bool(d.properties.Write_sdk_values) {
-		doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "docs", "out").String()
+		doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "out").String()
 	}
 	return doclavaFlags, MetalavaFlags
 }
@@ -915,7 +926,7 @@
 			"static_doc_index_redirect")
 		*implicits = append(*implicits, static_doc_index_redirect)
 		cmds = cmds + " && cp " + static_doc_index_redirect.String() + " " +
-			android.PathForModuleOut(ctx, "docs", "out", "index.html").String()
+			android.PathForModuleOut(ctx, "out", "index.html").String()
 	}
 
 	if String(d.properties.Static_doc_properties) != "" {
@@ -923,7 +934,7 @@
 			"static_doc_properties")
 		*implicits = append(*implicits, static_doc_properties)
 		cmds = cmds + " && cp " + static_doc_properties.String() + " " +
-			android.PathForModuleOut(ctx, "docs", "out", "source.properties").String()
+			android.PathForModuleOut(ctx, "out", "source.properties").String()
 	}
 	return cmds
 }
@@ -931,18 +942,16 @@
 func (d *Droiddoc) collectMetalavaAnnotationsFlags(
 	ctx android.ModuleContext, implicits *android.Paths, implicitOutputs *android.WritablePaths) string {
 	var flags string
-	if String(d.properties.Metalava_previous_api) != "" {
-		previousApi := ctx.ExpandSource(String(d.properties.Metalava_previous_api),
-			"metalava_previous_api")
-		flags += " --previous-api " + previousApi.String()
-		*implicits = append(*implicits, previousApi)
-	}
-
 	if Bool(d.properties.Metalava_annotations_enabled) {
 		if String(d.properties.Metalava_previous_api) == "" {
 			ctx.PropertyErrorf("metalava_previous_api",
 				"has to be non-empty if annotations was enabled!")
 		}
+		previousApi := ctx.ExpandSource(String(d.properties.Metalava_previous_api),
+			"metalava_previous_api")
+		*implicits = append(*implicits, previousApi)
+		flags += " --previous-api " + previousApi.String()
+
 		flags += " --include-annotations --migrate-nullness"
 
 		d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
@@ -970,13 +979,111 @@
 	return flags
 }
 
-func (d *Droiddoc) collectMetalavaDocsFlags(ctx android.ModuleContext,
-	bootClasspathArgs, classpathArgs string) string {
-	return " --doc-stubs " + android.PathForModuleOut(ctx, "docs", "docStubsDir").String() +
-		" --write-doc-stubs-source-list $outDir/doc_stubs_src_list " +
+func (d *Droiddoc) collectMetalavaJavadocFlags(ctx android.ModuleContext,
+	bootClasspathArgs, classpathArgs, outDir, docStubsDir string) string {
+	return " --doc-stubs " + docStubsDir +
+		" --write-doc-stubs-source-list " + android.PathForModuleOut(ctx, "doc_stubs.srclist").String() +
 		" --generate-documentation ${config.JavadocCmd} -encoding UTF-8 DOC_STUBS_SOURCE_LIST " +
 		bootClasspathArgs + " " + classpathArgs + " " + " -sourcepath " +
-		android.PathForModuleOut(ctx, "docs", "docStubsDir").String() + " -quiet -d $outDir "
+		docStubsDir + " -quiet -d " + outDir
+}
+
+func (d *Droiddoc) collectMetalavaDokkaFlags(ctx android.ModuleContext, implicits *android.Paths,
+	classpathArgs, outDir, docStubsDir string) string {
+	dokka := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "dokka.jar")
+	*implicits = append(*implicits, dokka)
+
+	return " --doc-stubs " + docStubsDir + " --write-doc-stubs-source-list " +
+		android.PathForModuleOut(ctx, "doc_stubs.srclist").String() +
+		" --generate-documentation ${config.JavaCmd} -jar " + dokka.String() + " " +
+		docStubsDir + " " + classpathArgs + " -format dac -dacRoot /reference/kotlin -output " + outDir
+}
+
+func (d *Droiddoc) transformMetalava(ctx android.ModuleContext, implicits android.Paths,
+	implicitOutputs android.WritablePaths, outDir, docStubsDir, javaVersion,
+	bootclasspathArgs, classpathArgs, opts string) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:            metalava,
+		Description:     "Metalava",
+		Output:          d.Javadoc.stubsSrcJar,
+		Inputs:          d.Javadoc.srcFiles,
+		Implicits:       implicits,
+		ImplicitOutputs: implicitOutputs,
+		Args: map[string]string{
+			"outDir":            outDir,
+			"srcJarDir":         android.PathForModuleOut(ctx, "srcjars").String(),
+			"stubsDir":          android.PathForModuleOut(ctx, "stubsDir").String(),
+			"docStubsDir":       docStubsDir,
+			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
+			"javaVersion":       javaVersion,
+			"bootclasspathArgs": bootclasspathArgs,
+			"classpathArgs":     classpathArgs,
+			"sourcepath":        strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
+			"docZip":            d.Javadoc.docZip.String(),
+			"opts":              opts,
+		},
+	})
+}
+
+func (d *Droiddoc) transformDoclava(ctx android.ModuleContext, implicits android.Paths,
+	implicitOutputs android.WritablePaths, bootclasspathArgs, classpathArgs, opts, postDoclavaCmds string) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:            javadoc,
+		Description:     "Doclava",
+		Output:          d.Javadoc.stubsSrcJar,
+		Inputs:          d.Javadoc.srcFiles,
+		Implicits:       implicits,
+		ImplicitOutputs: implicitOutputs,
+		Args: map[string]string{
+			"outDir":            android.PathForModuleOut(ctx, "out").String(),
+			"srcJarDir":         android.PathForModuleOut(ctx, "srcjars").String(),
+			"stubsDir":          android.PathForModuleOut(ctx, "stubsDir").String(),
+			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
+			"opts":              opts,
+			"bootclasspathArgs": bootclasspathArgs,
+			"classpathArgs":     classpathArgs,
+			"sourcepath":        strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
+			"docZip":            d.Javadoc.docZip.String(),
+			"postDoclavaCmds":   postDoclavaCmds,
+		},
+	})
+}
+
+func (d *Droiddoc) transformCheckApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
+	checkApiClasspath classpath, msg, opts string, output android.WritablePath) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        apiCheck,
+		Description: "Check API",
+		Output:      output,
+		Inputs:      nil,
+		Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
+			checkApiClasspath...),
+		Args: map[string]string{
+			"classpath":             checkApiClasspath.FormJavaClassPath(""),
+			"opts":                  opts,
+			"apiFile":               apiFile.String(),
+			"apiFileToCheck":        d.apiFile.String(),
+			"removedApiFile":        removedApiFile.String(),
+			"removedApiFileToCheck": d.removedApiFile.String(),
+			"msg": msg,
+		},
+	})
+}
+
+func (d *Droiddoc) transformUpdateApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
+	output android.WritablePath) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        updateApi,
+		Description: "Update API",
+		Output:      output,
+		Implicits:   append(android.Paths{}, apiFile, removedApiFile, d.apiFile, d.removedApiFile),
+		Args: map[string]string{
+			"apiFile":               apiFile.String(),
+			"apiFileToCheck":        d.apiFile.String(),
+			"removedApiFile":        removedApiFile.String(),
+			"removedApiFileToCheck": d.removedApiFile.String(),
+		},
+	})
 }
 
 func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1011,62 +1118,39 @@
 
 	flags.doclavaStubsFlags, flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs)
 	if Bool(d.properties.Metalava_enabled) {
-		opts := flags.metalavaStubsFlags
 		flags.metalavaAnnotationsFlags = d.collectMetalavaAnnotationsFlags(ctx, &implicits, &implicitOutputs)
-		opts += flags.metalavaAnnotationsFlags
-		if strings.Contains(flags.args, "--generate-documentation") {
-			// TODO(nanzhang): Add a Soong property to handle documentation args.
-			flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
-			flags.metalavaDocsFlags = d.collectMetalavaDocsFlags(ctx, flags.bootClasspathArgs, flags.classpathArgs)
-			opts += " " + strings.Split(flags.args, "--generate-documentation")[0] + " " +
-				flags.metalavaDocsFlags + flags.doclavaDocsFlags +
-				" " + strings.Split(flags.args, "--generate-documentation")[1]
+		outDir := android.PathForModuleOut(ctx, "out").String()
+		docStubsDir := android.PathForModuleOut(ctx, "docStubsDir").String()
+		// TODO(nanzhang): Add a Soong property to handle documentation args.
+		if strings.Contains(flags.args, "--generate-documentation") { // enable docs generation
+			if Bool(d.properties.Dokka_enabled) {
+				flags.metalavaDokkaFlags = d.collectMetalavaDokkaFlags(ctx, &implicits,
+					flags.dokkaClasspathArgs, outDir, docStubsDir)
+				d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
+					flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
+						flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
+						flags.metalavaDokkaFlags+" "+strings.Split(flags.args, "--generate-documentation")[1])
+			} else {
+				flags.metalavaJavadocFlags = d.collectMetalavaJavadocFlags(
+					ctx, flags.bootClasspathArgs, flags.classpathArgs, outDir, docStubsDir)
+				flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
+				d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
+					flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
+						flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
+						flags.metalavaJavadocFlags+flags.doclavaDocsFlags+
+						" "+strings.Split(flags.args, "--generate-documentation")[1])
+			}
 		} else {
-			opts += " " + flags.args
+			d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
+				flags.bootClasspathArgs, flags.classpathArgs,
+				flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.args)
 		}
-		ctx.Build(pctx, android.BuildParams{
-			Rule:            metalava,
-			Description:     "Metalava",
-			Output:          d.Javadoc.stubsSrcJar,
-			Inputs:          d.Javadoc.srcFiles,
-			Implicits:       implicits,
-			ImplicitOutputs: implicitOutputs,
-			Args: map[string]string{
-				"outDir":            android.PathForModuleOut(ctx, "docs", "out").String(),
-				"srcJarDir":         android.PathForModuleOut(ctx, "docs", "srcjars").String(),
-				"stubsDir":          android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
-				"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
-				"javaVersion":       javaVersion,
-				"bootclasspathArgs": flags.bootClasspathArgs,
-				"classpathArgs":     flags.classpathArgs,
-				"sourcepath":        strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
-				"docZip":            d.Javadoc.docZip.String(),
-				"opts":              opts,
-			},
-		})
 	} else {
 		flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
 		flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits)
-		ctx.Build(pctx, android.BuildParams{
-			Rule:            javadoc,
-			Description:     "Droiddoc",
-			Output:          d.Javadoc.stubsSrcJar,
-			Inputs:          d.Javadoc.srcFiles,
-			Implicits:       implicits,
-			ImplicitOutputs: implicitOutputs,
-			Args: map[string]string{
-				"outDir":            android.PathForModuleOut(ctx, "docs", "out").String(),
-				"srcJarDir":         android.PathForModuleOut(ctx, "docs", "srcjars").String(),
-				"stubsDir":          android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
-				"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
-				"opts":              flags.doclavaDocsFlags + flags.doclavaStubsFlags + " " + flags.args,
-				"bootclasspathArgs": flags.bootClasspathArgs,
-				"classpathArgs":     flags.classpathArgs,
-				"sourcepath":        strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
-				"docZip":            d.Javadoc.docZip.String(),
-				"postDoclavaCmds":   flags.postDoclavaCmds,
-			},
-		})
+		d.transformDoclava(ctx, implicits, implicitOutputs, flags.bootClasspathArgs, flags.classpathArgs,
+			flags.doclavaDocsFlags+flags.doclavaStubsFlags+" "+flags.args,
+			flags.postDoclavaCmds)
 	}
 
 	if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() {
@@ -1077,46 +1161,21 @@
 		removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file),
 			"check_api.current_removed_api_file")
 
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        apiCheck,
-			Description: "Current API check",
-			Output:      d.checkCurrentApiTimestamp,
-			Inputs:      nil,
-			Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
-				checkApiClasspath...),
-			Args: map[string]string{
-				"classpath":             checkApiClasspath.FormJavaClassPath(""),
-				"opts":                  String(d.properties.Check_api.Current.Args),
-				"apiFile":               apiFile.String(),
-				"apiFileToCheck":        d.apiFile.String(),
-				"removedApiFile":        removedApiFile.String(),
-				"removedApiFileToCheck": d.removedApiFile.String(),
-				"msg": fmt.Sprintf(`\n******************************\n`+
-					`You have tried to change the API from what has been previously approved.\n\n`+
-					`To make these errors go away, you have two choices:\n`+
-					`   1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
-					`      errors above.\n\n`+
-					`   2. You can update current.txt by executing the following command:\n`+
-					`         make %s-update-current-api\n\n`+
-					`      To submit the revised current.txt to the main Android repository,\n`+
-					`      you will need approval.\n`+
-					`******************************\n`, ctx.ModuleName()),
-			},
-		})
+		d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
+			fmt.Sprintf(`\n******************************\n`+
+				`You have tried to change the API from what has been previously approved.\n\n`+
+				`To make these errors go away, you have two choices:\n`+
+				`   1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
+				`      errors above.\n\n`+
+				`   2. You can update current.txt by executing the following command:\n`+
+				`         make %s-update-current-api\n\n`+
+				`      To submit the revised current.txt to the main Android repository,\n`+
+				`      you will need approval.\n`+
+				`******************************\n`, ctx.ModuleName()), String(d.properties.Check_api.Current.Args),
+			d.checkCurrentApiTimestamp)
 
 		d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        updateApi,
-			Description: "update current API",
-			Output:      d.updateCurrentApiTimestamp,
-			Implicits:   append(android.Paths{}, apiFile, removedApiFile, d.apiFile, d.removedApiFile),
-			Args: map[string]string{
-				"apiFile":               apiFile.String(),
-				"apiFileToCheck":        d.apiFile.String(),
-				"removedApiFile":        removedApiFile.String(),
-				"removedApiFileToCheck": d.removedApiFile.String(),
-			},
-		})
+		d.transformUpdateApi(ctx, apiFile, removedApiFile, d.updateCurrentApiTimestamp)
 	}
 
 	if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
@@ -1127,26 +1186,12 @@
 		removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
 			"check_api.last_released.removed_api_file")
 
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        apiCheck,
-			Description: "Last Released API check",
-			Output:      d.checkLastReleasedApiTimestamp,
-			Inputs:      nil,
-			Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
-				checkApiClasspath...),
-			Args: map[string]string{
-				"classpath":             checkApiClasspath.FormJavaClassPath(""),
-				"opts":                  String(d.properties.Check_api.Last_released.Args),
-				"apiFile":               apiFile.String(),
-				"apiFileToCheck":        d.apiFile.String(),
-				"removedApiFile":        removedApiFile.String(),
-				"removedApiFileToCheck": d.removedApiFile.String(),
-				"msg": `\n******************************\n` +
-					`You have tried to change the API from what has been previously released in\n` +
-					`an SDK.  Please fix the errors listed above.\n` +
-					`******************************\n`,
-			},
-		})
+		d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
+			`\n******************************\n`+
+				`You have tried to change the API from what has been previously released in\n`+
+				`an SDK.  Please fix the errors listed above.\n`+
+				`******************************\n`, String(d.properties.Check_api.Last_released.Args),
+			d.checkLastReleasedApiTimestamp)
 	}
 }
 
diff --git a/java/java.go b/java/java.go
index 700b917..c912368 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1573,6 +1573,10 @@
 	})
 
 	j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
+	if Bool(j.properties.Installable) {
+		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+			ctx.ModuleName()+".jar", outputFile)
+	}
 }
 
 var _ Dependency = (*Import)(nil)