Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b16bd5db authored by Colin Cross's avatar Colin Cross Committed by Gerrit Code Review
Browse files

Merge "Remove top down strict updatability checks" into main

parents 22ad6c00 87427354
Loading
Loading
Loading
Loading
+1 −23
Original line number Diff line number Diff line
@@ -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 {
@@ -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) {
@@ -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)
}
+70 −44
Original line number Diff line number Diff line
@@ -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 {
@@ -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)
		})
	}
}

@@ -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) {
+12 −1
Original line number Diff line number Diff line
@@ -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 {
+0 −14
Original line number Diff line number Diff line
@@ -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)...)
@@ -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")
+80 −82
Original line number Diff line number Diff line
@@ -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 {
@@ -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
}

@@ -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
}

@@ -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(),
	}
}

@@ -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 {
@@ -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 {
@@ -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")
@@ -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{
@@ -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 {
@@ -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")).
@@ -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())
@@ -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)
@@ -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.
@@ -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())
@@ -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}
}
@@ -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")
@@ -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 {
@@ -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