Migrate seapp_contexts to Android.bp

Bug: 33691272
Test: build and boot
Test: atest SELinuxHostTest#testValidSeappContexts
Change-Id: I86f9d010d1628f9756cc152b4ee74dea1b9ff955
diff --git a/Android.bp b/Android.bp
index 438b13f..6aeb27b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -184,6 +184,11 @@
     srcs: ["keystore2_key_contexts"],
 }
 
+se_build_files {
+    name: "seapp_contexts_files",
+    srcs: ["seapp_contexts"],
+}
+
 // For vts_treble_sys_prop_test
 filegroup {
     name: "private_property_contexts",
@@ -1044,17 +1049,3 @@
 se_freeze_test {
     name: "sepolicy_freeze_test",
 }
-
-//////////////////////////////////
-// Makefile rules temporary imported to Soong
-// TODO(b/33691272): remove these after migrating seapp to Soong
-//////////////////////////////////
-makefile_goal {
-    name: "plat_seapp_contexts_rule",
-    product_out_path: "obj/ETC/plat_seapp_contexts_intermediates/plat_seapp_contexts",
-}
-
-makefile_goal {
-    name: "plat_seapp_neverallows_rule",
-    product_out_path: "obj/ETC/plat_seapp_neverallows_intermediates/plat_seapp_neverallows",
-}
diff --git a/Android.mk b/Android.mk
index dfaca5a..2225c63 100644
--- a/Android.mk
+++ b/Android.mk
@@ -703,9 +703,6 @@
 file_contexts.modules.tmp :=
 
 ##################################
-include $(LOCAL_PATH)/seapp_contexts.mk
-
-##################################
 include $(LOCAL_PATH)/contexts_tests.mk
 
 ##################################
diff --git a/build/soong/selinux_contexts.go b/build/soong/selinux_contexts.go
index 71de38a..c55fba2 100644
--- a/build/soong/selinux_contexts.go
+++ b/build/soong/selinux_contexts.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"io"
+	"os"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -58,11 +59,20 @@
 	}
 }
 
+type seappProperties struct {
+	// Files containing neverallow rules.
+	Neverallow_files []string `android:"path"`
+
+	// Precompiled sepolicy binary file which will be fed to checkseapp.
+	Sepolicy *string `android:"path"`
+}
+
 type selinuxContextsModule struct {
 	android.ModuleBase
 
 	properties             selinuxContextsProperties
 	fileContextsProperties fileContextsProperties
+	seappProperties        seappProperties
 	build                  func(ctx android.ModuleContext, inputs android.Paths) android.Path
 	deps                   func(ctx android.BottomUpMutatorContext)
 	outputPath             android.Path
@@ -82,6 +92,7 @@
 	android.RegisterModuleType("property_contexts", propertyFactory)
 	android.RegisterModuleType("service_contexts", serviceFactory)
 	android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory)
+	android.RegisterModuleType("seapp_contexts", seappFactory)
 }
 
 func (m *selinuxContextsModule) InstallInRoot() bool {
@@ -147,6 +158,7 @@
 	m.AddProperties(
 		&m.properties,
 		&m.fileContextsProperties,
+		&m.seappProperties,
 	)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	android.AddLoadHook(m, func(ctx android.LoadHookContext) {
@@ -422,6 +434,31 @@
 	return builtCtxFile
 }
 
+func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
+	neverallowFile := android.PathForModuleGen(ctx, "neverallow")
+	ret := android.PathForModuleGen(ctx, m.stem())
+
+	rule := android.NewRuleBuilder(pctx, ctx)
+	rule.Command().Text("(grep").
+		Flag("-ihe").
+		Text("'^neverallow'").
+		Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)).
+		Text(os.DevNull). // to make grep happy even when Neverallow_files is empty
+		Text(">").
+		Output(neverallowFile).
+		Text("|| true)") // to make ninja happy even when result is empty
+
+	rule.Temporary(neverallowFile)
+	rule.Command().BuiltTool("checkseapp").
+		FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))).
+		FlagWithOutput("-o ", ret).
+		Inputs(inputs).
+		Input(neverallowFile)
+
+	rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name())
+	return ret
+}
+
 func hwServiceFactory() android.Module {
 	m := newModule()
 	m.build = m.buildHwServiceContexts
@@ -447,6 +484,12 @@
 	return m
 }
 
+func seappFactory() android.Module {
+	m := newModule()
+	m.build = m.buildSeappContexts
+	return m
+}
+
 var _ android.OutputFileProducer = (*selinuxContextsModule)(nil)
 
 // Implements android.OutputFileProducer
diff --git a/contexts/Android.bp b/contexts/Android.bp
index ed98683..4679589 100644
--- a/contexts/Android.bp
+++ b/contexts/Android.bp
@@ -222,3 +222,70 @@
     ],
     soc_specific: true,
 }
+
+seapp_contexts {
+    name: "plat_seapp_contexts",
+    srcs: [":seapp_contexts_files{.plat_private}"],
+    sepolicy: ":precompiled_sepolicy",
+}
+
+seapp_contexts {
+    name: "system_ext_seapp_contexts",
+    srcs: [":seapp_contexts_files{.system_ext_private}"],
+    neverallow_files: [":seapp_contexts_files{.plat_private}"],
+    system_ext_specific: true,
+    sepolicy: ":precompiled_sepolicy",
+}
+
+seapp_contexts {
+    name: "product_seapp_contexts",
+    srcs: [":seapp_contexts_files{.product_private}"],
+    neverallow_files: [
+        ":seapp_contexts_files{.plat_private}",
+        ":seapp_contexts_files{.system_ext_private}",
+    ],
+    product_specific: true,
+    sepolicy: ":precompiled_sepolicy",
+}
+
+seapp_contexts {
+    name: "vendor_seapp_contexts",
+    srcs: [
+        ":seapp_contexts_files{.plat_vendor_for_vendor}",
+        ":seapp_contexts_files{.vendor}",
+        ":seapp_contexts_files{.reqd_mask_for_vendor}",
+    ],
+    neverallow_files: [
+        ":seapp_contexts_files{.plat_private_for_vendor}",
+        ":seapp_contexts_files{.system_ext_private_for_vendor}",
+        ":seapp_contexts_files{.product_private_for_vendor}",
+    ],
+    soc_specific: true,
+    sepolicy: ":precompiled_sepolicy",
+}
+
+seapp_contexts {
+    name: "odm_seapp_contexts",
+    srcs: [
+        ":seapp_contexts_files{.odm}",
+    ],
+    neverallow_files: [
+        ":seapp_contexts_files{.plat_private_for_vendor}",
+        ":seapp_contexts_files{.system_ext_private_for_vendor}",
+        ":seapp_contexts_files{.product_private_for_vendor}",
+    ],
+    device_specific: true,
+    sepolicy: ":precompiled_sepolicy",
+}
+
+// for CTS
+genrule {
+    name: "plat_seapp_neverallows",
+    srcs: [
+        ":seapp_contexts_files{.plat_private}",
+        ":seapp_contexts_files{.system_ext_private}",
+        ":seapp_contexts_files{.product_private}",
+    ],
+    out: ["plat_seapp_neverallows"],
+    cmd: "grep -ihe '^neverallow' $(in) > $(out) || true",
+}
diff --git a/seapp_contexts.mk b/seapp_contexts.mk
deleted file mode 100644
index c0c3abb..0000000
--- a/seapp_contexts.mk
+++ /dev/null
@@ -1,142 +0,0 @@
-include $(CLEAR_VARS)
-LOCAL_MODULE := plat_seapp_contexts
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
-LOCAL_LICENSE_CONDITIONS := notice unencumbered
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/selinux
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-plat_sc_files := $(call build_policy, seapp_contexts, $(PLAT_PRIVATE_POLICY))
-
-$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILES := $(plat_sc_files)
-$(LOCAL_BUILT_MODULE): $(built_sepolicy) $(plat_sc_files) $(HOST_OUT_EXECUTABLES)/checkseapp
-	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkseapp -p $(PRIVATE_SEPOLICY) -o $@ $(PRIVATE_SC_FILES)
-
-built_plat_sc := $(LOCAL_BUILT_MODULE)
-plat_sc_files :=
-
-##################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := system_ext_seapp_contexts
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
-LOCAL_LICENSE_CONDITIONS := notice unencumbered
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc/selinux
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-system_ext_sc_files := $(call build_policy, seapp_contexts, $(SYSTEM_EXT_PRIVATE_POLICY))
-plat_sc_neverallow_files := $(call build_policy, seapp_contexts, $(PLAT_PRIVATE_POLICY))
-
-$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILES := $(system_ext_sc_files)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_NEVERALLOW_FILES := $(plat_sc_neverallow_files)
-$(LOCAL_BUILT_MODULE): $(built_sepolicy) $(system_ext_sc_files) $(HOST_OUT_EXECUTABLES)/checkseapp $(plat_sc_neverallow_files)
-	@mkdir -p $(dir $@)
-	$(hide) grep -ihe '^neverallow' $(PRIVATE_SC_NEVERALLOW_FILES) > $@.tmp
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkseapp -p $(PRIVATE_SEPOLICY) -o $@ $(PRIVATE_SC_FILES) $@.tmp
-
-system_ext_sc_files :=
-plat_sc_neverallow_files :=
-
-##################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := product_seapp_contexts
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
-LOCAL_LICENSE_CONDITIONS := notice unencumbered
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc/selinux
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-product_sc_files := $(call build_policy, seapp_contexts, $(PRODUCT_PRIVATE_POLICY))
-plat_sc_neverallow_files := $(call build_policy, seapp_contexts, $(PLAT_PRIVATE_POLICY))
-
-$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILES := $(product_sc_files)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_NEVERALLOW_FILES := $(plat_sc_neverallow_files)
-$(LOCAL_BUILT_MODULE): $(built_sepolicy) $(product_sc_files) $(HOST_OUT_EXECUTABLES)/checkseapp $(plat_sc_neverallow_files)
-	@mkdir -p $(dir $@)
-	$(hide) grep -ihe '^neverallow' $(PRIVATE_SC_NEVERALLOW_FILES) > $@.tmp
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkseapp -p $(PRIVATE_SEPOLICY) -o $@ $(PRIVATE_SC_FILES) $@.tmp
-
-product_sc_files :=
-plat_sc_neverallow_files :=
-
-##################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := vendor_seapp_contexts
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
-LOCAL_LICENSE_CONDITIONS := notice unencumbered
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/selinux
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-vendor_sc_files := $(call build_policy, seapp_contexts, $(BOARD_PLAT_VENDOR_POLICY) $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_REQD_MASK_POLICY))
-plat_sc_neverallow_files := $(call build_policy, seapp_contexts, $(PLAT_PRIVATE_POLICY) $(SYSTEM_EXT_PRIVATE_POLICY) $(PRODUCT_PRIVATE_POLICY))
-
-$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILES := $(vendor_sc_files)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_NEVERALLOW_FILES := $(plat_sc_neverallow_files)
-$(LOCAL_BUILT_MODULE): $(built_sepolicy) $(vendor_sc_files) $(HOST_OUT_EXECUTABLES)/checkseapp $(plat_sc_neverallow_files)
-	@mkdir -p $(dir $@)
-	$(hide) grep -ihe '^neverallow' $(PRIVATE_SC_NEVERALLOW_FILES) > $@.tmp
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkseapp -p $(PRIVATE_SEPOLICY) -o $@ $(PRIVATE_SC_FILES) $@.tmp
-
-built_vendor_sc := $(LOCAL_BUILT_MODULE)
-vendor_sc_files :=
-
-##################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := odm_seapp_contexts
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
-LOCAL_LICENSE_CONDITIONS := notice unencumbered
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc/selinux
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-odm_sc_files := $(call build_policy, seapp_contexts, $(BOARD_ODM_SEPOLICY_DIRS))
-plat_sc_neverallow_files := $(call build_policy, seapp_contexts, $(PLAT_PRIVATE_POLICY) $(SYSTEM_EXT_PRIVATE_POLICY) $(PRODUCT_PRIVATE_POLICY))
-
-$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILES := $(odm_sc_files)
-$(LOCAL_BUILT_MODULE): PRIVATE_SC_NEVERALLOW_FILES := $(plat_sc_neverallow_files)
-$(LOCAL_BUILT_MODULE): $(built_sepolicy) $(odm_sc_files) $(HOST_OUT_EXECUTABLES)/checkseapp $(plat_sc_neverallow_files)
-	@mkdir -p $(dir $@)
-	$(hide) grep -ihe '^neverallow' $(PRIVATE_SC_NEVERALLOW_FILES) > $@.tmp
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkseapp -p $(PRIVATE_SEPOLICY) -o $@ $(PRIVATE_SC_FILES) $@.tmp
-
-built_odm_sc := $(LOCAL_BUILT_MODULE)
-odm_sc_files :=
-
-##################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := plat_seapp_neverallows
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
-LOCAL_LICENSE_CONDITIONS := notice unencumbered
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(plat_sc_neverallow_files)
-	@mkdir -p $(dir $@)
-	- $(hide) grep -ihe '^neverallow' $< > $@
-
-plat_sc_neverallow_files :=