Remove top down strict updatability checks

The enforce_strict_updatability_linting and apex_strict_updatability_lint
are some of the last top down mutators, and removing them will help
with incremental analysis.  Both mutators are used to propagate a flag
to transitive java dependencies that causes them to add extra checks to
their lint rules to require that baselines not include any skipped
NewApi checks.

Instead of modifying dependencies to check the baselines, propagate the
baselines up to the modules that are requesting the checks, and perform
the checks on all transitive baselines there.

Bug: 367784740
Test: TestJavaLintStrictUpdatabilityLinting
Test: TestApexStrictUpdtabilityLint
Flag: EXEMPT refactor
Change-Id: Ief2e3b26d745da61f13e621d635a5879d9c56779
diff --git a/apex/apex.go b/apex/apex.go
index aff69c1..79f1ad6 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -68,8 +68,6 @@
 	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 @@
 	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 @@
 	}
 )
 
-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)
 }
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8cb8a91..c3c9b7c 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -9693,59 +9693,84 @@
 	}
 
 	testCases := []struct {
-		testCaseName              string
-		apexUpdatable             bool
-		javaStrictUpdtabilityLint bool
-		lintFileExists            bool
-		disallowedFlagExpected    bool
+		testCaseName                    string
+		apexUpdatable                   bool
+		javaStrictUpdtabilityLint       bool
+		lintFileExists                  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,
+			testCaseName:                    "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
+			apexUpdatable:                   true,
+			javaStrictUpdtabilityLint:       true,
+			lintFileExists:                  false,
+			disallowedFlagExpectedOnApex:    false,
+			disallowedFlagExpectedOnJavalib: false,
 		},
 		{
-			testCaseName:              "non-updatable apex respects strict_updatability of javalib",
-			apexUpdatable:             false,
-			javaStrictUpdtabilityLint: false,
-			lintFileExists:            true,
-			disallowedFlagExpected:    false,
+			testCaseName:                    "non-updatable apex respects strict_updatability of javalib",
+			apexUpdatable:                   false,
+			javaStrictUpdtabilityLint:       false,
+			lintFileExists:                  true,
+			disallowedFlagExpectedOnApex:    false,
+			disallowedFlagExpectedOnJavalib: false,
 		},
 		{
-			testCaseName:              "non-updatable apex respects strict updatability of javalib",
-			apexUpdatable:             false,
-			javaStrictUpdtabilityLint: true,
-			lintFileExists:            true,
-			disallowedFlagExpected:    true,
+			testCaseName:                    "non-updatable apex respects strict updatability of javalib",
+			apexUpdatable:                   false,
+			javaStrictUpdtabilityLint:       true,
+			lintFileExists:                  true,
+			disallowedFlagExpectedOnApex:    false,
+			disallowedFlagExpectedOnJavalib: true,
 		},
 		{
-			testCaseName:              "updatable apex sets strict updatability of javalib to true",
-			apexUpdatable:             true,
-			javaStrictUpdtabilityLint: false, // will be set to true by mutator
-			lintFileExists:            true,
-			disallowedFlagExpected:    true,
+			testCaseName:                    "updatable apex checks strict updatability of javalib",
+			apexUpdatable:                   true,
+			javaStrictUpdtabilityLint:       false,
+			lintFileExists:                  true,
+			disallowedFlagExpectedOnApex:    true,
+			disallowedFlagExpectedOnJavalib: false,
 		},
 	}
 
 	for _, testCase := range testCases {
-		fixtures := []android.FixturePreparer{}
-		baselineProperty := ""
-		if testCase.lintFileExists {
-			fixtures = append(fixtures, fs.AddToFixture())
-			baselineProperty = "baseline_filename: \"lint-baseline.xml\""
-		}
-		bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
+		t.Run(testCase.testCaseName, func(t *testing.T) {
+			fixtures := []android.FixturePreparer{}
+			baselineProperty := ""
+			if testCase.lintFileExists {
+				fixtures = append(fixtures, fs.AddToFixture())
+				baselineProperty = "baseline_filename: \"lint-baseline.xml\""
+			}
+			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")
+			result := testApex(t, bp, fixtures...)
 
-		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 @@
 	}
 
 	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) {
diff --git a/apex/builder.go b/apex/builder.go
index 244119b..bf3ba9f 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -1164,7 +1164,18 @@
 		}
 	}
 
-	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 {
diff --git a/java/java.go b/java/java.go
index c6fa663..f0f70a1 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2612,13 +2612,6 @@
 	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 @@
 	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")
diff --git a/java/lint.go b/java/lint.go
index 5cd49a8..2cbefc3 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -100,32 +100,30 @@
 	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 {
 	return LintDepSetsBuilder{
-		HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
-		Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
-		XML:  android.NewDepSetBuilder[android.Path](android.POSTORDER),
+		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,14 +137,18 @@
 	if info.TransitiveXML != nil {
 		l.XML.Transitive(info.TransitiveXML)
 	}
+	if info.TransitiveBaseline != nil {
+		l.Baseline.Transitive(info.TransitiveBaseline)
+	}
 	return l
 }
 
 func (l LintDepSetsBuilder) Build() LintDepSets {
 	return LintDepSets{
-		HTML: l.HTML.Build(),
-		Text: l.Text.Build(),
-		XML:  l.XML.Build(),
+		HTML:     l.HTML.Build(),
+		Text:     l.Text.Build(),
+		XML:      l.XML.Build(),
+		Baseline: l.Baseline.Build(),
 	}
 }
 
@@ -194,16 +196,6 @@
 	},
 }
 
-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 {
@@ -212,9 +204,10 @@
 	XML               android.Path
 	ReferenceBaseline android.Path
 
-	TransitiveHTML *android.DepSet[android.Path]
-	TransitiveText *android.DepSet[android.Path]
-	TransitiveXML  *android.DepSet[android.Path]
+	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 @@
 	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 @@
 	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 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 @@
 	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 @@
 	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)
+	baselines := depSets.Baseline.ToList()
 
-	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)
-		}
-	})
-
-	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 @@
 		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)
@@ -526,13 +542,14 @@
 		XML:               xml,
 		ReferenceBaseline: referenceBaseline,
 
-		TransitiveHTML: depSets.HTML,
-		TransitiveText: depSets.Text,
-		TransitiveXML:  depSets.XML,
+		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 @@
 	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 @@
 	}
 
 	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 @@
 			}
 		}
 
-		lintZip(ctx, paths, outputPath)
+		lintZip(ctx, paths, outputPath, nil)
 	}
 
 	l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
@@ -697,17 +714,9 @@
 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 @@
 	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)
-			}
-		})
-	}
-}
diff --git a/java/lint_test.go b/java/lint_test.go
index b51753f..afe3914 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -164,7 +164,7 @@
 			sdk_version: "current",
 			lint: {
 				strict_updatability_linting: true,
-				baseline_filename: "lint-baseline.xml",
+				baseline_filename: "foo_lint_baseline.xml",
 			},
 		}
 
@@ -176,7 +176,7 @@
 			min_sdk_version: "29",
 			sdk_version: "current",
 			lint: {
-				baseline_filename: "lint-baseline.xml",
+				baseline_filename: "bar_lint_baseline.xml",
 			}
 		}
 	`
@@ -188,18 +188,13 @@
 		RunTestWithBp(t, bp)
 
 	foo := result.ModuleForTests("foo", "android_common")
-	sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto"))
-	if !strings.Contains(*sboxProto.Commands[0].Command,
-		"--baseline lint-baseline.xml --disallowed_issues NewApi") {
+	strictUpdatabilityCheck := foo.Output("lint_strict_updatability_check.stamp")
+	if !strings.Contains(strictUpdatabilityCheck.RuleParams.Command,
+		"--disallowed_issues NewApi") {
 		t.Error("did not restrict baselining NewApi")
 	}
-
-	bar := result.ModuleForTests("bar", "android_common")
-	sboxProto = android.RuleBuilderSboxProtoForTests(t, result.TestContext, bar.Output("lint.sbox.textproto"))
-	if !strings.Contains(*sboxProto.Commands[0].Command,
-		"--baseline lint-baseline.xml --disallowed_issues NewApi") {
-		t.Error("did not restrict baselining NewApi")
-	}
+	android.AssertStringListContains(t, "strict updatability check baseline inputs", strictUpdatabilityCheck.Inputs.Strings(), "foo_lint_baseline.xml")
+	android.AssertStringListContains(t, "strict updatability check baseline inputs", strictUpdatabilityCheck.Inputs.Strings(), "bar_lint_baseline.xml")
 }
 
 func TestJavaLintDatabaseSelectionFull(t *testing.T) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index eb9fa5f..c7a1292 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2257,21 +2257,6 @@
 }
 
 // to satisfy apex.javaDependency interface
-func (module *SdkLibraryImport) GetStrictUpdatabilityLinting() bool {
-	if module.implLibraryModule == nil {
-		return false
-	} else {
-		return module.implLibraryModule.GetStrictUpdatabilityLinting()
-	}
-}
-
-func (module *SdkLibraryImport) SetStrictUpdatabilityLinting(strictLinting bool) {
-	if module.implLibraryModule != nil {
-		module.implLibraryModule.SetStrictUpdatabilityLinting(strictLinting)
-	}
-}
-
-// to satisfy apex.javaDependency interface
 func (module *SdkLibraryImport) Stem() string {
 	return module.BaseModuleName()
 }
diff --git a/java/testing.go b/java/testing.go
index 6cc9fd1..d5a19e9 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -388,7 +388,6 @@
 	RegisterStubsBuildComponents(ctx)
 	RegisterSystemModulesBuildComponents(ctx)
 	registerSystemserverClasspathBuildComponents(ctx)
-	registerLintBuildComponents(ctx)
 	android.RegisterApexContributionsBuildComponents(ctx)
 }
 
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 3d81b83..00b3ca5 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -184,12 +184,21 @@
     libs: ["ninja_rsp"],
 }
 
-python_test_host {
-    name: "lint_project_xml_test",
-    main: "lint_project_xml_test.py",
+python_binary_host {
+    name: "lint_strict_updatability_checks",
+    main: "lint_strict_updatability_checks.py",
     srcs: [
-        "lint_project_xml_test.py",
-        "lint_project_xml.py",
+        "lint_strict_updatability_checks.py",
+    ],
+    libs: ["ninja_rsp"],
+}
+
+python_test_host {
+    name: "lint_strict_updatability_checks_test",
+    main: "lint_strict_updatability_checks_test.py",
+    srcs: [
+        "lint_strict_updatability_checks_test.py",
+        "lint_strict_updatability_checks.py",
     ],
     libs: ["ninja_rsp"],
     test_suites: ["general-tests"],
diff --git a/scripts/lint_project_xml.py b/scripts/lint_project_xml.py
index c40b07d..ce6aa21 100755
--- a/scripts/lint_project_xml.py
+++ b/scripts/lint_project_xml.py
@@ -75,8 +75,6 @@
                       help='file containing the module\'s manifest.')
   parser.add_argument('--merged_manifest', dest='merged_manifest',
                       help='file containing merged manifest for the module and its dependencies.')
-  parser.add_argument('--baseline', dest='baseline_path',
-                      help='file containing baseline lint issues.')
   parser.add_argument('--library', dest='library', action='store_true',
                       help='mark the module as a library.')
   parser.add_argument('--test', dest='test', action='store_true',
@@ -94,8 +92,6 @@
                      help='treat a lint issue as a warning.')
   group.add_argument('--disable_check', dest='checks', action=check_action('ignore'), default=[],
                      help='disable a lint issue.')
-  group.add_argument('--disallowed_issues', dest='disallowed_issues', default=[],
-                     help='lint issues disallowed in the baseline file')
   return parser.parse_args()
 
 
@@ -140,30 +136,10 @@
   f.write("</lint>\n")
 
 
-def check_baseline_for_disallowed_issues(baseline, forced_checks):
-  issues_element = baseline.documentElement
-  if issues_element.tagName != 'issues':
-    raise RuntimeError('expected issues tag at root')
-  issues = issues_element.getElementsByTagName('issue')
-  disallowed = set()
-  for issue in issues:
-    id = issue.getAttribute('id')
-    if id in forced_checks:
-      disallowed.add(id)
-  return disallowed
-
-
 def main():
   """Program entry point."""
   args = parse_args()
 
-  if args.baseline_path:
-    baseline = minidom.parse(args.baseline_path)
-    disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
-    if disallowed_issues:
-      sys.exit('disallowed issues %s found in lint baseline file %s for module %s'
-                         % (disallowed_issues, args.baseline_path, args.name))
-
   if args.project_out:
     with open(args.project_out, 'w') as f:
       write_project_xml(f, args)
diff --git a/scripts/lint_strict_updatability_checks.py b/scripts/lint_strict_updatability_checks.py
new file mode 100755
index 0000000..5b5dfd8
--- /dev/null
+++ b/scripts/lint_strict_updatability_checks.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""This file checks baselines passed to Android Lint for checks that must not be baselined."""
+
+import argparse
+import sys
+from xml.dom import minidom
+
+from ninja_rsp import NinjaRspFileReader
+
+
+def parse_args():
+  """Parse commandline arguments."""
+
+  def convert_arg_line_to_args(arg_line):
+    for arg in arg_line.split():
+      if arg.startswith('#'):
+        return
+      if not arg.strip():
+        continue
+      yield arg
+
+  parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
+  parser.convert_arg_line_to_args = convert_arg_line_to_args
+  parser.add_argument('--name', dest='name',
+                      help='name of the module.')
+  parser.add_argument('--baselines', dest='baselines', action='append', default=[],
+                      help='file containing whitespace separated list of baseline files.')
+  parser.add_argument('--disallowed_issues', dest='disallowed_issues', default=[],
+                     help='lint issues disallowed in the baseline file')
+  return parser.parse_args()
+
+
+def check_baseline_for_disallowed_issues(baseline, forced_checks):
+  issues_element = baseline.documentElement
+  if issues_element.tagName != 'issues':
+    raise RuntimeError('expected issues tag at root')
+  issues = issues_element.getElementsByTagName('issue')
+  disallowed = set()
+  for issue in issues:
+    id = issue.getAttribute('id')
+    if id in forced_checks:
+      disallowed.add(id)
+  return disallowed
+
+
+def main():
+  """Program entry point."""
+  args = parse_args()
+
+  error = False
+  for baseline_rsp_file in args.baselines:
+    for baseline_path in NinjaRspFileReader(baseline_rsp_file):
+      baseline = minidom.parse(baseline_path)
+      disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
+      if disallowed_issues:
+        print('disallowed issues %s found in lint baseline file %s for module %s'
+                % (disallowed_issues, baseline_path, args.name))
+        error = True
+
+  if error:
+    sys.exit(1)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/scripts/lint_project_xml_test.py b/scripts/lint_strict_updatability_checks_test.py
old mode 100644
new mode 100755
similarity index 88%
rename from scripts/lint_project_xml_test.py
rename to scripts/lint_strict_updatability_checks_test.py
index 344691d..fd8610f
--- a/scripts/lint_project_xml_test.py
+++ b/scripts/lint_strict_updatability_checks_test.py
@@ -15,12 +15,12 @@
 # limitations under the License.
 #
 
-"""Unit tests for lint_project_xml.py."""
+"""Unit tests for lint_strict_updatability_checks.py."""
 
 import unittest
 from xml.dom import minidom
 
-import lint_project_xml
+import lint_strict_updatability_checks
 
 
 class CheckBaselineForDisallowedIssuesTest(unittest.TestCase):
@@ -44,7 +44,7 @@
       '</issues>\n')
 
   def test_check_baseline_for_disallowed_issues(self):
-    disallowed_issues = lint_project_xml.check_baseline_for_disallowed_issues(self.baseline_xml, ["foo", "bar", "qux"])
+    disallowed_issues = lint_strict_updatability_checks.check_baseline_for_disallowed_issues(self.baseline_xml, ["foo", "bar", "qux"])
     self.assertEqual({"foo", "bar"}, disallowed_issues)