Loading apex/apex.go +1 −23 Original line number Diff line number Diff line Loading @@ -68,8 +68,6 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { ctx.Transition("apex", &apexTransitionMutator{}) ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel() ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel() // Register after apex_info mutator so that it can use ApexVariationName ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel() } type apexBundleProperties struct { Loading Loading @@ -1115,26 +1113,6 @@ func apexInfoMutator(mctx android.TopDownMutatorContext) { enforceAppUpdatability(mctx) } // apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module // This check is enforced for updatable modules func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) { if !mctx.Module().Enabled(mctx) { return } if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting(mctx) { apex.WalkPayloadDeps(mctx, func(mctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { if externalDep { return false } if lintable, ok := to.(java.LintDepSetsIntf); ok { lintable.SetStrictUpdatabilityLinting(true) } // visit transitive deps return true }) } } // enforceAppUpdatability propagates updatable=true to apps of updatable apexes func enforceAppUpdatability(mctx android.TopDownMutatorContext) { if !mctx.Module().Enabled(mctx) { Loading Loading @@ -1197,7 +1175,7 @@ var ( } ) func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.TopDownMutatorContext) bool { func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.ModuleContext) bool { // The allowlist contains the base apex name, so use that instead of the ApexVariationName return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist) } Loading apex/apex_test.go +70 −44 Original line number Diff line number Diff line Loading @@ -9697,39 +9697,45 @@ func TestApexStrictUpdtabilityLint(t *testing.T) { apexUpdatable bool javaStrictUpdtabilityLint bool lintFileExists bool disallowedFlagExpected bool disallowedFlagExpectedOnApex bool disallowedFlagExpectedOnJavalib bool }{ { testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd", apexUpdatable: true, javaStrictUpdtabilityLint: true, lintFileExists: false, disallowedFlagExpected: false, disallowedFlagExpectedOnApex: false, disallowedFlagExpectedOnJavalib: false, }, { testCaseName: "non-updatable apex respects strict_updatability of javalib", apexUpdatable: false, javaStrictUpdtabilityLint: false, lintFileExists: true, disallowedFlagExpected: false, disallowedFlagExpectedOnApex: false, disallowedFlagExpectedOnJavalib: false, }, { testCaseName: "non-updatable apex respects strict updatability of javalib", apexUpdatable: false, javaStrictUpdtabilityLint: true, lintFileExists: true, disallowedFlagExpected: true, disallowedFlagExpectedOnApex: false, disallowedFlagExpectedOnJavalib: true, }, { testCaseName: "updatable apex sets strict updatability of javalib to true", testCaseName: "updatable apex checks strict updatability of javalib", apexUpdatable: true, javaStrictUpdtabilityLint: false, // will be set to true by mutator javaStrictUpdtabilityLint: false, lintFileExists: true, disallowedFlagExpected: true, disallowedFlagExpectedOnApex: true, disallowedFlagExpectedOnJavalib: false, }, } for _, testCase := range testCases { t.Run(testCase.testCaseName, func(t *testing.T) { fixtures := []android.FixturePreparer{} baselineProperty := "" if testCase.lintFileExists { Loading @@ -9739,13 +9745,32 @@ func TestApexStrictUpdtabilityLint(t *testing.T) { bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty) result := testApex(t, bp, fixtures...) myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") if disallowedFlagActual != testCase.disallowedFlagExpected { t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) checkModule := func(m android.TestingBuildParams, name string, expectStrictUpdatability bool) { if expectStrictUpdatability { if m.Rule == nil { t.Errorf("expected strict updatability check rule on %s", name) } else { android.AssertStringDoesContain(t, fmt.Sprintf("strict updatability check rule for %s", name), m.RuleParams.Command, "--disallowed_issues NewApi") android.AssertStringListContains(t, fmt.Sprintf("strict updatability check baselines for %s", name), m.Inputs.Strings(), "lint-baseline.xml") } } else { if m.Rule != nil { t.Errorf("expected no strict updatability check rule on %s", name) } } } myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") apex := result.ModuleForTests("myapex", "android_common_myapex") apexStrictUpdatabilityCheck := apex.MaybeOutput("lint_strict_updatability_check.stamp") javalibStrictUpdatabilityCheck := myjavalib.MaybeOutput("lint_strict_updatability_check.stamp") checkModule(apexStrictUpdatabilityCheck, "myapex", testCase.disallowedFlagExpectedOnApex) checkModule(javalibStrictUpdatabilityCheck, "myjavalib", testCase.disallowedFlagExpectedOnJavalib) }) } } Loading Loading @@ -9787,11 +9812,12 @@ func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) { } result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture()) myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") { t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command) } apex := result.ModuleForTests("myapex", "android_common_myapex") apexStrictUpdatabilityCheck := apex.Output("lint_strict_updatability_check.stamp") android.AssertStringDoesContain(t, "strict updatability check rule for myapex", apexStrictUpdatabilityCheck.RuleParams.Command, "--disallowed_issues NewApi") android.AssertStringListContains(t, "strict updatability check baselines for myapex", apexStrictUpdatabilityCheck.Inputs.Strings(), "lint-baseline.xml") } func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) { Loading apex/builder.go +12 −1 Original line number Diff line number Diff line Loading @@ -1164,7 +1164,18 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) { } } a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build()) depSets := depSetsBuilder.Build() var validations android.Paths if a.checkStrictUpdatabilityLinting(ctx) { baselines := depSets.Baseline.ToList() if len(baselines) > 0 { outputFile := java.VerifyStrictUpdatabilityChecks(ctx, baselines) validations = append(validations, outputFile) } } a.lintReports = java.BuildModuleLintReportZips(ctx, depSets, validations) } func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath { Loading java/java.go +0 −14 Original line number Diff line number Diff line Loading @@ -2612,13 +2612,6 @@ func (a *Import) JacocoReportClassesFile() android.Path { return nil } func (j *Import) getStrictUpdatabilityLinting() bool { return false } func (j *Import) setStrictUpdatabilityLinting(bool) { } func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...) ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs.GetOrDefault(ctx, nil)...) Loading Loading @@ -3098,13 +3091,6 @@ func (j *DexImport) IsInstallable() bool { return true } func (j *DexImport) getStrictUpdatabilityLinting() bool { return false } func (j *DexImport) setStrictUpdatabilityLinting(bool) { } func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { if len(j.properties.Jars) != 1 { ctx.PropertyErrorf("jars", "exactly one jar must be provided") Loading java/lint.go +80 −82 Original line number Diff line number Diff line Loading @@ -100,18 +100,12 @@ type linter struct { buildModuleReportZip bool } type LintDepSetsIntf interface { // Methods used to propagate strict_updatability_linting values. GetStrictUpdatabilityLinting() bool SetStrictUpdatabilityLinting(bool) } type LintDepSets struct { HTML, Text, XML *android.DepSet[android.Path] HTML, Text, XML, Baseline *android.DepSet[android.Path] } type LintDepSetsBuilder struct { HTML, Text, XML *android.DepSetBuilder[android.Path] HTML, Text, XML, Baseline *android.DepSetBuilder[android.Path] } func NewLintDepSetBuilder() LintDepSetsBuilder { Loading @@ -119,13 +113,17 @@ func NewLintDepSetBuilder() LintDepSetsBuilder { HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER), Text: android.NewDepSetBuilder[android.Path](android.POSTORDER), XML: android.NewDepSetBuilder[android.Path](android.POSTORDER), Baseline: android.NewDepSetBuilder[android.Path](android.POSTORDER), } } func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder { func (l LintDepSetsBuilder) Direct(html, text, xml android.Path, baseline android.OptionalPath) LintDepSetsBuilder { l.HTML.Direct(html) l.Text.Direct(text) l.XML.Direct(xml) if baseline.Valid() { l.Baseline.Direct(baseline.Path()) } return l } Loading @@ -139,6 +137,9 @@ func (l LintDepSetsBuilder) Transitive(info *LintInfo) LintDepSetsBuilder { if info.TransitiveXML != nil { l.XML.Transitive(info.TransitiveXML) } if info.TransitiveBaseline != nil { l.Baseline.Transitive(info.TransitiveBaseline) } return l } Loading @@ -147,6 +148,7 @@ func (l LintDepSetsBuilder) Build() LintDepSets { HTML: l.HTML.Build(), Text: l.Text.Build(), XML: l.XML.Build(), Baseline: l.Baseline.Build(), } } Loading Loading @@ -194,16 +196,6 @@ var allLintDatabasefiles = map[android.SdkKind]lintDatabaseFiles{ }, } func (l *linter) GetStrictUpdatabilityLinting() bool { return BoolDefault(l.properties.Lint.Strict_updatability_linting, false) } func (l *linter) SetStrictUpdatabilityLinting(strictLinting bool) { l.properties.Lint.Strict_updatability_linting = &strictLinting } var _ LintDepSetsIntf = (*linter)(nil) var LintProvider = blueprint.NewProvider[*LintInfo]() type LintInfo struct { Loading @@ -215,6 +207,7 @@ type LintInfo struct { TransitiveHTML *android.DepSet[android.Path] TransitiveText *android.DepSet[android.Path] TransitiveXML *android.DepSet[android.Path] TransitiveBaseline *android.DepSet[android.Path] } func (l *linter) enabled() bool { Loading Loading @@ -250,7 +243,9 @@ func lintRBEExecStrategy(ctx android.ModuleContext) string { return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy) } func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path) lintPaths { func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path, baselines android.Paths) lintPaths { projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml") // Lint looks for a lint.xml file next to the project.xml file, give it one. configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml") Loading Loading @@ -313,12 +308,10 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks) cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks) if l.GetStrictUpdatabilityLinting() { if Bool(l.properties.Lint.Strict_updatability_linting) && len(baselines) > 0 { // Verify the module does not baseline issues that endanger safe updatability. if l.properties.Lint.Baseline_filename != nil { cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks) } strictUpdatabilityChecksOutputFile := VerifyStrictUpdatabilityChecks(ctx, baselines) cmd.Validation(strictUpdatabilityChecksOutputFile) } return lintPaths{ Loading @@ -330,6 +323,22 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru } func VerifyStrictUpdatabilityChecks(ctx android.ModuleContext, baselines android.Paths) android.Path { rule := android.NewRuleBuilder(pctx, ctx) baselineRspFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check_baselines.rsp") outputFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check.stamp") rule.Command().Text("rm -f").Output(outputFile) rule.Command(). BuiltTool("lint_strict_updatability_checks"). FlagWithArg("--name ", ctx.ModuleName()). FlagWithRspFileInputList("--baselines ", baselineRspFile, baselines). FlagForEachArg("--disallowed_issues ", updatabilityChecks) rule.Command().Text("touch").Output(outputFile) rule.Build("lint_strict_updatability_checks", "lint strict updatability checks") return outputFile } // generateManifest adds a command to the rule to write a simple manifest that contains the // minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest. func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath { Loading Loading @@ -399,6 +408,26 @@ func (l *linter) lint(ctx android.ModuleContext) { l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx, "prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar")) var baseline android.OptionalPath if l.properties.Lint.Baseline_filename != nil { baseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) } html := android.PathForModuleOut(ctx, "lint", "lint-report.html") text := android.PathForModuleOut(ctx, "lint", "lint-report.txt") xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml") referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml") depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline) ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) { if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok { depSetsBuilder.Transitive(info) } }) depSets := depSetsBuilder.Build() rule := android.NewRuleBuilder(pctx, ctx). Sbox(android.PathForModuleOut(ctx, "lint"), android.PathForModuleOut(ctx, "lint.sbox.textproto")). Loading @@ -425,22 +454,9 @@ func (l *linter) lint(ctx android.ModuleContext) { srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp") rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data) lintPaths := l.writeLintProjectXML(ctx, rule, srcsList) html := android.PathForModuleOut(ctx, "lint", "lint-report.html") text := android.PathForModuleOut(ctx, "lint", "lint-report.txt") xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml") referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml") depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml) ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) { if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok { depSetsBuilder.Transitive(info) } }) baselines := depSets.Baseline.ToList() depSets := depSetsBuilder.Build() lintPaths := l.writeLintProjectXML(ctx, rule, srcsList, baselines) rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) Loading Loading @@ -495,8 +511,8 @@ func (l *linter) lint(ctx android.ModuleContext) { cmd.FlagWithArg("--check ", checkOnly) } if l.properties.Lint.Baseline_filename != nil { cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) if baseline.Valid() { cmd.FlagWithInput("--baseline ", baseline.Path()) } cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline) Loading Loading @@ -529,10 +545,11 @@ func (l *linter) lint(ctx android.ModuleContext) { TransitiveHTML: depSets.HTML, TransitiveText: depSets.Text, TransitiveXML: depSets.XML, TransitiveBaseline: depSets.Baseline, }) if l.buildModuleReportZip { l.reports = BuildModuleLintReportZips(ctx, depSets) l.reports = BuildModuleLintReportZips(ctx, depSets, nil) } // Create a per-module phony target to run the lint check. Loading @@ -542,7 +559,7 @@ func (l *linter) lint(ctx android.ModuleContext) { ctx.SetOutputFiles(android.Paths{xml}, ".lint") } func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths { func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets, validations android.Paths) android.Paths { htmlList := android.SortedUniquePaths(depSets.HTML.ToList()) textList := android.SortedUniquePaths(depSets.Text.ToList()) xmlList := android.SortedUniquePaths(depSets.XML.ToList()) Loading @@ -552,13 +569,13 @@ func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) a } htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip") lintZip(ctx, htmlList, htmlZip) lintZip(ctx, htmlList, htmlZip, validations) textZip := android.PathForModuleOut(ctx, "lint-report-text.zip") lintZip(ctx, textList, textZip) lintZip(ctx, textList, textZip, validations) xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip") lintZip(ctx, xmlList, xmlZip) lintZip(ctx, xmlList, xmlZip, validations) return android.Paths{htmlZip, textZip, xmlZip} } Loading Loading @@ -668,7 +685,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { } } lintZip(ctx, paths, outputPath) lintZip(ctx, paths, outputPath, nil) } l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip") Loading Loading @@ -697,17 +714,9 @@ var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil) func init() { android.RegisterParallelSingletonType("lint", func() android.Singleton { return &lintSingleton{} }) registerLintBuildComponents(android.InitRegistrationContext) } func registerLintBuildComponents(ctx android.RegistrationContext) { ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.TopDown("enforce_strict_updatability_linting", enforceStrictUpdatabilityLintingMutator).Parallel() }) } func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) { func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath, validations android.Paths) { paths = android.SortedUniquePaths(android.CopyOfPaths(paths)) sort.Slice(paths, func(i, j int) bool { Loading @@ -719,19 +728,8 @@ func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputPath). FlagWithArg("-C ", android.PathForIntermediates(ctx).String()). FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths) FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths). Validations(validations) rule.Build(outputPath.Base(), outputPath.Base()) } // Enforce the strict updatability linting to all applicable transitive dependencies. func enforceStrictUpdatabilityLintingMutator(ctx android.TopDownMutatorContext) { m := ctx.Module() if d, ok := m.(LintDepSetsIntf); ok && d.GetStrictUpdatabilityLinting() { ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) { if a, ok := d.(LintDepSetsIntf); ok { a.SetStrictUpdatabilityLinting(true) } }) } } Loading
apex/apex.go +1 −23 Original line number Diff line number Diff line Loading @@ -68,8 +68,6 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { ctx.Transition("apex", &apexTransitionMutator{}) ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel() ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel() // Register after apex_info mutator so that it can use ApexVariationName ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel() } type apexBundleProperties struct { Loading Loading @@ -1115,26 +1113,6 @@ func apexInfoMutator(mctx android.TopDownMutatorContext) { enforceAppUpdatability(mctx) } // apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module // This check is enforced for updatable modules func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) { if !mctx.Module().Enabled(mctx) { return } if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting(mctx) { apex.WalkPayloadDeps(mctx, func(mctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { if externalDep { return false } if lintable, ok := to.(java.LintDepSetsIntf); ok { lintable.SetStrictUpdatabilityLinting(true) } // visit transitive deps return true }) } } // enforceAppUpdatability propagates updatable=true to apps of updatable apexes func enforceAppUpdatability(mctx android.TopDownMutatorContext) { if !mctx.Module().Enabled(mctx) { Loading Loading @@ -1197,7 +1175,7 @@ var ( } ) func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.TopDownMutatorContext) bool { func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.ModuleContext) bool { // The allowlist contains the base apex name, so use that instead of the ApexVariationName return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist) } Loading
apex/apex_test.go +70 −44 Original line number Diff line number Diff line Loading @@ -9697,39 +9697,45 @@ func TestApexStrictUpdtabilityLint(t *testing.T) { apexUpdatable bool javaStrictUpdtabilityLint bool lintFileExists bool disallowedFlagExpected bool disallowedFlagExpectedOnApex bool disallowedFlagExpectedOnJavalib bool }{ { testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd", apexUpdatable: true, javaStrictUpdtabilityLint: true, lintFileExists: false, disallowedFlagExpected: false, disallowedFlagExpectedOnApex: false, disallowedFlagExpectedOnJavalib: false, }, { testCaseName: "non-updatable apex respects strict_updatability of javalib", apexUpdatable: false, javaStrictUpdtabilityLint: false, lintFileExists: true, disallowedFlagExpected: false, disallowedFlagExpectedOnApex: false, disallowedFlagExpectedOnJavalib: false, }, { testCaseName: "non-updatable apex respects strict updatability of javalib", apexUpdatable: false, javaStrictUpdtabilityLint: true, lintFileExists: true, disallowedFlagExpected: true, disallowedFlagExpectedOnApex: false, disallowedFlagExpectedOnJavalib: true, }, { testCaseName: "updatable apex sets strict updatability of javalib to true", testCaseName: "updatable apex checks strict updatability of javalib", apexUpdatable: true, javaStrictUpdtabilityLint: false, // will be set to true by mutator javaStrictUpdtabilityLint: false, lintFileExists: true, disallowedFlagExpected: true, disallowedFlagExpectedOnApex: true, disallowedFlagExpectedOnJavalib: false, }, } for _, testCase := range testCases { t.Run(testCase.testCaseName, func(t *testing.T) { fixtures := []android.FixturePreparer{} baselineProperty := "" if testCase.lintFileExists { Loading @@ -9739,13 +9745,32 @@ func TestApexStrictUpdtabilityLint(t *testing.T) { bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty) result := testApex(t, bp, fixtures...) myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") if disallowedFlagActual != testCase.disallowedFlagExpected { t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) checkModule := func(m android.TestingBuildParams, name string, expectStrictUpdatability bool) { if expectStrictUpdatability { if m.Rule == nil { t.Errorf("expected strict updatability check rule on %s", name) } else { android.AssertStringDoesContain(t, fmt.Sprintf("strict updatability check rule for %s", name), m.RuleParams.Command, "--disallowed_issues NewApi") android.AssertStringListContains(t, fmt.Sprintf("strict updatability check baselines for %s", name), m.Inputs.Strings(), "lint-baseline.xml") } } else { if m.Rule != nil { t.Errorf("expected no strict updatability check rule on %s", name) } } } myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") apex := result.ModuleForTests("myapex", "android_common_myapex") apexStrictUpdatabilityCheck := apex.MaybeOutput("lint_strict_updatability_check.stamp") javalibStrictUpdatabilityCheck := myjavalib.MaybeOutput("lint_strict_updatability_check.stamp") checkModule(apexStrictUpdatabilityCheck, "myapex", testCase.disallowedFlagExpectedOnApex) checkModule(javalibStrictUpdatabilityCheck, "myjavalib", testCase.disallowedFlagExpectedOnJavalib) }) } } Loading Loading @@ -9787,11 +9812,12 @@ func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) { } result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture()) myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") { t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command) } apex := result.ModuleForTests("myapex", "android_common_myapex") apexStrictUpdatabilityCheck := apex.Output("lint_strict_updatability_check.stamp") android.AssertStringDoesContain(t, "strict updatability check rule for myapex", apexStrictUpdatabilityCheck.RuleParams.Command, "--disallowed_issues NewApi") android.AssertStringListContains(t, "strict updatability check baselines for myapex", apexStrictUpdatabilityCheck.Inputs.Strings(), "lint-baseline.xml") } func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) { Loading
apex/builder.go +12 −1 Original line number Diff line number Diff line Loading @@ -1164,7 +1164,18 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) { } } a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build()) depSets := depSetsBuilder.Build() var validations android.Paths if a.checkStrictUpdatabilityLinting(ctx) { baselines := depSets.Baseline.ToList() if len(baselines) > 0 { outputFile := java.VerifyStrictUpdatabilityChecks(ctx, baselines) validations = append(validations, outputFile) } } a.lintReports = java.BuildModuleLintReportZips(ctx, depSets, validations) } func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath { Loading
java/java.go +0 −14 Original line number Diff line number Diff line Loading @@ -2612,13 +2612,6 @@ func (a *Import) JacocoReportClassesFile() android.Path { return nil } func (j *Import) getStrictUpdatabilityLinting() bool { return false } func (j *Import) setStrictUpdatabilityLinting(bool) { } func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...) ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs.GetOrDefault(ctx, nil)...) Loading Loading @@ -3098,13 +3091,6 @@ func (j *DexImport) IsInstallable() bool { return true } func (j *DexImport) getStrictUpdatabilityLinting() bool { return false } func (j *DexImport) setStrictUpdatabilityLinting(bool) { } func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { if len(j.properties.Jars) != 1 { ctx.PropertyErrorf("jars", "exactly one jar must be provided") Loading
java/lint.go +80 −82 Original line number Diff line number Diff line Loading @@ -100,18 +100,12 @@ type linter struct { buildModuleReportZip bool } type LintDepSetsIntf interface { // Methods used to propagate strict_updatability_linting values. GetStrictUpdatabilityLinting() bool SetStrictUpdatabilityLinting(bool) } type LintDepSets struct { HTML, Text, XML *android.DepSet[android.Path] HTML, Text, XML, Baseline *android.DepSet[android.Path] } type LintDepSetsBuilder struct { HTML, Text, XML *android.DepSetBuilder[android.Path] HTML, Text, XML, Baseline *android.DepSetBuilder[android.Path] } func NewLintDepSetBuilder() LintDepSetsBuilder { Loading @@ -119,13 +113,17 @@ func NewLintDepSetBuilder() LintDepSetsBuilder { HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER), Text: android.NewDepSetBuilder[android.Path](android.POSTORDER), XML: android.NewDepSetBuilder[android.Path](android.POSTORDER), Baseline: android.NewDepSetBuilder[android.Path](android.POSTORDER), } } func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder { func (l LintDepSetsBuilder) Direct(html, text, xml android.Path, baseline android.OptionalPath) LintDepSetsBuilder { l.HTML.Direct(html) l.Text.Direct(text) l.XML.Direct(xml) if baseline.Valid() { l.Baseline.Direct(baseline.Path()) } return l } Loading @@ -139,6 +137,9 @@ func (l LintDepSetsBuilder) Transitive(info *LintInfo) LintDepSetsBuilder { if info.TransitiveXML != nil { l.XML.Transitive(info.TransitiveXML) } if info.TransitiveBaseline != nil { l.Baseline.Transitive(info.TransitiveBaseline) } return l } Loading @@ -147,6 +148,7 @@ func (l LintDepSetsBuilder) Build() LintDepSets { HTML: l.HTML.Build(), Text: l.Text.Build(), XML: l.XML.Build(), Baseline: l.Baseline.Build(), } } Loading Loading @@ -194,16 +196,6 @@ var allLintDatabasefiles = map[android.SdkKind]lintDatabaseFiles{ }, } func (l *linter) GetStrictUpdatabilityLinting() bool { return BoolDefault(l.properties.Lint.Strict_updatability_linting, false) } func (l *linter) SetStrictUpdatabilityLinting(strictLinting bool) { l.properties.Lint.Strict_updatability_linting = &strictLinting } var _ LintDepSetsIntf = (*linter)(nil) var LintProvider = blueprint.NewProvider[*LintInfo]() type LintInfo struct { Loading @@ -215,6 +207,7 @@ type LintInfo struct { TransitiveHTML *android.DepSet[android.Path] TransitiveText *android.DepSet[android.Path] TransitiveXML *android.DepSet[android.Path] TransitiveBaseline *android.DepSet[android.Path] } func (l *linter) enabled() bool { Loading Loading @@ -250,7 +243,9 @@ func lintRBEExecStrategy(ctx android.ModuleContext) string { return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy) } func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path) lintPaths { func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path, baselines android.Paths) lintPaths { projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml") // Lint looks for a lint.xml file next to the project.xml file, give it one. configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml") Loading Loading @@ -313,12 +308,10 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks) cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks) if l.GetStrictUpdatabilityLinting() { if Bool(l.properties.Lint.Strict_updatability_linting) && len(baselines) > 0 { // Verify the module does not baseline issues that endanger safe updatability. if l.properties.Lint.Baseline_filename != nil { cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks) } strictUpdatabilityChecksOutputFile := VerifyStrictUpdatabilityChecks(ctx, baselines) cmd.Validation(strictUpdatabilityChecksOutputFile) } return lintPaths{ Loading @@ -330,6 +323,22 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru } func VerifyStrictUpdatabilityChecks(ctx android.ModuleContext, baselines android.Paths) android.Path { rule := android.NewRuleBuilder(pctx, ctx) baselineRspFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check_baselines.rsp") outputFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check.stamp") rule.Command().Text("rm -f").Output(outputFile) rule.Command(). BuiltTool("lint_strict_updatability_checks"). FlagWithArg("--name ", ctx.ModuleName()). FlagWithRspFileInputList("--baselines ", baselineRspFile, baselines). FlagForEachArg("--disallowed_issues ", updatabilityChecks) rule.Command().Text("touch").Output(outputFile) rule.Build("lint_strict_updatability_checks", "lint strict updatability checks") return outputFile } // generateManifest adds a command to the rule to write a simple manifest that contains the // minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest. func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath { Loading Loading @@ -399,6 +408,26 @@ func (l *linter) lint(ctx android.ModuleContext) { l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx, "prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar")) var baseline android.OptionalPath if l.properties.Lint.Baseline_filename != nil { baseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) } html := android.PathForModuleOut(ctx, "lint", "lint-report.html") text := android.PathForModuleOut(ctx, "lint", "lint-report.txt") xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml") referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml") depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline) ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) { if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok { depSetsBuilder.Transitive(info) } }) depSets := depSetsBuilder.Build() rule := android.NewRuleBuilder(pctx, ctx). Sbox(android.PathForModuleOut(ctx, "lint"), android.PathForModuleOut(ctx, "lint.sbox.textproto")). Loading @@ -425,22 +454,9 @@ func (l *linter) lint(ctx android.ModuleContext) { srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp") rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data) lintPaths := l.writeLintProjectXML(ctx, rule, srcsList) html := android.PathForModuleOut(ctx, "lint", "lint-report.html") text := android.PathForModuleOut(ctx, "lint", "lint-report.txt") xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml") referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml") depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml) ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) { if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok { depSetsBuilder.Transitive(info) } }) baselines := depSets.Baseline.ToList() depSets := depSetsBuilder.Build() lintPaths := l.writeLintProjectXML(ctx, rule, srcsList, baselines) rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) Loading Loading @@ -495,8 +511,8 @@ func (l *linter) lint(ctx android.ModuleContext) { cmd.FlagWithArg("--check ", checkOnly) } if l.properties.Lint.Baseline_filename != nil { cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) if baseline.Valid() { cmd.FlagWithInput("--baseline ", baseline.Path()) } cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline) Loading Loading @@ -529,10 +545,11 @@ func (l *linter) lint(ctx android.ModuleContext) { TransitiveHTML: depSets.HTML, TransitiveText: depSets.Text, TransitiveXML: depSets.XML, TransitiveBaseline: depSets.Baseline, }) if l.buildModuleReportZip { l.reports = BuildModuleLintReportZips(ctx, depSets) l.reports = BuildModuleLintReportZips(ctx, depSets, nil) } // Create a per-module phony target to run the lint check. Loading @@ -542,7 +559,7 @@ func (l *linter) lint(ctx android.ModuleContext) { ctx.SetOutputFiles(android.Paths{xml}, ".lint") } func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths { func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets, validations android.Paths) android.Paths { htmlList := android.SortedUniquePaths(depSets.HTML.ToList()) textList := android.SortedUniquePaths(depSets.Text.ToList()) xmlList := android.SortedUniquePaths(depSets.XML.ToList()) Loading @@ -552,13 +569,13 @@ func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) a } htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip") lintZip(ctx, htmlList, htmlZip) lintZip(ctx, htmlList, htmlZip, validations) textZip := android.PathForModuleOut(ctx, "lint-report-text.zip") lintZip(ctx, textList, textZip) lintZip(ctx, textList, textZip, validations) xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip") lintZip(ctx, xmlList, xmlZip) lintZip(ctx, xmlList, xmlZip, validations) return android.Paths{htmlZip, textZip, xmlZip} } Loading Loading @@ -668,7 +685,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { } } lintZip(ctx, paths, outputPath) lintZip(ctx, paths, outputPath, nil) } l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip") Loading Loading @@ -697,17 +714,9 @@ var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil) func init() { android.RegisterParallelSingletonType("lint", func() android.Singleton { return &lintSingleton{} }) registerLintBuildComponents(android.InitRegistrationContext) } func registerLintBuildComponents(ctx android.RegistrationContext) { ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.TopDown("enforce_strict_updatability_linting", enforceStrictUpdatabilityLintingMutator).Parallel() }) } func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) { func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath, validations android.Paths) { paths = android.SortedUniquePaths(android.CopyOfPaths(paths)) sort.Slice(paths, func(i, j int) bool { Loading @@ -719,19 +728,8 @@ func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputPath). FlagWithArg("-C ", android.PathForIntermediates(ctx).String()). FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths) FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths). Validations(validations) rule.Build(outputPath.Base(), outputPath.Base()) } // Enforce the strict updatability linting to all applicable transitive dependencies. func enforceStrictUpdatabilityLintingMutator(ctx android.TopDownMutatorContext) { m := ctx.Module() if d, ok := m.(LintDepSetsIntf); ok && d.GetStrictUpdatabilityLinting() { ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) { if a, ok := d.(LintDepSetsIntf); ok { a.SetStrictUpdatabilityLinting(true) } }) } }