diff options
| -rw-r--r-- | cc/library.go | 37 | ||||
| -rw-r--r-- | java/java.go | 179 | ||||
| -rw-r--r-- | java/java_test.go | 105 | ||||
| -rw-r--r-- | java/legacy_core_platform_api_usage.go | 94 |
4 files changed, 302 insertions, 113 deletions
diff --git a/cc/library.go b/cc/library.go index 897f3c7fb..b63993004 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1875,25 +1875,21 @@ func prevDumpRefVersion(ctx ModuleContext) int { } } +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 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec 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 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec } } - 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 718e1fef6..ad46e9880 100644 --- a/java/java.go +++ b/java/java.go @@ -25,6 +25,7 @@ import ( "android/soong/bazel" "android/soong/bazel/cquery" + "android/soong/remoteexec" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -59,6 +60,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { 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 @@ func BinaryHostFactory() android.Module { 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 f06b520d5..3f8cd8e90 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1806,3 +1806,108 @@ func TestDeviceBinaryWrapperGeneration(t *testing.T) { 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 7a5da5c98..1a1eaf252 100644 --- a/java/legacy_core_platform_api_usage.go +++ b/java/legacy_core_platform_api_usage.go @@ -22,101 +22,34 @@ import ( 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 @@ var legacyCorePlatformApiModules = []string{ "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 @@ var legacyCorePlatformApiModules = []string{ "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", } |