Get the dex2oat host tool path from module dependency on the binary
module.

This uses the Once cache for GlobalSoongConfig to propagate the dex2oat
path from a module dependency to the singletons (both the one that
writes out dexpreopt_soong.config and the one that creates the
dexpreopted boot images). Unless dexpreopting is disabled altogether
through DisablePreopt in dexpreopt.config, that means:

- We must ensure at least one module registers a dex2oat tool
  dependency and resolves a GlobalSoongConfig using it, or else the
  singletons fail. That means we litter dex2oat dependencies in java
  modules even when they won't get dexpreopted and hence don't really
  need them.

- We still assume there's at least one java_library or android_app in
  the build.

Bug: 145934348
Test: m
  (check that out/soong/dexpreopt_soong.config points to dex2oatd64)
Test: env USE_DEX2OAT_DEBUG=false m
  (check that out/soong/dexpreopt_soong.config points to dex2oat)
Test: env OUT_DIR=out-tools prebuilts/build-tools/build-prebuilts.sh
  on the aosp-build-tools branch
Change-Id: I38317f2d5e5cf6822f87daae25745767c8a3656c
diff --git a/java/java.go b/java/java.go
index 4c6a5a5..320cb7b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -29,6 +29,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/dexpreopt"
 	"android/soong/java/config"
 	"android/soong/tradefed"
 )
@@ -79,6 +80,8 @@
 	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
 	ctx.RegisterModuleType("dex_import", DexImportFactory)
 
+	ctx.FinalDepsMutators(dexpreopt.RegisterToolDepsMutator)
+
 	ctx.RegisterSingletonType("logtags", LogtagsSingleton)
 	ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
 }
@@ -335,6 +338,7 @@
 	android.DefaultableModuleBase
 	android.ApexModuleBase
 	android.SdkBase
+	dexpreopt.DexPreoptModule
 
 	properties       CompilerProperties
 	protoProperties  android.ProtoProperties
@@ -1525,6 +1529,16 @@
 		}
 	} else {
 		outputFile = implementationAndResourcesJar
+
+		// dexpreopt.GetGlobalSoongConfig needs to be called at least once even if
+		// no module actually is dexpreopted, to ensure there's a cached
+		// GlobalSoongConfig for the dexpreopt singletons, which will run
+		// regardless.
+		// TODO(b/147613152): Remove when the singletons no longer rely on the
+		// cached GlobalSoongConfig.
+		if !dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+			_ = dexpreopt.GetGlobalSoongConfig(ctx)
+		}
 	}
 
 	ctx.CheckbuildFile(outputFile)
@@ -2275,6 +2289,7 @@
 	android.ApexModuleBase
 	prebuilt android.Prebuilt
 	android.SdkBase
+	dexpreopt.DexPreoptModule
 
 	properties ImportProperties
 
@@ -2477,6 +2492,7 @@
 	android.DefaultableModuleBase
 	android.ApexModuleBase
 	prebuilt android.Prebuilt
+	dexpreopt.DexPreoptModule
 
 	properties DexImportProperties