diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-02-02 07:41:54 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-02-02 07:41:54 +0000 |
commit | 2f493d90fb64e35bab7d413296cff7e1737ecf18 (patch) | |
tree | 1c68430d0c671ffebe28515523da9a1617c3b3ab | |
parent | 4d13457eb361c0f4a24d616d815fd8e70487d1f8 (diff) | |
parent | c895c7b3ee4f1c9f11201370476b7c4442c114a9 (diff) | |
download | soong-2f493d90fb64e35bab7d413296cff7e1737ecf18.tar.gz |
Snap for 9554547 from c895c7b3ee4f1c9f11201370476b7c4442c114a9 to mainline-networking-releaseaml_net_331610000
Change-Id: Ie6fd687fbe91d1a12c5d21b911a051a2be4155d9
-rw-r--r-- | android/paths.go | 15 | ||||
-rw-r--r-- | apex/apex.go | 18 | ||||
-rwxr-xr-x | java/app.go | 9 | ||||
-rw-r--r-- | java/app_test.go | 72 | ||||
-rw-r--r-- | java/droiddoc.go | 2 | ||||
-rw-r--r-- | java/java.go | 235 | ||||
-rw-r--r-- | java/java_test.go | 106 |
7 files changed, 421 insertions, 36 deletions
diff --git a/android/paths.go b/android/paths.go index c3ef7548a..6163762a5 100644 --- a/android/paths.go +++ b/android/paths.go @@ -1137,6 +1137,21 @@ func PathForSource(ctx PathContext, pathComponents ...string) SourcePath { return path } +// MaybeExistentPathForSource joins the provided path components and validates that the result +// neither escapes the source dir nor is in the out dir. +// It does not validate whether the path exists. +func MaybeExistentPathForSource(ctx PathContext, pathComponents ...string) SourcePath { + path, err := pathForSource(ctx, pathComponents...) + if err != nil { + reportPathError(ctx, err) + } + + if pathtools.IsGlob(path.String()) { + ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String()) + } + return path +} + // ExistentPathForSource returns an OptionalPath with the SourcePath, rooted from SrcDir, *not* // rooted from the module's local source directory, if the path exists, or an empty OptionalPath if // it doesn't exist. Dependencies are added so that the ninja file will be regenerated if the state diff --git a/apex/apex.go b/apex/apex.go index d5e2a3db6..132b2b29f 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -120,10 +120,6 @@ type apexBundleProperties struct { // List of filesystem images that are embedded inside this APEX bundle. Filesystems []string - // The minimum SDK version that this APEX must support at minimum. This is usually set to - // the SDK version that the APEX was first introduced. - Min_sdk_version *string - // Whether this APEX is considered updatable or not. When set to true, this will enforce // additional rules for making sure that the APEX is truly updatable. To be updatable, // min_sdk_version should be set as well. This will also disable the size optimizations like @@ -386,6 +382,10 @@ type overridableProperties struct { // conditions, e.g., target device needs to support APEX compression, are also fulfilled. // Default: false. Compressible *bool + + // The minimum SDK version that this APEX must support at minimum. This is usually set to + // the SDK version that the APEX was first introduced. + Min_sdk_version *string } type apexBundle struct { @@ -2550,14 +2550,14 @@ func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string { // min_sdk_version value is lower than the one to override with. overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride() overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue) - originalMinApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version)) - isMinSdkSet := a.properties.Min_sdk_version != nil + originalMinApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.overridableProperties.Min_sdk_version)) + isMinSdkSet := a.overridableProperties.Min_sdk_version != nil isOverrideValueHigher := overrideApiLevel.CompareTo(originalMinApiLevel) > 0 if overrideMinSdkValue != "" && isMinSdkSet && isOverrideValueHigher { return overrideMinSdkValue } - return proptools.String(a.properties.Min_sdk_version) + return proptools.String(a.overridableProperties.Min_sdk_version) } // Returns apex's min_sdk_version SdkSpec, honoring overrides @@ -3255,8 +3255,8 @@ func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) { // TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but // given it's coming via config, we probably don't want to put it in here. var minSdkVersion *string - if a.properties.Min_sdk_version != nil { - minSdkVersion = a.properties.Min_sdk_version + if a.overridableProperties.Min_sdk_version != nil { + minSdkVersion = a.overridableProperties.Min_sdk_version } var keyLabelAttribute bazel.LabelAttribute diff --git a/java/app.go b/java/app.go index 04db0d4d8..4c7f0172e 100755 --- a/java/app.go +++ b/java/app.go @@ -315,10 +315,6 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { } } - if Bool(a.appProperties.Enforce_default_target_sdk_version) { - a.SetEnforceDefaultTargetSdkVersion(true) - } - a.checkPlatformAPI(ctx) a.checkSdkVersions(ctx) } @@ -620,6 +616,11 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath) } + // For apps targeting latest target_sdk_version + if Bool(a.appProperties.Enforce_default_target_sdk_version) { + a.SetEnforceDefaultTargetSdkVersion(true) + } + // Process all building blocks, from AAPT to certificates. a.aaptBuildActions(ctx) diff --git a/java/app_test.go b/java/app_test.go index 83b47bdc9..53676be37 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -3166,7 +3166,7 @@ func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) { updatable: true, }, { - name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion", + name: "Enforce Target SDK Version: Android.bp has current targetSdkVersion", enforceDefaultTargetSdkVersion: true, platform_sdk_final: false, targetSdkVersionInBp: "current", @@ -3222,6 +3222,76 @@ func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) { } } +func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) { + platform_sdk_codename := "Tiramisu" + platform_sdk_version := 33 + testCases := []struct { + name string + enforceDefaultTargetSdkVersion bool + expectedError string + platform_sdk_final bool + targetSdkVersionInBp string + targetSdkVersionExpected string + }{ + { + name: "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion", + enforceDefaultTargetSdkVersion: false, + targetSdkVersionInBp: "29", + targetSdkVersionExpected: "29", + }, + { + name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion", + enforceDefaultTargetSdkVersion: true, + platform_sdk_final: true, + targetSdkVersionInBp: "current", + targetSdkVersionExpected: "33", + }, + { + name: "Enforce Target SDK Version: Android.bp has current targetSdkVersion", + enforceDefaultTargetSdkVersion: true, + platform_sdk_final: false, + targetSdkVersionInBp: "current", + targetSdkVersionExpected: "10000", + }, + } + for _, testCase := range testCases { + errExpected := testCase.expectedError != "" + bp := fmt.Sprintf(` + android_test { + name: "foo", + enforce_default_target_sdk_version: %t, + min_sdk_version: "29", + target_sdk_version: "%v", + } + `, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp) + + fixture := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAllowMissingDependencies, + android.PrepareForTestWithAndroidMk, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + // explicitly set following platform variables to make the test deterministic + variables.Platform_sdk_final = &testCase.platform_sdk_final + variables.Platform_sdk_version = &platform_sdk_version + variables.Platform_sdk_codename = &platform_sdk_codename + variables.Unbundled_build_apps = []string{"sampleModule"} + }), + ) + + errorHandler := android.FixtureExpectsNoErrors + if errExpected { + errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError) + } + result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp) + + if !errExpected { + foo := result.ModuleForTests("foo", "android_common") + manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + } + } +} + func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) { result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, diff --git a/java/droiddoc.go b/java/droiddoc.go index c1182652f..0c8908e24 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -591,7 +591,7 @@ func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.Rule // Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9 // sources, droiddoc will get sources produced by metalava which will have already stripped out the // 1.9 language features. - cmd.FlagWithArg("-source ", "1.8"). + cmd.FlagWithArg("-source ", getStubsJavaVersion().String()). Flag("-J-Xmx1600m"). Flag("-J-XX:-OmitStackTraceInFastThrow"). Flag("-XDignore.symbol.file"). diff --git a/java/java.go b/java/java.go index e46712349..5a3a2e0a3 100644 --- a/java/java.go +++ b/java/java.go @@ -24,6 +24,7 @@ import ( "strings" "android/soong/bazel" + "android/soong/remoteexec" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -58,6 +59,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 @@ -500,6 +503,11 @@ func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext an } } +// Java version for stubs generation +func getStubsJavaVersion() javaVersion { + return JAVA_VERSION_8 +} + type javaVersion int const ( @@ -1444,6 +1452,193 @@ 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 Java API contribution modules that consists this API surface + // This is a list of Soong modules + Api_contributions []string + + // list of api.txt files relative to this directory that contribute to the + // API surface. + // This is a list of relative paths + Api_files []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 javaApiContributionTag = dependencyTag{name: "java-api-contribution"} + +func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { + apiContributions := al.properties.Api_contributions + for _, apiContributionName := range apiContributions { + ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName) + } +} + +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") + + var srcFiles []android.Path + ctx.VisitDirectDepsWithTag(javaApiContributionTag, func(dep android.Module) { + provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo) + srcFiles = append(srcFiles, android.PathForSource(ctx, provider.ApiFile.String())) + }) + + // Add the api_files inputs + for _, api := range al.properties.Api_files { + // Use MaybeExistentPathForSource since the api file might not exist during analysis. + // This will be provided by the orchestrator in the combined execution. + srcFiles = append(srcFiles, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), api)) + } + + 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.javaVersion = getStubsJavaVersion() + flags.javacFlags = strings.Join(al.properties.Javacflags, " ") + + TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{}, + android.Paths{al.stubsSrcJar}, flags, android.Paths{}) + + ctx.Phony(ctx.ModuleName(), al.stubsJar) +} + // // Java prebuilts // @@ -2017,9 +2212,7 @@ func DexImportFactory() android.Module { return module } -// // Defaults -// type Defaults struct { android.ModuleBase android.DefaultsModuleBase @@ -2034,29 +2227,29 @@ type Defaults struct { // // Example: // -// java_defaults { -// name: "example_defaults", -// srcs: ["common/**/*.java"], -// javacflags: ["-Xlint:all"], -// aaptflags: ["--auto-add-overlay"], -// } +// java_defaults { +// name: "example_defaults", +// srcs: ["common/**/*.java"], +// javacflags: ["-Xlint:all"], +// aaptflags: ["--auto-add-overlay"], +// } // -// java_library { -// name: "example", -// defaults: ["example_defaults"], -// srcs: ["example/**/*.java"], -// } +// java_library { +// name: "example", +// defaults: ["example_defaults"], +// srcs: ["example/**/*.java"], +// } // // is functionally identical to: // -// java_library { -// name: "example", -// srcs: [ -// "common/**/*.java", -// "example/**/*.java", -// ], -// javacflags: ["-Xlint:all"], -// } +// java_library { +// name: "example", +// srcs: [ +// "common/**/*.java", +// "example/**/*.java", +// ], +// javacflags: ["-Xlint:all"], +// } func DefaultsFactory() android.Module { module := &Defaults{} diff --git a/java/java_test.go b/java/java_test.go index af889ccd4..2378a6cbe 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1667,3 +1667,109 @@ func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) { }) } } + +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_contributions: ["foo1"], + } + + java_api_library { + name: "bar2", + api_surface: "system", + api_contributions: ["foo1", "foo2"], + api_files: ["api1/current.txt", "api2/current.txt"] + } + `, + 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", "api1/current.txt", "api2/current.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_contributions: ["foo1"], + } + + java_api_library { + name: "bar2", + api_surface: "system", + api_contributions: ["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) + } + } +} |