Merge "Deprecate Snapshot build" into main
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index c76d9c2..dd09fbf 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -115,10 +115,6 @@
 func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
 	addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
 		for _, content := range m.Contents() {
-			// Skip any apexes that have been added to the product specific ignore list
-			if InList(content, ctx.Config().BuildIgnoreApexContributionContents()) {
-				continue
-			}
 			// Coverage builds for TARGET_RELEASE=foo should always build from source,
 			// even if TARGET_RELEASE=foo uses prebuilt mainline modules.
 			// This is necessary because the checked-in prebuilts were generated with
@@ -141,13 +137,19 @@
 	}
 
 	p := PrebuiltSelectionInfoMap{}
-	ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
-		if m, ok := child.(*apexContributions); ok {
-			addContentsToProvider(&p, m)
-		} else {
-			ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
-		}
-	})
+	// Skip apex_contributions if BuildApexContributionContents is true
+	// This product config var allows some products in the same family to use mainline modules from source
+	// (e.g. shiba and shiba_fullmte)
+	// Eventually these product variants will have their own release config maps.
+	if !proptools.Bool(ctx.Config().BuildIgnoreApexContributionContents()) {
+		ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
+			if m, ok := child.(*apexContributions); ok {
+				addContentsToProvider(&p, m)
+			} else {
+				ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
+			}
+		})
+	}
 	SetProvider(ctx, PrebuiltSelectionInfoProvider, p)
 }
 
diff --git a/android/config.go b/android/config.go
index 651b6ea..f2f7d7d 100644
--- a/android/config.go
+++ b/android/config.go
@@ -2122,7 +2122,7 @@
 	return ret
 }
 
-func (c *config) BuildIgnoreApexContributionContents() []string {
+func (c *config) BuildIgnoreApexContributionContents() *bool {
 	return c.productVariables.BuildIgnoreApexContributionContents
 }
 
diff --git a/android/paths.go b/android/paths.go
index 61c1258..a40f482 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1831,17 +1831,13 @@
 	return base.Join(ctx, pathComponents...)
 }
 
-func pathForNdkOrSdkInstall(ctx PathContext, prefix string, paths []string) InstallPath {
-	base := pathForPartitionInstallDir(ctx, "", prefix, false)
-	return base.Join(ctx, paths...)
-}
-
-func PathForNdkInstall(ctx PathContext, paths ...string) InstallPath {
-	return pathForNdkOrSdkInstall(ctx, "ndk", paths)
+func PathForNdkInstall(ctx PathContext, paths ...string) OutputPath {
+	return PathForOutput(ctx, append([]string{"ndk"}, paths...)...)
 }
 
 func PathForMainlineSdksInstall(ctx PathContext, paths ...string) InstallPath {
-	return pathForNdkOrSdkInstall(ctx, "mainline-sdks", paths)
+	base := pathForPartitionInstallDir(ctx, "", "mainline-sdks", false)
+	return base.Join(ctx, paths...)
 }
 
 func InstallPathToOnDevicePath(ctx PathContext, path InstallPath) string {
diff --git a/android/selects_test.go b/android/selects_test.go
index adbe59a..a54459c 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -39,7 +39,7 @@
 				my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": ["a.cpp"],
 					"b": ["b.cpp"],
-					_: ["c.cpp"],
+					default: ["c.cpp"],
 				}),
 			}
 			`,
@@ -55,7 +55,7 @@
 				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": "a.cpp",
 					"b": "b.cpp",
-					_: "c.cpp",
+					default: "c.cpp",
 				}),
 			}
 			`,
@@ -71,7 +71,7 @@
 				my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": true,
 					"b": false,
-					_: true,
+					default: true,
 				}),
 			}
 			`,
@@ -87,7 +87,7 @@
 				my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": ["foo.txt"],
 					"b": ["bar.txt"],
-					_: ["baz.txt"],
+					default: ["baz.txt"],
 				}),
 			}
 			`,
@@ -103,7 +103,7 @@
 				my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": [":a"],
 					"b": [":b"],
-					_: [":c"],
+					default: [":c"],
 				}),
 			}
 			`,
@@ -117,11 +117,25 @@
 				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": "a.cpp",
 					"b": true,
-					_: "c.cpp",
+					default: "c.cpp",
 				}),
 			}
 			`,
-			expectedError: `can't assign bool value to string property "my_string\[1\]"`,
+			expectedError: `Android.bp:8:5: Found select statement with differing types "string" and "bool" in its cases`,
+		},
+		{
+			name: "Select type doesn't match property type",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+					"a": false,
+					"b": true,
+					default: true,
+				}),
+			}
+			`,
+			expectedError: `can't assign bool value to string property "my_string\[0\]"`,
 		},
 		{
 			name: "String list non-default",
@@ -131,7 +145,7 @@
 				my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": ["a.cpp"],
 					"b": ["b.cpp"],
-					_: ["c.cpp"],
+					default: ["c.cpp"],
 				}),
 			}
 			`,
@@ -152,11 +166,11 @@
 				my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": ["a.cpp"],
 					"b": ["b.cpp"],
-					_: ["c.cpp"],
+					default: ["c.cpp"],
 				}) + select(soong_config_variable("my_namespace", "my_variable_2"), {
 					"a2": ["a2.cpp"],
 					"b2": ["b2.cpp"],
-					_: ["c2.cpp"],
+					default: ["c2.cpp"],
 				}),
 			}
 			`,
@@ -177,7 +191,7 @@
 				my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
 					"a2": ["a2.cpp"],
 					"b2": ["b2.cpp"],
-					_: ["c2.cpp"],
+					default: ["c2.cpp"],
 				}),
 			}
 			`,
@@ -193,7 +207,7 @@
 				my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a2": ["a2.cpp"],
 					"b2": ["b2.cpp"],
-					_: ["c2.cpp"],
+					default: ["c2.cpp"],
 				}) + ["literal.cpp"],
 			}
 			`,
@@ -209,7 +223,7 @@
 				my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": true,
 					"b": false,
-					_: true,
+					default: true,
 				}) + false,
 			}
 			`,
@@ -225,7 +239,7 @@
 				my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": true,
 					"b": false,
-					_: true,
+					default: true,
 				}) + false,
 			}
 			`,
@@ -246,7 +260,7 @@
 				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
 					"a": "a",
 					"b": "b",
-					_: "c",
+					default: "c",
 				}) + ".cpp",
 			}
 			`,
@@ -264,7 +278,7 @@
 					"x86_64": "my_x86_64",
 					"arm": "my_arm",
 					"arm64": "my_arm64",
-					_: "my_default",
+					default: "my_default",
 				}),
 			}
 			`,
@@ -272,6 +286,88 @@
 				my_string: proptools.StringPtr("my_arm64"),
 			},
 		},
+		{
+			name: "Unset value",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+					"a": unset,
+					"b": "b",
+					default: "c",
+				})
+			}
+			`,
+			vendorVars: map[string]map[string]string{
+				"my_namespace": {
+					"my_variable": "a",
+				},
+			},
+			provider: selectsTestProvider{},
+		},
+		{
+			name: "Unset value on different branch",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+					"a": unset,
+					"b": "b",
+					default: "c",
+				})
+			}
+			`,
+			provider: selectsTestProvider{
+				my_string: proptools.StringPtr("c"),
+			},
+		},
+		{
+			name: "unset + unset = unset",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+					default: unset,
+				}) + select(soong_config_variable("my_namespace", "my_variable2"), {
+					default: unset,
+				})
+			}
+			`,
+			provider: selectsTestProvider{},
+		},
+		{
+			name: "unset + string = string",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+					default: unset,
+				}) + select(soong_config_variable("my_namespace", "my_variable2"), {
+					default: "a",
+				})
+			}
+			`,
+			provider: selectsTestProvider{
+				my_string: proptools.StringPtr("a"),
+			},
+		},
+		{
+			name: "unset + bool = bool",
+			bp: `
+			my_module_type {
+				name: "foo",
+				my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
+					"a": true,
+					default: unset,
+				}) + select(soong_config_variable("my_namespace", "my_variable2"), {
+					default: true,
+				})
+			}
+			`,
+			provider: selectsTestProvider{
+				my_bool: proptools.BoolPtr(true),
+			},
+		},
 	}
 
 	for _, tc := range testCases {
diff --git a/android/variable.go b/android/variable.go
index fc5ae23..b0afd5b 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -499,7 +499,7 @@
 
 	BuildFromSourceStub *bool `json:",omitempty"`
 
-	BuildIgnoreApexContributionContents []string `json:",omitempty"`
+	BuildIgnoreApexContributionContents *bool `json:",omitempty"`
 
 	HiddenapiExportableStubs *bool `json:",omitempty"`
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index fae8fcc..1e75948 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7166,7 +7166,7 @@
 
 	// The bar library should depend on the implementation jar.
 	barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
-	if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+	if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
 		t.Errorf("expected %q, found %#q", expected, actual)
 	}
 }
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5fe71f0..ef26366 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -446,6 +446,7 @@
 		if c.parsedCoverageXmlPath.String() != "" {
 			entries.SetString("SOONG_NDK_API_XML", "$(SOONG_NDK_API_XML) "+c.parsedCoverageXmlPath.String())
 		}
+		entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) // Stubs should not be installed
 	})
 }
 
diff --git a/cc/builder.go b/cc/builder.go
index f28f47f..845176e 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -854,14 +854,15 @@
 // Generate a rule to combine .dump sAbi dump files from multiple source files
 // into a single .ldump sAbi dump file
 func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
-	baseName, exportedHeaderFlags string, symbolFile android.OptionalPath,
+	baseName string, exportedIncludeDirs []string, symbolFile android.OptionalPath,
 	excludedSymbolVersions, excludedSymbolTags []string,
-	api string) android.OptionalPath {
+	api string) android.Path {
 
 	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
 
 	implicits := android.Paths{soFile}
 	symbolFilterStr := "-so " + soFile.String()
+	exportedHeaderFlags := android.JoinWithPrefix(exportedIncludeDirs, "-I")
 
 	if symbolFile.Valid() {
 		implicits = append(implicits, symbolFile.Path())
@@ -886,13 +887,7 @@
 	}
 	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_LINKER") {
 		rule = sAbiLinkRE
-		rbeImplicits := implicits.Strings()
-		for _, p := range strings.Split(exportedHeaderFlags, " ") {
-			if len(p) > 2 {
-				// Exclude the -I prefix.
-				rbeImplicits = append(rbeImplicits, p[2:])
-			}
-		}
+		rbeImplicits := append(implicits.Strings(), exportedIncludeDirs...)
 		args["implicitInputs"] = strings.Join(rbeImplicits, ",")
 	}
 	ctx.Build(pctx, android.BuildParams{
@@ -903,7 +898,7 @@
 		Implicits:   implicits,
 		Args:        args,
 	})
-	return android.OptionalPathForPath(outputFile)
+	return outputFile
 }
 
 func transformAbiDumpToAbiDiff(ctx android.ModuleContext, inputDump, referenceDump android.Path,
diff --git a/cc/library.go b/cc/library.go
index e840c3e..3887c7a 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -390,9 +390,6 @@
 	// Output archive of gcno coverage information files
 	coverageOutputFile android.OptionalPath
 
-	// linked Source Abi Dump
-	sAbiOutputFile android.OptionalPath
-
 	// Source Abi Diff
 	sAbiDiff android.Paths
 
@@ -639,15 +636,11 @@
 		return Objects{}
 	}
 	if library.sabi.shouldCreateSourceAbiDump() {
-		exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
-		var SourceAbiFlags []string
-		for _, dir := range exportIncludeDirs.Strings() {
-			SourceAbiFlags = append(SourceAbiFlags, "-I"+dir)
+		dirs := library.exportedIncludeDirsForAbiCheck(ctx)
+		flags.SAbiFlags = make([]string, 0, len(dirs))
+		for _, dir := range dirs {
+			flags.SAbiFlags = append(flags.SAbiFlags, "-I"+dir)
 		}
-		for _, reexportedInclude := range library.sabi.Properties.ReexportedIncludes {
-			SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
-		}
-		flags.SAbiFlags = SourceAbiFlags
 		totalLength := len(library.baseCompiler.Properties.Srcs) + len(deps.GeneratedSources) +
 			len(library.SharedProperties.Shared.Srcs) + len(library.StaticProperties.Static.Srcs)
 		if totalLength > 0 {
@@ -1221,6 +1214,12 @@
 	return library.coverageOutputFile
 }
 
+func (library *libraryDecorator) exportedIncludeDirsForAbiCheck(ctx ModuleContext) []string {
+	exportIncludeDirs := library.flagExporter.exportedIncludes(ctx).Strings()
+	exportIncludeDirs = append(exportIncludeDirs, library.sabi.Properties.ReexportedIncludes...)
+	return exportIncludeDirs
+}
+
 func getRefAbiDumpFile(ctx android.ModuleInstallPathContext,
 	versionedDumpDir, fileName string) android.OptionalPath {
 
@@ -1267,12 +1266,11 @@
 }
 
 // sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
-func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
+func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext,
+	sourceDump, referenceDump android.Path,
 	baseName, nameExt string, isLlndkOrNdk, allowExtensions bool,
 	sourceVersion, errorMessage string) {
 
-	sourceDump := library.sAbiOutputFile.Path()
-
 	extraFlags := []string{"-target-version", sourceVersion}
 	headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
 	if Bool(headerAbiChecker.Check_all_apis) {
@@ -1296,26 +1294,29 @@
 			baseName, nameExt, extraFlags, errorMessage))
 }
 
-func (library *libraryDecorator) crossVersionAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
+func (library *libraryDecorator) crossVersionAbiDiff(ctx android.ModuleContext,
+	sourceDump, referenceDump android.Path,
 	baseName string, isLlndkOrNdk bool, sourceVersion, prevVersion string) {
 
 	errorMessage := "error: Please follow https://android.googlesource.com/platform/development/+/main/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the ABI difference between your source code and version " + prevVersion + "."
 
-	library.sourceAbiDiff(ctx, referenceDump, baseName, prevVersion,
+	library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, prevVersion,
 		isLlndkOrNdk, true /* allowExtensions */, sourceVersion, errorMessage)
 }
 
-func (library *libraryDecorator) sameVersionAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
+func (library *libraryDecorator) sameVersionAbiDiff(ctx android.ModuleContext,
+	sourceDump, referenceDump android.Path,
 	baseName, nameExt string, isLlndkOrNdk bool) {
 
 	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
 	errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName
 
-	library.sourceAbiDiff(ctx, referenceDump, baseName, nameExt,
+	library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
 		isLlndkOrNdk, false /* allowExtensions */, "current", errorMessage)
 }
 
-func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
+func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext,
+	sourceDump, referenceDump android.Path,
 	baseName, nameExt string, refDumpDir string) {
 
 	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
@@ -1325,33 +1326,26 @@
 		errorMessage += " -products " + ctx.Config().DeviceProduct()
 	}
 
-	library.sourceAbiDiff(ctx, referenceDump, baseName, nameExt,
+	library.sourceAbiDiff(ctx, sourceDump, referenceDump, baseName, nameExt,
 		false /* isLlndkOrNdk */, false /* allowExtensions */, "current", errorMessage)
 }
 
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
 	if library.sabi.shouldCreateSourceAbiDump() {
-		exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
-		var SourceAbiFlags []string
-		for _, dir := range exportIncludeDirs.Strings() {
-			SourceAbiFlags = append(SourceAbiFlags, "-I"+dir)
-		}
-		for _, reexportedInclude := range library.sabi.Properties.ReexportedIncludes {
-			SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
-		}
-		exportedHeaderFlags := strings.Join(SourceAbiFlags, " ")
+		exportedIncludeDirs := library.exportedIncludeDirsForAbiCheck(ctx)
 		headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
 		currSdkVersion := currRefAbiDumpSdkVersion(ctx)
 		currVendorVersion := ctx.Config().VendorApiLevel()
-		library.sAbiOutputFile = transformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
+		sourceDump := transformDumpToLinkedDump(ctx,
+			objs.sAbiDumpFiles, soFile, fileName,
+			exportedIncludeDirs,
 			android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
 			headerAbiChecker.Exclude_symbol_versions,
 			headerAbiChecker.Exclude_symbol_tags,
 			currSdkVersion)
 
 		for _, tag := range classifySourceAbiDump(ctx) {
-			addLsdumpPath(string(tag) + ":" + library.sAbiOutputFile.String())
-
+			addLsdumpPath(string(tag) + ":" + sourceDump.String())
 			dumpDirName := tag.dirName()
 			if dumpDirName == "" {
 				continue
@@ -1376,7 +1370,7 @@
 			prevDumpDir := filepath.Join(dumpDir, prevVersion, binderBitness)
 			prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
 			if prevDumpFile.Valid() {
-				library.crossVersionAbiDiff(ctx, prevDumpFile.Path(),
+				library.crossVersionAbiDiff(ctx, sourceDump, prevDumpFile.Path(),
 					fileName, isLlndk || isNdk, currVersion, nameExt+prevVersion)
 			}
 			// Check against the current version.
@@ -1388,7 +1382,7 @@
 			currDumpDir := filepath.Join(dumpDir, currVersion, binderBitness)
 			currDumpFile := getRefAbiDumpFile(ctx, currDumpDir, fileName)
 			if currDumpFile.Valid() {
-				library.sameVersionAbiDiff(ctx, currDumpFile.Path(),
+				library.sameVersionAbiDiff(ctx, sourceDump, currDumpFile.Path(),
 					fileName, nameExt, isLlndk || isNdk)
 			}
 		}
@@ -1401,7 +1395,8 @@
 			if !optInDumpFile.Valid() {
 				continue
 			}
-			library.optInAbiDiff(ctx, optInDumpFile.Path(),
+			library.optInAbiDiff(ctx,
+				sourceDump, optInDumpFile.Path(),
 				fileName, "opt"+strconv.Itoa(i), optInDumpDirPath.String())
 		}
 	}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 567cb7c..57a3b3a 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -15,7 +15,6 @@
 package cc
 
 import (
-	"fmt"
 	"path/filepath"
 
 	"android/soong/android"
@@ -45,7 +44,7 @@
 }
 
 // Returns the NDK base include path for use with sdk_version current. Usable with -I.
-func getCurrentIncludePath(ctx android.ModuleContext) android.InstallPath {
+func getCurrentIncludePath(ctx android.ModuleContext) android.OutputPath {
 	return getNdkSysrootBase(ctx).Join(ctx, "usr/include")
 }
 
@@ -87,7 +86,7 @@
 }
 
 func getHeaderInstallDir(ctx android.ModuleContext, header android.Path, from string,
-	to string) android.InstallPath {
+	to string) android.OutputPath {
 	// Output path is the sysroot base + "usr/include" + to directory + directory component
 	// of the file without the leading from directory stripped.
 	//
@@ -129,13 +128,12 @@
 	for _, header := range m.srcPaths {
 		installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
 			String(m.properties.To))
-		installedPath := ctx.InstallFile(installDir, header.Base(), header)
 		installPath := installDir.Join(ctx, header.Base())
-		if installPath != installedPath {
-			panic(fmt.Sprintf(
-				"expected header install path (%q) not equal to actual install path %q",
-				installPath, installedPath))
-		}
+		ctx.Build(pctx, android.BuildParams{
+			Rule:   android.Cp,
+			Input:  header,
+			Output: installPath,
+		})
 		m.installPaths = append(m.installPaths, installPath)
 	}
 
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 64193b1..39dd415 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -518,19 +518,25 @@
 
 // Returns the install path for unversioned NDK libraries (currently only static
 // libraries).
-func getUnversionedLibraryInstallPath(ctx ModuleContext) android.InstallPath {
+func getUnversionedLibraryInstallPath(ctx ModuleContext) android.OutputPath {
 	return getNdkSysrootBase(ctx).Join(ctx, "usr/lib", config.NDKTriple(ctx.toolchain()))
 }
 
 // Returns the install path for versioned NDK libraries. These are most often
 // stubs, but the same paths are used for CRT objects.
-func getVersionedLibraryInstallPath(ctx ModuleContext, apiLevel android.ApiLevel) android.InstallPath {
+func getVersionedLibraryInstallPath(ctx ModuleContext, apiLevel android.ApiLevel) android.OutputPath {
 	return getUnversionedLibraryInstallPath(ctx).Join(ctx, apiLevel.String())
 }
 
 func (stub *stubDecorator) install(ctx ModuleContext, path android.Path) {
 	installDir := getVersionedLibraryInstallPath(ctx, stub.apiLevel)
-	stub.installPath = ctx.InstallFile(installDir, path.Base(), path)
+	out := installDir.Join(ctx, path.Base())
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.Cp,
+		Input:  path,
+		Output: out,
+	})
+	stub.installPath = out
 }
 
 func newStubLibrary() *Module {
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 483d23b..e815172 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -69,12 +69,12 @@
 	ctx.RegisterParallelSingletonType("ndk", NdkSingleton)
 }
 
-func getNdkInstallBase(ctx android.PathContext) android.InstallPath {
+func getNdkInstallBase(ctx android.PathContext) android.OutputPath {
 	return android.PathForNdkInstall(ctx)
 }
 
 // Returns the main install directory for the NDK sysroot. Usable with --sysroot.
-func getNdkSysrootBase(ctx android.PathContext) android.InstallPath {
+func getNdkSysrootBase(ctx android.PathContext) android.OutputPath {
 	return getNdkInstallBase(ctx).Join(ctx, "sysroot")
 }
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 5ddc675..355654f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -949,6 +949,10 @@
 
 	// Functionality related to this being used as a component of a java_sdk_library.
 	EmbeddableSdkLibraryComponent
+
+	// Path to the header jars of the implementation library
+	// This is non-empty only when api_only is false.
+	implLibraryHeaderJars android.Paths
 }
 
 func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
@@ -1356,13 +1360,6 @@
 	// class changes but it does not contain and implementation or JavaDoc.
 	SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
 
-	// Get the implementation jars appropriate for the supplied sdk version.
-	//
-	// These are either the implementation jar for the whole sdk library or the implementation
-	// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
-	// they are identical to the corresponding header jars.
-	SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
-
 	// SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt
 	// java_sdk_library_import module. It is needed by the hiddenapi processing tool which
 	// processes dex files.
@@ -1599,6 +1596,12 @@
 
 			exportedComponents[ctx.OtherModuleName(to)] = struct{}{}
 		}
+
+		if tag == implLibraryTag {
+			if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok {
+				module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...)
+			}
+		}
 	})
 
 	// Make the set of components exported by this module available for use elsewhere.
@@ -2238,7 +2241,7 @@
 	return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
 }
 
-func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
+func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
 	// If the client doesn't set sdk_version, but if this library prefers stubs over
 	// the impl library, let's provide the widest API surface possible. To do so,
 	// force override sdk_version to module_current so that the closest possible API
@@ -2255,11 +2258,7 @@
 		// * No sdk_version specified on the referencing module.
 		// * The referencing module is in the same apex as this.
 		if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) {
-			if headerJars {
-				return module.HeaderJars()
-			} else {
-				return module.ImplementationJars()
-			}
+			return module.implLibraryHeaderJars
 		}
 	}
 
@@ -2268,12 +2267,7 @@
 
 // to satisfy SdkLibraryDependency interface
 func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
-	return module.sdkJars(ctx, sdkVersion, true /*headerJars*/)
-}
-
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
-	return module.sdkJars(ctx, sdkVersion, false /*headerJars*/)
+	return module.sdkJars(ctx, sdkVersion)
 }
 
 var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
@@ -2983,12 +2977,6 @@
 	return module.sdkJars(ctx, sdkVersion, true)
 }
 
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
-	// This module is just a wrapper for the stubs.
-	return module.sdkJars(ctx, sdkVersion, false)
-}
-
 // to satisfy UsesLibraryDependency interface
 func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
 	// The dex implementation jar extracted from the .apex file should be used in preference to the
diff --git a/licenses/Android.bp b/licenses/Android.bp
index d045725..e4e5da7 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -1126,6 +1126,12 @@
 }
 
 license_kind {
+    name: "SPDX-license-identifier-Unicode-3.0",
+    conditions: ["notice"],
+    url: "https://spdx.org/licenses/Unicode-3.0.html",
+}
+
+license_kind {
     name: "SPDX-license-identifier-Unicode-DFS-2015",
     conditions: ["notice"],
     url: "https://spdx.org/licenses/Unicode-DFS-2015.html",