Merge "Provide Bazel timing breakdown for the mixed builds"
diff --git a/cc/library.go b/cc/library.go
index 897f3c7..b639930 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1875,25 +1875,21 @@
 	}
 }
 
+func currRefAbiDumpVersion(ctx ModuleContext, isVndk bool) string {
+	if isVndk {
+		// Each version of VNDK is independent, so follow the VNDK version which is the codename or PLATFORM_SDK_VERSION.
+		return ctx.Module().(*Module).VndkVersion()
+	} else if ctx.Config().PlatformSdkFinal() {
+		// After sdk finalization, the ABI of the latest API level must be consistent with the source code,
+		// so choose PLATFORM_SDK_VERSION as the current version.
+		return ctx.Config().PlatformSdkVersion().String()
+	} else {
+		return "current"
+	}
+}
+
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
 	if library.sabi.shouldCreateSourceAbiDump() {
-		var version string
-		var prevVersion int
-
-		if ctx.useVndk() {
-			// For modules linking against vndk, follow its vndk version
-			version = ctx.Module().(*Module).VndkVersion()
-		} else {
-			// After sdk finalizatoin, the ABI of the latest API level must be consistent with the source code
-			// so the chosen reference dump is the PLATFORM_SDK_VERSION.
-			if ctx.Config().PlatformSdkFinal() {
-				version = ctx.Config().PlatformSdkVersion().String()
-			} else {
-				version = "current"
-			}
-			prevVersion = prevDumpRefVersion(ctx)
-		}
-
 		exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
 		var SourceAbiFlags []string
 		for _, dir := range exportIncludeDirs.Strings() {
@@ -1910,10 +1906,12 @@
 
 		addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
 
+		isVndk := ctx.useVndk() && ctx.isVndk()
 		isNdk := ctx.isNdk(ctx.Config())
 		isLlndk := ctx.isImplementationForLLNDKPublic()
 		// If NDK or PLATFORM library, check against previous version ABI.
-		if !ctx.useVndk() {
+		if !isVndk {
+			prevVersion := prevDumpRefVersion(ctx)
 			prevRefAbiDumpFile := getRefAbiDumpFile(ctx, strconv.Itoa(prevVersion), fileName)
 			if prevRefAbiDumpFile != nil {
 				library.prevSAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
@@ -1924,7 +1922,8 @@
 			}
 		}
 
-		refAbiDumpFile := getRefAbiDumpFile(ctx, version, fileName)
+		currVersion := currRefAbiDumpVersion(ctx, isVndk)
+		refAbiDumpFile := getRefAbiDumpFile(ctx, currVersion, fileName)
 		if refAbiDumpFile != nil {
 			library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
 				refAbiDumpFile, fileName,
diff --git a/java/java.go b/java/java.go
index 718e1fe..ad46e98 100644
--- a/java/java.go
+++ b/java/java.go
@@ -25,6 +25,7 @@
 
 	"android/soong/bazel"
 	"android/soong/bazel/cquery"
+	"android/soong/remoteexec"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -59,6 +60,8 @@
 	ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
 	ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
 	ctx.RegisterModuleType("dex_import", DexImportFactory)
+	ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
+	ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
 
 	// This mutator registers dependencies on dex2oat for modules that should be
 	// dexpreopted. This is done late when the final variants have been
@@ -1529,6 +1532,182 @@
 	return module
 }
 
+type JavaApiContribution struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties struct {
+		// name of the API surface
+		Api_surface *string
+
+		// relative path to the API signature text file
+		Api_file *string `android:"path"`
+	}
+}
+
+func ApiContributionFactory() android.Module {
+	module := &JavaApiContribution{}
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	return module
+}
+
+type JavaApiImportInfo struct {
+	ApiFile android.Path
+}
+
+var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
+
+func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	apiFile := android.PathForModuleSrc(ctx, String(ap.properties.Api_file))
+	ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
+		ApiFile: apiFile,
+	})
+}
+
+type ApiLibrary struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties JavaApiLibraryProperties
+
+	stubsSrcJar android.WritablePath
+	stubsJar    android.WritablePath
+}
+
+type JavaApiLibraryProperties struct {
+	// name of the API surface
+	Api_surface *string
+
+	// list of API provider modules that consists this API surface
+	Api_providers []string
+
+	// List of flags to be passed to the javac compiler to generate jar file
+	Javacflags []string
+}
+
+func ApiLibraryFactory() android.Module {
+	module := &ApiLibrary{}
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	return module
+}
+
+func (al *ApiLibrary) ApiSurface() *string {
+	return al.properties.Api_surface
+}
+
+func (al *ApiLibrary) StubsJar() android.Path {
+	return al.stubsJar
+}
+
+func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
+	srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand {
+	rule.Command().Text("rm -rf").Flag(homeDir.String())
+	rule.Command().Text("mkdir -p").Flag(homeDir.String())
+
+	cmd := rule.Command()
+	cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
+
+	if metalavaUseRbe(ctx) {
+		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
+		execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+		labels := map[string]string{"type": "tool", "name": "metalava"}
+
+		pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
+		rule.Rewrapper(&remoteexec.REParams{
+			Labels:          labels,
+			ExecStrategy:    execStrategy,
+			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+			Platform:        map[string]string{remoteexec.PoolKey: pool},
+		})
+	}
+
+	cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
+		Flag(config.JavacVmFlags).
+		Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
+		FlagWithArg("-encoding ", "UTF-8").
+		FlagWithInputList("--source-files ", srcs, " ")
+
+	cmd.Flag("--no-banner").
+		Flag("--color").
+		Flag("--quiet").
+		Flag("--format=v2").
+		FlagWithArg("--repeat-errors-max ", "10").
+		FlagWithArg("--hide ", "UnresolvedImport").
+		FlagWithArg("--hide ", "InvalidNullabilityOverride").
+		FlagWithArg("--hide ", "ChangedDefault")
+
+	return cmd
+}
+
+func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
+	if stubsDir.Valid() {
+		cmd.FlagWithArg("--stubs ", stubsDir.String())
+	}
+}
+
+var javaApiProviderTag = dependencyTag{name: "java-api-provider"}
+
+func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	apiProviders := al.properties.Api_providers
+	for _, apiProviderName := range apiProviders {
+		ctx.AddDependency(ctx.Module(), javaApiProviderTag, apiProviderName)
+	}
+}
+
+func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+	rule := android.NewRuleBuilder(pctx, ctx)
+
+	rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
+		android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
+		SandboxInputs()
+
+	var stubsDir android.OptionalPath
+	stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
+	rule.Command().Text("rm -rf").Text(stubsDir.String())
+	rule.Command().Text("mkdir -p").Text(stubsDir.String())
+
+	homeDir := android.PathForModuleOut(ctx, "metalava", "home")
+
+	apiProviders := al.properties.Api_providers
+	srcFiles := make([]android.Path, len(apiProviders))
+	for i, apiProviderName := range apiProviders {
+		apiProvider := ctx.GetDirectDepWithTag(apiProviderName, javaApiProviderTag)
+		if apiProvider == nil {
+			panic(fmt.Errorf("Java API provider module %s not found, called from %s", apiProviderName, al.Name()))
+		}
+		provider := ctx.OtherModuleProvider(apiProvider, JavaApiImportProvider).(JavaApiImportInfo)
+		srcFiles[i] = android.PathForModuleSrc(ctx, provider.ApiFile.String())
+	}
+
+	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
+
+	al.stubsFlags(ctx, cmd, stubsDir)
+
+	al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
+	rule.Command().
+		BuiltTool("soong_zip").
+		Flag("-write_if_changed").
+		Flag("-jar").
+		FlagWithOutput("-o ", al.stubsSrcJar).
+		FlagWithArg("-C ", stubsDir.String()).
+		FlagWithArg("-D ", stubsDir.String())
+
+	rule.Build("metalava", "metalava merged")
+
+	al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), "android.jar")
+
+	var flags javaBuilderFlags
+	flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
+
+	TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{},
+		android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+}
+
 //
 // Java prebuilts
 //
diff --git a/java/java_test.go b/java/java_test.go
index f06b520..3f8cd8e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1806,3 +1806,108 @@
 			srcs: ["foo.java"],
 		}`)
 }
+
+func TestJavaApiLibraryAndProviderLink(t *testing.T) {
+	provider_bp_a := `
+	java_api_contribution {
+		name: "foo1",
+		api_file: "foo1.txt",
+	}
+	`
+	provider_bp_b := `java_api_contribution {
+		name: "foo2",
+		api_file: "foo2.txt",
+	}
+	`
+	ctx, _ := testJavaWithFS(t, `
+		java_api_library {
+			name: "bar1",
+			api_surface: "public",
+			api_providers: ["foo1"],
+		}
+
+		java_api_library {
+			name: "bar2",
+			api_surface: "system",
+			api_providers: ["foo1", "foo2"],
+		}
+		`,
+		map[string][]byte{
+			"a/Android.bp": []byte(provider_bp_a),
+			"b/Android.bp": []byte(provider_bp_b),
+		})
+
+	testcases := []struct {
+		moduleName         string
+		sourceTextFileDirs []string
+	}{
+		{
+			moduleName:         "bar1",
+			sourceTextFileDirs: []string{"a/foo1.txt"},
+		},
+		{
+			moduleName:         "bar2",
+			sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"},
+		},
+	}
+	for _, c := range testcases {
+		m := ctx.ModuleForTests(c.moduleName, "android_common")
+		manifest := m.Output("metalava.sbox.textproto")
+		sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+		manifestCommand := sboxProto.Commands[0].GetCommand()
+		sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
+		android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
+	}
+}
+
+func TestJavaApiLibraryJarGeneration(t *testing.T) {
+	provider_bp_a := `
+	java_api_contribution {
+		name: "foo1",
+		api_file: "foo1.txt",
+	}
+	`
+	provider_bp_b := `java_api_contribution {
+		name: "foo2",
+		api_file: "foo2.txt",
+	}
+	`
+	ctx, _ := testJavaWithFS(t, `
+		java_api_library {
+			name: "bar1",
+			api_surface: "public",
+			api_providers: ["foo1"],
+		}
+
+		java_api_library {
+			name: "bar2",
+			api_surface: "system",
+			api_providers: ["foo1", "foo2"],
+		}
+		`,
+		map[string][]byte{
+			"a/Android.bp": []byte(provider_bp_a),
+			"b/Android.bp": []byte(provider_bp_b),
+		})
+
+	testcases := []struct {
+		moduleName    string
+		outputJarName string
+	}{
+		{
+			moduleName:    "bar1",
+			outputJarName: "bar1/android.jar",
+		},
+		{
+			moduleName:    "bar2",
+			outputJarName: "bar2/android.jar",
+		},
+	}
+	for _, c := range testcases {
+		m := ctx.ModuleForTests(c.moduleName, "android_common")
+		outputs := fmt.Sprint(m.AllOutputs())
+		if !strings.Contains(outputs, c.outputJarName) {
+			t.Errorf("Module output does not contain expected jar %s", c.outputJarName)
+		}
+	}
+}
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 7a5da5c..1a1eaf2 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -22,101 +22,34 @@
 var legacyCorePlatformApiModules = []string{
 	"AAECarSystemUI",
 	"AAECarSystemUI-tests",
-	"ahat-test-dump",
-	"android.car",
-	"android.test.mock",
-	"android.test.mock.impl",
-	"AoapTestDeviceApp",
-	"AoapTestHostApp",
 	"ArcSettings",
-	"art_cts_jvmti_test_library",
-	"art-gtest-jars-MyClassNatives",
-	"BackupFrameworksServicesRoboTests",
-	"BandwidthEnforcementTest",
-	"BlockedNumberProvider",
-	"BluetoothInstrumentationTests",
-	"BluetoothMidiLib",
-	"BluetoothMidiService",
 	"BTTestApp",
 	"CapCtrlInterface",
-	"CarService",
-	"CarServiceTest",
-	"car-service-test-static-lib",
-	"CertInstaller",
 	"com.qti.location.sdk",
 	"com.qti.media.secureprocessor",
-	"ConnectivityManagerTest",
-	"ContactsProvider",
-	"CorePerfTests",
-	"core-tests-support",
-	"cronet_impl_common_java",
-	"cronet_impl_native_java",
-	"cronet_impl_platform_java",
-	"CtsAppExitTestCases",
-	"CtsContentTestCases",
-	"CtsLibcoreWycheproofBCTestCases",
-	"CtsNetTestCases",
-	"CtsNetTestCasesLatestSdk",
-	"CtsSecurityTestCases",
-	"CtsSuspendAppsTestCases",
-	"CtsUsageStatsTestCases",
 	"DeviceInfo",
-	"DiagnosticTools",
 	"DocumentsUIGoogleTests",
-	"DocumentsUIPerfTests",
-	"DocumentsUITests",
 	"DocumentsUIUnitTests",
-	"DownloadProvider",
-	"DownloadProviderTests",
-	"DownloadProviderUi",
-	"ds-car-docs",
-	"DynamicSystemInstallationService",
-	"EmergencyInfo-lib",
-	"ExternalStorageProvider",
 	"face-V1-0-javalib",
 	"FloralClocks",
 	"framework-jobscheduler",
 	"framework-minus-apex",
 	"framework-minus-apex-intdefs",
-	"FrameworkOverlayG6QU3",
 	"FrameworksCoreTests",
-	"FrameworksIkeTests",
-	"FrameworksMockingServicesTests",
-	"FrameworksNetCommonTests",
-	"FrameworksNetTests",
-	"FrameworksServicesRoboTests",
-	"FrameworksServicesTests",
-	"FrameworksUtilTests",
 	"GtsIncrementalInstallTestCases",
 	"GtsIncrementalInstallTriggerApp",
 	"GtsInstallerV2TestCases",
 	"HelloOslo",
-	"hid",
-	"hidl_test_java_java",
 	"imssettings",
 	"izat.lib.glue",
-	"KeyChain",
-	"LocalTransport",
-	"lockagent",
-	"mediaframeworktest",
 	"mediatek-ims-base",
-	"MmsService",
 	"ModemTestMode",
 	"MtkCapCtrl",
-	"MtpService",
-	"MultiDisplayProvider",
 	"my.tests.snapdragonsdktest",
 	"NetworkSetting",
-	"NetworkStackIntegrationTestsLib",
-	"NetworkStackNextIntegrationTests",
-	"NetworkStackNextTests",
-	"NetworkStackTests",
-	"NetworkStackTestsLib",
 	"online-gcm-ref-docs",
 	"online-gts-docs",
 	"PerformanceMode",
-	"platform_library-docs",
-	"PrintSpooler",
 	"pxp-monitor",
 	"QColor",
 	"qcom.fmradio",
@@ -124,21 +57,11 @@
 	"Qmmi",
 	"QPerformance",
 	"remotesimlockmanagerlibrary",
-	"RollbackTest",
 	"sam",
 	"saminterfacelibrary",
 	"sammanagerlibrary",
-	"service-blobstore",
-	"service-connectivity-pre-jarjar",
-	"service-jobscheduler",
 	"services",
-	"services.accessibility",
-	"services.backup",
 	"services.core.unboosted",
-	"services.devicepolicy",
-	"services.print",
-	"services.usage",
-	"services.usb",
 	"Settings-core",
 	"SettingsGoogle",
 	"SettingsGoogleOverlayCoral",
@@ -156,33 +79,16 @@
 	"SettingsOverlayG025M",
 	"SettingsOverlayG025N",
 	"SettingsOverlayG5NZ6",
-	"SettingsProvider",
-	"SettingsProviderTest",
 	"SettingsRoboTests",
-	"Shell",
-	"ShellTests",
 	"SimContact",
 	"SimContacts",
 	"SimSettings",
-	"sl4a.Common",
-	"StatementService",
 	"tcmiface",
-	"Telecom",
-	"TelecomUnitTests",
 	"telephony-common",
-	"TelephonyProviderTests",
 	"TeleService",
-	"testables",
-	"TetheringTests",
 	"TMobilePlanProvider",
-	"TvProvider",
-	"uiautomator-stubs-docs",
 	"uimgbamanagerlibrary",
-	"UsbHostExternalManagementTestApp",
-	"UserDictionaryProvider",
 	"UxPerformance",
-	"WallpaperBackup",
-	"WallpaperBackupAgentTests",
 	"WfdCommon",
 }