Merge changes from topic "soong-cc-install"

* changes:
  Move cc module installation into Soong
  Temporarily add method to get java binary tool
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 94b8116..80237fb 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -326,6 +326,9 @@
 	var required []string
 	var targetRequired []string
 	var hostRequired []string
+	required = append(required, a.RequiredModuleNames()...)
+	targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...)
+	hostRequired = append(hostRequired, a.HostRequiredModuleNames()...)
 	installMapSet := make(map[string]bool) // set of dependency module:location mappings
 	for _, fi := range a.filesInfo {
 		required = append(required, fi.requiredModuleNames...)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8aaa31a..59ea206 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -8350,6 +8350,46 @@
 		})
 }
 
+func TestAndroidMk_RequiredModules(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			updatable: false,
+			java_libs: ["foo"],
+			required: ["otherapex"],
+		}
+
+		apex {
+			name: "otherapex",
+			key: "myapex.key",
+			updatable: false,
+			java_libs: ["foo"],
+			required: ["otherapex"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_library {
+			name: "foo",
+			srcs: ["foo.java"],
+			apex_available: ["myapex", "otherapex"],
+			installable: true,
+		}
+	`)
+
+	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
+	var builder strings.Builder
+	data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
+	androidMk := builder.String()
+	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += otherapex")
+}
+
 func TestMain(m *testing.M) {
 	os.Exit(m.Run())
 }
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 0dedcf4..6d96b1c 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -245,9 +245,9 @@
 			out := outputPaths[0]
 			outDir := proptools.ShellEscapeIncludingSpaces(filepath.Dir(out))
 			out = proptools.ShellEscapeIncludingSpaces(out)
-			in := proptools.ShellEscapeIncludingSpaces(inputPaths[0])
-			// Use hard links, because some soong actions expect real files (for example, `cp -d`).
-			buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -f %[3]s %[2]s", outDir, out, in)
+			in := filepath.Join("$PWD", proptools.ShellEscapeIncludingSpaces(inputPaths[0]))
+			// Use absolute paths, because some soong actions don't play well with relative paths (for example, `cp -d`).
+			buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -sf %[3]s %[2]s", outDir, out, in)
 			buildStatement.SymlinkPaths = outputPaths[:]
 		} else if len(actionEntry.Arguments) < 1 {
 			return nil, fmt.Errorf("received action with no command: [%v]", buildStatement)
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 88066c8..69f1115 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -859,7 +859,7 @@
 		BuildStatement{
 			Command: "mkdir -p one/symlink_subdir && " +
 				"rm -f one/symlink_subdir/symlink && " +
-				"ln -f one/file_subdir/file one/symlink_subdir/symlink",
+				"ln -sf $PWD/one/file_subdir/file one/symlink_subdir/symlink",
 			InputPaths:   []string{"one/file_subdir/file"},
 			OutputPaths:  []string{"one/symlink_subdir/symlink"},
 			SymlinkPaths: []string{"one/symlink_subdir/symlink"},
@@ -923,14 +923,14 @@
 		BuildStatement{
 			Command: "mkdir -p 'one/symlink subdir' && " +
 				"rm -f 'one/symlink subdir/symlink' && " +
-				"ln -f 'one/file subdir/file' 'one/symlink subdir/symlink'",
+				"ln -sf $PWD/'one/file subdir/file' 'one/symlink subdir/symlink'",
 			InputPaths:   []string{"one/file subdir/file"},
 			OutputPaths:  []string{"one/symlink subdir/symlink"},
 			SymlinkPaths: []string{"one/symlink subdir/symlink"},
 			Mnemonic:     "SolibSymlink",
 		},
 	}
-	assertBuildStatements(t, actual, expectedBuildStatements)
+	assertBuildStatements(t, expectedBuildStatements, actual)
 }
 
 func TestSymlinkMultipleInputs(t *testing.T) {
diff --git a/cc/builder.go b/cc/builder.go
index abd5f1d..72c2fa5 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -949,8 +949,7 @@
 }
 
 // Generate a rule for extracting a table of contents from a shared library (.so)
-func transformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
-	outputFile android.WritablePath, flags builderFlags) {
+func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) {
 
 	var format string
 	if ctx.Darwin() {
diff --git a/cc/library.go b/cc/library.go
index c3f7305..a394409 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1377,7 +1377,7 @@
 	// depending on a table of contents file instead of the library itself.
 	tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
 	library.tocFile = android.OptionalPathForPath(tocFile)
-	transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
+	TransformSharedObjectToToc(ctx, outputFile, tocFile)
 
 	stripFlags := flagsToStripFlags(flags)
 	needsStrip := library.stripper.NeedsStrip(ctx)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 3401e36..16945ac 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -114,8 +114,6 @@
 	// TODO(ccross): verify shared library dependencies
 	srcs := p.prebuiltSrcs(ctx)
 	if len(srcs) > 0 {
-		builderFlags := flagsToBuilderFlags(flags)
-
 		if len(srcs) > 1 {
 			ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
 			return nil
@@ -152,7 +150,7 @@
 			// depending on a table of contents file instead of the library itself.
 			tocFile := android.PathForModuleOut(ctx, libName+".toc")
 			p.tocFile = android.OptionalPathForPath(tocFile)
-			transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
+			TransformSharedObjectToToc(ctx, outputFile, tocFile)
 
 			if ctx.Windows() && p.properties.Windows_import_lib != nil {
 				// Consumers of this library actually links to the import library in build
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f6a9d5b..c7e8411 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -39,8 +39,15 @@
 	}
 	asanLdflags = []string{"-Wl,-u,__asan_preinit"}
 
-	hwasanCflags = []string{"-fno-omit-frame-pointer", "-Wno-frame-larger-than=",
+	hwasanCflags = []string{
+		"-fno-omit-frame-pointer",
+		"-Wno-frame-larger-than=",
 		"-fsanitize-hwaddress-abi=platform",
+	}
+
+	// ThinLTO performs codegen during link time, thus these flags need to
+	// passed to both CFLAGS and LDFLAGS.
+	hwasanCommonflags = []string{
 		// The following improves debug location information
 		// availability at the cost of its accuracy. It increases
 		// the likelihood of a stack variable's frame offset
@@ -48,11 +55,11 @@
 		// for the quality of hwasan reports. The downside is a
 		// higher number of "optimized out" stack variables.
 		// b/112437883.
-		"-mllvm", "-instcombine-lower-dbg-declare=0",
+		"-instcombine-lower-dbg-declare=0",
 		// TODO(b/159343917): HWASan and GlobalISel don't play nicely, and
 		// GlobalISel is the default at -O0 on aarch64.
-		"-mllvm", "--aarch64-enable-global-isel-at-O=-1",
-		"-mllvm", "-fast-isel=false",
+		"--aarch64-enable-global-isel-at-O=-1",
+		"-fast-isel=false",
 	}
 
 	cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
@@ -629,6 +636,14 @@
 
 	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
 		flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...)
+
+		for _, flag := range hwasanCommonflags {
+			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag)
+		}
+		for _, flag := range hwasanCommonflags {
+			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag)
+		}
+
 		if Bool(sanitize.Properties.Sanitize.Writeonly) {
 			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
 		}
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 9570664..d9b0bbe 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -476,13 +476,12 @@
 
 	if p.shared() {
 		libName := in.Base()
-		builderFlags := flagsToBuilderFlags(flags)
 
 		// Optimize out relinking against shared libraries whose interface hasn't changed by
 		// depending on a table of contents file instead of the library itself.
 		tocFile := android.PathForModuleOut(ctx, libName+".toc")
 		p.tocFile = android.OptionalPathForPath(tocFile)
-		transformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+		TransformSharedObjectToToc(ctx, in, tocFile)
 
 		ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
 			SharedLibrary: in,
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index da34f36..31b6d10 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -144,7 +144,6 @@
 		// current VNDK prebuilts are only shared libs.
 
 		in := p.singleSourcePath(ctx)
-		builderFlags := flagsToBuilderFlags(flags)
 		p.unstrippedOutputFile = in
 		libName := in.Base()
 		if p.stripper.NeedsStrip(ctx) {
@@ -158,7 +157,7 @@
 		// depending on a table of contents file instead of the library itself.
 		tocFile := android.PathForModuleOut(ctx, libName+".toc")
 		p.tocFile = android.OptionalPathForPath(tocFile)
-		transformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+		TransformSharedObjectToToc(ctx, in, tocFile)
 
 		p.androidMkSuffix = p.NameSuffix()
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 273efec..d7f14d6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -361,13 +361,14 @@
 	// The sdk_version to use for building the stubs.
 	//
 	// If not specified then it will use an sdk_version determined as follows:
+	//
 	// 1) If the sdk_version specified on the java_sdk_library is none then this
-	//    will be none. This is used for java_sdk_library instances that are used
-	//    to create stubs that contribute to the core_current sdk version.
-	// 2) Otherwise, it is assumed that this library extends but does not contribute
-	//    directly to a specific sdk_version and so this uses the sdk_version appropriate
-	//    for the api scope. e.g. public will use sdk_version: current, system will use
-	//    sdk_version: system_current, etc.
+	// will be none. This is used for java_sdk_library instances that are used
+	// to create stubs that contribute to the core_current sdk version.
+	// 2) Otherwise, it is assumed that this library extends but does not
+	// contribute directly to a specific sdk_version and so this uses the
+	// sdk_version appropriate for the api scope. e.g. public will use
+	// sdk_version: current, system will use sdk_version: system_current, etc.
 	//
 	// This does not affect the sdk_version used for either generating the stubs source
 	// or the API file. They both have to use the same sdk_version as is used for
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 630805a..e429416 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -137,12 +137,16 @@
 	} else if library.shared() {
 		ret.Class = "SHARED_LIBRARIES"
 	}
-
 	if library.distFile.Valid() {
 		ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
 	}
+	ret.ExtraEntries = append(ret.ExtraEntries,
+		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+			if library.tocFile.Valid() {
+				entries.SetString("LOCAL_SOONG_TOC", library.tocFile.String())
+			}
+		})
 }
-
 func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
 	ctx.SubAndroidMk(ret, procMacro.baseCompiler)
 
diff --git a/rust/builder.go b/rust/builder.go
index f79cf9b..6f20347 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -185,7 +185,7 @@
 }
 
 func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags,
-	outputFile android.WritablePath, crate_type string) buildOutput {
+	outputFile android.WritablePath, crateType string) buildOutput {
 
 	var inputs android.Paths
 	var implicits android.Paths
@@ -204,7 +204,7 @@
 	// Collect rustc flags
 	rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
 	rustcFlags = append(rustcFlags, flags.RustFlags...)
-	rustcFlags = append(rustcFlags, "--crate-type="+crate_type)
+	rustcFlags = append(rustcFlags, "--crate-type="+crateType)
 	if crateName != "" {
 		rustcFlags = append(rustcFlags, "--crate-name="+crateName)
 	}
diff --git a/rust/library.go b/rust/library.go
index 38dae4d..ea14e6d 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -102,6 +102,9 @@
 	sourceProvider    SourceProvider
 
 	collectedSnapshotHeaders android.Paths
+
+	// table-of-contents file for cdylib crates to optimize out relinking when possible
+	tocFile android.OptionalPath
 }
 
 type libraryInterface interface {
@@ -137,12 +140,18 @@
 	BuildOnlyDylib()
 	BuildOnlyStatic()
 	BuildOnlyShared()
+
+	toc() android.OptionalPath
 }
 
 func (library *libraryDecorator) nativeCoverage() bool {
 	return true
 }
 
+func (library *libraryDecorator) toc() android.OptionalPath {
+	return library.tocFile
+}
+
 func (library *libraryDecorator) rlib() bool {
 	return library.MutatedProperties.VariantIsRlib
 }
@@ -519,9 +528,16 @@
 	}
 
 	if library.shared() {
+		// Optimize out relinking against shared libraries whose interface hasn't changed by
+		// depending on a table of contents file instead of the library itself.
+		tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc")
+		library.tocFile = android.OptionalPathForPath(tocFile)
+		cc.TransformSharedObjectToToc(ctx, outputFile, tocFile)
+
 		ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
-			SharedLibrary: outputFile,
-			Target:        ctx.Target(),
+			TableOfContents: android.OptionalPathForPath(tocFile),
+			SharedLibrary:   outputFile,
+			Target:          ctx.Target(),
 		})
 	}
 
diff --git a/rust/library_test.go b/rust/library_test.go
index cb4ef7e..edb9c89 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -160,6 +160,26 @@
 	}
 }
 
+func TestSharedLibraryToc(t *testing.T) {
+	ctx := testRust(t, `
+		rust_ffi_shared {
+			name: "libfoo",
+			srcs: ["foo.rs"],
+			crate_name: "foo",
+		}
+		cc_binary {
+			name: "fizzbuzz",
+			shared_libs: ["libfoo"],
+		}`)
+
+	fizzbuzz := ctx.ModuleForTests("fizzbuzz", "android_arm64_armv8-a").Rule("ld")
+
+	if !android.SuffixInList(fizzbuzz.Implicits.Strings(), "libfoo.so.toc") {
+		t.Errorf("missing expected libfoo.so.toc implicit dependency, instead found: %#v",
+			fizzbuzz.Implicits.Strings())
+	}
+}
+
 func TestStaticLibraryLinkage(t *testing.T) {
 	ctx := testRust(t, `
 		rust_ffi_static {
diff --git a/rust/rust.go b/rust/rust.go
index c465cb6..c159e4a 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -281,8 +281,8 @@
 
 func (mod *Module) Toc() android.OptionalPath {
 	if mod.compiler != nil {
-		if _, ok := mod.compiler.(libraryInterface); ok {
-			return android.OptionalPath{}
+		if lib, ok := mod.compiler.(libraryInterface); ok {
+			return lib.toc()
 		}
 	}
 	panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName()))
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 6304a11..a376e06 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -7,3 +7,4 @@
 "$TOP/build/soong/tests/mixed_mode_test.sh"
 "$TOP/build/soong/tests/bp2build_bazel_test.sh"
 "$TOP/build/soong/tests/soong_test.sh"
+"$TOP/build/bazel/ci/rbc_product_config.sh" aosp_arm64-userdebug