Use target specific intermediate paths

This won't be harmful and this can help reduce rebuilding sepolicy
artifacts upon lunch target change.

Bug: 279524023
Test: m selinux_policy
Change-Id: I859de6dc0ac1958b44d847159904960bd7f9a0c2
diff --git a/build/soong/policy.go b/build/soong/policy.go
index aea8e09..7c1aab2 100644
--- a/build/soong/policy.go
+++ b/build/soong/policy.go
@@ -209,7 +209,7 @@
 }
 
 func (c *policyConf) transformPolicyToConf(ctx android.ModuleContext) android.OutputPath {
-	conf := android.PathForModuleOut(ctx, c.stem()).OutputPath
+	conf := pathForModuleOut(ctx, c.stem())
 	rule := android.NewRuleBuilder(pctx, ctx)
 
 	srcs := android.PathsForModuleSrc(ctx, c.properties.Srcs)
@@ -340,7 +340,7 @@
 }
 
 func (c *policyCil) compileConfToCil(ctx android.ModuleContext, conf android.Path) android.OutputPath {
-	cil := android.PathForModuleOut(ctx, c.stem()).OutputPath
+	cil := pathForModuleOut(ctx, c.stem())
 	rule := android.NewRuleBuilder(pctx, ctx)
 	checkpolicyCmd := rule.Command().BuiltTool("checkpolicy").
 		Flag("-C"). // Write CIL
@@ -496,7 +496,7 @@
 		ctx.PropertyErrorf("srcs", "must be specified")
 		return
 	}
-	bin := android.PathForModuleOut(ctx, c.stem()+"_policy")
+	bin := pathForModuleOut(ctx, c.stem()+"_policy")
 	rule := android.NewRuleBuilder(pctx, ctx)
 	secilcCmd := rule.Command().BuiltTool("secilc").
 		Flag("-m").                 // Multiple decls
@@ -514,7 +514,7 @@
 
 	// permissive check is performed only in user build (not debuggable).
 	if !ctx.Config().Debuggable() {
-		permissiveDomains := android.PathForModuleOut(ctx, c.stem()+"_permissive")
+		permissiveDomains := pathForModuleOut(ctx, c.stem()+"_permissive")
 		cmd := rule.Command().BuiltTool("sepolicy-analyze").
 			Input(bin).
 			Text("permissive")
@@ -544,7 +544,7 @@
 			Text("; exit 1; fi")
 	}
 
-	out := android.PathForModuleOut(ctx, c.stem())
+	out := pathForModuleOut(ctx, c.stem())
 	rule.Command().Text("cp").
 		Flag("-f").
 		Input(bin).
diff --git a/build/soong/selinux.go b/build/soong/selinux.go
index 7ad4776..5fbe01eb 100644
--- a/build/soong/selinux.go
+++ b/build/soong/selinux.go
@@ -28,3 +28,15 @@
 var (
 	pctx = android.NewPackageContext("android/soong/selinux")
 )
+
+// pathForModuleOut is same as android.PathForModuleOut, except that it uses DeviceName() as its
+// intermediate directory name for system_ext/product/vendor/odm modules, to avoid rebuilding upon
+// target change. Contents of system modules (core sepolicy) should be identical across devices, so
+// they falls back to android.PathForModuleOut.
+func pathForModuleOut(ctx android.ModuleContext, paths ...string) android.OutputPath {
+	if ctx.Platform() && !ctx.InstallInRecovery() {
+		return android.PathForModuleOut(ctx, paths...).OutputPath
+	}
+
+	return android.PathForModuleOut(ctx, ctx.Config().DeviceName()).Join(ctx, paths...)
+}
diff --git a/build/soong/selinux_contexts.go b/build/soong/selinux_contexts.go
index 7faafc6..587fe91 100644
--- a/build/soong/selinux_contexts.go
+++ b/build/soong/selinux_contexts.go
@@ -243,11 +243,11 @@
 var _ android.ImageInterface = (*selinuxContextsModule)(nil)
 
 func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
-	builtContext := android.PathForModuleGen(ctx, ctx.ModuleName()+"_m4out")
+	builtContext := pathForModuleOut(ctx, ctx.ModuleName()+"_m4out")
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 
-	newlineFile := android.PathForModuleGen(ctx, "newline")
+	newlineFile := pathForModuleOut(ctx, "newline")
 
 	rule.Command().Text("echo").FlagWithOutput("> ", newlineFile)
 	rule.Temporary(newlineFile)
@@ -267,7 +267,7 @@
 	if proptools.Bool(m.properties.Remove_comment) {
 		rule.Temporary(builtContext)
 
-		remove_comment_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_remove_comment")
+		remove_comment_output := pathForModuleOut(ctx, ctx.ModuleName()+"_remove_comment")
 
 		rule.Command().
 			Text("sed -e 's/#.*$//' -e '/^$/d'").
@@ -280,7 +280,7 @@
 	if proptools.Bool(m.properties.Fc_sort) {
 		rule.Temporary(builtContext)
 
-		sorted_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_sorted")
+		sorted_output := pathForModuleOut(ctx, ctx.ModuleName()+"_sorted")
 
 		rule.Command().
 			Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
@@ -290,7 +290,7 @@
 		builtContext = sorted_output
 	}
 
-	ret := android.PathForModuleGen(ctx, m.stem())
+	ret := pathForModuleOut(ctx, m.stem())
 	rule.Temporary(builtContext)
 	rule.Command().Text("cp").Input(builtContext).Output(ret)
 
@@ -309,7 +309,7 @@
 
 	if ctx.Config().FlattenApex() {
 		for _, path := range android.PathsForModuleSrc(ctx, m.fileContextsProperties.Flatten_apex.Srcs) {
-			out := android.PathForModuleGen(ctx, "flattened_apex", path.Rel())
+			out := pathForModuleOut(ctx, "flattened_apex", path.Rel())
 			apex_path := "/system/apex/" + strings.Replace(
 				strings.TrimSuffix(path.Base(), "-file_contexts"),
 				".", "\\\\.", -1)
@@ -394,7 +394,7 @@
 			cmd.Flag("--strict")
 		}
 
-		out := android.PathForModuleGen(ctx, "namespace_checked").Join(ctx, input.String())
+		out := pathForModuleOut(ctx, "namespace_checked").Join(ctx, input.String())
 		rule.Command().Text("cp -f").Input(input).Output(out)
 		ret = append(ret, out)
 	}
@@ -426,7 +426,7 @@
 
 	// check compatibility with sysprop_library
 	if len(apiFiles) > 0 {
-		out := android.PathForModuleGen(ctx, ctx.ModuleName()+"_api_checked")
+		out := pathForModuleOut(ctx, ctx.ModuleName()+"_api_checked")
 		rule := android.NewRuleBuilder(pctx, ctx)
 
 		msg := `\n******************************\n` +
@@ -452,8 +452,8 @@
 }
 
 func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
-	neverallowFile := android.PathForModuleGen(ctx, "neverallow")
-	ret := android.PathForModuleGen(ctx, m.stem())
+	neverallowFile := pathForModuleOut(ctx, "neverallow")
+	ret := pathForModuleOut(ctx, m.stem())
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 	rule.Command().Text("(grep").
@@ -547,7 +547,7 @@
 	flags []string
 
 	properties    contextsTestProperties
-	testTimestamp android.ModuleOutPath
+	testTimestamp android.OutputPath
 }
 
 // checkfc parses a context file and checks for syntax errors.
@@ -622,7 +622,7 @@
 		Input(sepolicy).
 		Inputs(srcs)
 
-	m.testTimestamp = android.PathForModuleOut(ctx, "timestamp")
+	m.testTimestamp = pathForModuleOut(ctx, "timestamp")
 	rule.Command().Text("touch").Output(m.testTimestamp)
 	rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName())
 }
diff --git a/build/soong/sepolicy_neverallow.go b/build/soong/sepolicy_neverallow.go
index 98dd3cf..fc47ab3 100644
--- a/build/soong/sepolicy_neverallow.go
+++ b/build/soong/sepolicy_neverallow.go
@@ -36,7 +36,7 @@
 type neverallowTestModule struct {
 	android.ModuleBase
 	properties    neverallowTestProperties
-	testTimestamp android.ModuleOutPath
+	testTimestamp android.OutputPath
 }
 
 type nameProperties struct {
@@ -98,7 +98,7 @@
 }
 
 func (n *neverallowTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	n.testTimestamp = android.PathForModuleOut(ctx, "timestamp")
+	n.testTimestamp = pathForModuleOut(ctx, "timestamp")
 	if ctx.Config().SelinuxIgnoreNeverallows() {
 		// just touch
 		android.WriteFileRule(ctx, n.testTimestamp, "")
@@ -146,7 +146,7 @@
 	rule := android.NewRuleBuilder(pctx, ctx)
 
 	// Step 1. Build a binary policy from the conf file including build test
-	binaryPolicy := android.PathForModuleOut(ctx, "policy")
+	binaryPolicy := pathForModuleOut(ctx, "policy")
 	rule.Command().BuiltTool("checkpolicy").
 		Flag("-M").
 		FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
diff --git a/build/soong/versioned_policy.go b/build/soong/versioned_policy.go
index c316d2a..be396e3 100644
--- a/build/soong/versioned_policy.go
+++ b/build/soong/versioned_policy.go
@@ -103,7 +103,7 @@
 		stem = ctx.ModuleName()
 	}
 
-	out := android.PathForModuleOut(ctx, stem)
+	out := pathForModuleOut(ctx, stem)
 	rule := android.NewRuleBuilder(pctx, ctx)
 
 	if proptools.String(m.properties.Base) == "" {