Merge changes from topic "se_policy_binary"

* changes:
  Migrate system sepolicy binaries to Soong
  Add se_policy_binary module
diff --git a/Android.bp b/Android.bp
index 5629e1c..1c272f8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1035,6 +1035,125 @@
 }
 
 //////////////////////////////////
+// Base system policy for treble sepolicy tests.
+// If system sepolicy is extended (e.g. by SoC vendors), their plat_pub_versioned.cil may differ
+// with system/sepolicy/prebuilts/api/{version}/plat_pub_versioned.cil. In that case,
+// BOARD_PLAT_PUB_VERSIONED_POLICY can be used to specify extended plat_pub_versioned.cil.
+// See treble_sepolicy_tests_for_release.mk for more details.
+//////////////////////////////////
+se_policy_conf {
+    name: "base_plat_sepolicy.conf",
+    srcs: [":se_build_files{.plat}"],
+    build_variant: "user",
+    installable: false,
+}
+
+se_policy_cil {
+    name: "base_plat_sepolicy.cil",
+    src: ":base_plat_sepolicy.conf",
+    additional_cil_files: ["private/technical_debt.cil"],
+    installable: false,
+    secilc_check: false, // done by se_policy_binary
+}
+
+se_policy_binary {
+    name: "base_plat_sepolicy",
+    srcs: [":base_plat_sepolicy.cil"],
+    installable: false,
+}
+
+se_policy_conf {
+    name: "base_system_ext_sepolicy.conf",
+    srcs: [":se_build_files{.system_ext}"],
+    build_variant: "user",
+    installable: false,
+}
+
+se_policy_cil {
+    name: "base_system_ext_sepolicy.cil",
+    src: ":base_system_ext_sepolicy.conf",
+    additional_cil_files: ["private/technical_debt.cil"],
+    system_ext_specific: true,
+    installable: false,
+    secilc_check: false, // done by se_policy_binary
+}
+
+se_policy_binary {
+    name: "base_system_ext_sepolicy",
+    srcs: [":base_system_ext_sepolicy.cil"],
+    system_ext_specific: true,
+    installable: false,
+}
+
+se_policy_conf {
+    name: "base_product_sepolicy.conf",
+    srcs: [":se_build_files{.product}"],
+    build_variant: "user",
+    installable: false,
+}
+
+se_policy_cil {
+    name: "base_product_sepolicy.cil",
+    src: ":base_product_sepolicy.conf",
+    additional_cil_files: ["private/technical_debt.cil"],
+    product_specific: true,
+    installable: false,
+    secilc_check: false, // done by se_policy_binary
+}
+
+se_policy_binary {
+    name: "base_product_sepolicy",
+    srcs: [":base_product_sepolicy.cil"],
+    product_specific: true,
+    installable: false,
+}
+
+se_policy_conf {
+    name: "base_plat_pub_policy.conf",
+    srcs: [":se_build_files{.plat_public}"],
+    build_variant: "user",
+    installable: false,
+}
+
+se_policy_cil {
+    name: "base_plat_pub_policy.cil",
+    src: ":base_plat_pub_policy.conf",
+    filter_out: [":reqd_policy_mask.cil"],
+    secilc_check: false,
+    installable: false,
+}
+
+se_policy_conf {
+    name: "base_system_ext_pub_policy.conf",
+    srcs: [":se_build_files{.system_ext_public}"], // system_ext_public includes system
+    build_variant: "user",
+    installable: false,
+}
+
+se_policy_cil {
+    name: "base_system_ext_pub_policy.cil",
+    src: ":base_system_ext_pub_policy.conf",
+    filter_out: [":reqd_policy_mask.cil"],
+    secilc_check: false,
+    installable: false,
+}
+
+se_policy_conf {
+    name: "base_product_pub_policy.conf",
+    srcs: [":se_build_files{.product_public}"], // product_ includes system and system_ext
+    build_variant: "user",
+    installable: false,
+}
+
+se_policy_cil {
+    name: "base_product_pub_policy.cil",
+    src: ":base_product_pub_policy.conf",
+    filter_out: [":reqd_policy_mask.cil"],
+    secilc_check: false,
+    installable: false,
+}
+
+//////////////////////////////////
 // se_freeze_test compares the plat sepolicy with the prebuilt sepolicy
 // Additional directories can be specified via Makefile variables:
 // SEPOLICY_FREEZE_TEST_EXTRA_DIRS and SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS.
diff --git a/Android.mk b/Android.mk
index cc9fe55..66ff2e3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1304,199 +1304,18 @@
 	$(hide) touch $@
 
 ##################################
-intermediates := $(call intermediates-dir-for,ETC,built_plat_sepolicy,,,,)
-
-# plat_sepolicy - the current platform policy only, built into a policy binary.
-# TODO - this currently excludes partner extensions, but support should be added
-# to enable partners to add their own compatibility mapping
-policy_files := $(call build_policy, $(sepolicy_build_files), \
-  $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
-base_plat_policy.conf := $(intermediates)/base_plat_policy.conf
-$(base_plat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(base_plat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(base_plat_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
-$(base_plat_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
-$(base_plat_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
-$(base_plat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(base_plat_policy.conf): PRIVATE_SEPOLICY_SPLIT := true
-$(base_plat_policy.conf): PRIVATE_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY)
-$(base_plat_policy.conf): PRIVATE_TREBLE_SYSPROP_NEVERALLOW := $(treble_sysprop_neverallow)
-$(base_plat_policy.conf): PRIVATE_ENFORCE_SYSPROP_OWNER := $(enforce_sysprop_owner)
-$(base_plat_policy.conf): PRIVATE_ENFORCE_DEBUGFS_RESTRICTION := $(enforce_debugfs_restriction)
-$(base_plat_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
-$(base_plat_policy.conf): $(policy_files) $(M4)
-	$(transform-policy-to-conf)
-	$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit
-
-built_plat_sepolicy := $(intermediates)/built_plat_sepolicy
-$(built_plat_sepolicy): PRIVATE_ADDITIONAL_CIL_FILES := \
-  $(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY))
-$(built_plat_sepolicy): PRIVATE_NEVERALLOW_ARG := $(NEVERALLOW_ARG)
-$(built_plat_sepolicy): $(base_plat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy \
-$(HOST_OUT_EXECUTABLES)/secilc \
-$(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY)) \
-$(built_sepolicy_neverallows)
-	@mkdir -p $(dir $@)
-	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c \
-		$(POLICYVERS) -o $@ $<
-	$(hide) cat $(PRIVATE_ADDITIONAL_CIL_FILES) >> $@
-	$(hide) $(HOST_OUT_EXECUTABLES)/secilc -m -M true -G -c $(POLICYVERS) $(PRIVATE_NEVERALLOW_ARG) $@ -o $@ -f /dev/null
-
-policy_files := $(call build_policy, $(sepolicy_build_files), \
-  $(PLAT_PUBLIC_POLICY) $(REQD_MASK_POLICY))
-base_plat_pub_policy.conf := $(intermediates)/base_plat_pub_policy.conf
-$(base_plat_pub_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(base_plat_pub_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(base_plat_pub_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
-$(base_plat_pub_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
-$(base_plat_pub_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
-$(base_plat_pub_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(base_plat_pub_policy.conf): PRIVATE_SEPOLICY_SPLIT := true
-$(base_plat_pub_policy.conf): PRIVATE_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY)
-$(base_plat_pub_policy.conf): PRIVATE_TREBLE_SYSPROP_NEVERALLOW := $(treble_sysprop_neverallow)
-$(base_plat_pub_policy.conf): PRIVATE_ENFORCE_SYSPROP_OWNER := $(enforce_sysprop_owner)
-$(base_plat_pub_policy.conf): PRIVATE_ENFORCE_DEBUGFS_RESTRICTION := $(enforce_debugfs_restriction)
-$(base_plat_pub_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
-$(base_plat_pub_policy.conf): $(policy_files) $(M4)
-	$(transform-policy-to-conf)
-
-base_plat_pub_policy.cil := $(intermediates)/base_plat_pub_policy.cil
-$(base_plat_pub_policy.cil): PRIVATE_POL_CONF := $(base_plat_pub_policy.conf)
-$(base_plat_pub_policy.cil): PRIVATE_REQD_MASK := $(reqd_policy_mask.cil)
-$(base_plat_pub_policy.cil): $(HOST_OUT_EXECUTABLES)/checkpolicy \
-$(HOST_OUT_EXECUTABLES)/build_sepolicy $(base_plat_pub_policy.conf) $(reqd_policy_mask.cil)
-	@mkdir -p $(dir $@)
-	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $< -C -M -c $(POLICYVERS) -o $@ $(PRIVATE_POL_CONF)
-	$(hide) $(HOST_OUT_EXECUTABLES)/build_sepolicy -a $(HOST_OUT_EXECUTABLES) filter_out \
-		-f $(PRIVATE_REQD_MASK) -t $@
-
-
-#####################################################
-intermediates := $(call intermediates-dir-for,ETC,built_system_ext_sepolicy,,,,)
-
-policy_files := $(call build_policy, $(sepolicy_build_files), \
-  $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(SYSTEM_EXT_PUBLIC_POLICY) $(SYSTEM_EXT_PRIVATE_POLICY))
-base_system_ext_policy.conf := $(intermediates)/base_system_ext_policy.conf
-$(base_system_ext_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(base_system_ext_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(base_system_ext_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
-$(base_system_ext_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
-$(base_system_ext_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
-$(base_system_ext_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(base_system_ext_policy.conf): PRIVATE_SEPOLICY_SPLIT := true
-$(base_system_ext_policy.conf): PRIVATE_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY)
-$(base_system_ext_policy.conf): PRIVATE_TREBLE_SYSPROP_NEVERALLOW := $(treble_sysprop_neverallow)
-$(base_system_ext_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
-$(base_system_ext_policy.conf): $(policy_files) $(M4)
-	$(transform-policy-to-conf)
-	$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit
-
-built_system_ext_sepolicy := $(intermediates)/built_system_ext_sepolicy
-$(built_system_ext_sepolicy): PRIVATE_ADDITIONAL_CIL_FILES := \
-  $(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY))
-$(built_system_ext_sepolicy): PRIVATE_NEVERALLOW_ARG := $(NEVERALLOW_ARG)
-$(built_system_ext_sepolicy): $(base_system_ext_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy \
-$(HOST_OUT_EXECUTABLES)/secilc \
-$(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY)) \
-$(built_sepolicy_neverallows)
-	@mkdir -p $(dir $@)
-	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c \
-                $(POLICYVERS) -o $@ $<
-	$(hide) cat $(PRIVATE_ADDITIONAL_CIL_FILES) >> $@
-	$(hide) $(HOST_OUT_EXECUTABLES)/secilc -m -M true -G -c $(POLICYVERS) $(PRIVATE_NEVERALLOW_ARG) $@ -o $@ -f /dev/null
-
-policy_files := $(call build_policy, $(sepolicy_build_files), \
-$(PLAT_PUBLIC_POLICY) $(SYSTEM_EXT_PUBLIC_POLICY) $(REQD_MASK_POLICY))
-base_system_ext_pub_policy.conf := $(intermediates)/base_system_ext_pub_policy.conf
-$(base_system_ext_pub_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(base_system_ext_pub_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(base_system_ext_pub_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
-$(base_system_ext_pub_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
-$(base_system_ext_pub_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
-$(base_system_ext_pub_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(base_system_ext_pub_policy.conf): PRIVATE_SEPOLICY_SPLIT := true
-$(base_system_ext_pub_policy.conf): PRIVATE_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY)
-$(base_system_ext_pub_policy.conf): PRIVATE_TREBLE_SYSPROP_NEVERALLOW := $(treble_sysprop_neverallow)
-$(base_system_ext_pub_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
-$(base_system_ext_pub_policy.conf): $(policy_files) $(M4)
-	$(transform-policy-to-conf)
-
-base_system_ext_pub_policy.cil := $(intermediates)/base_system_ext_pub_policy.cil
-$(base_system_ext_pub_policy.cil): PRIVATE_POL_CONF := $(base_system_ext_pub_policy.conf)
-$(base_system_ext_pub_policy.cil): PRIVATE_REQD_MASK := $(reqd_policy_mask.cil)
-$(base_system_ext_pub_policy.cil): $(HOST_OUT_EXECUTABLES)/checkpolicy \
-$(HOST_OUT_EXECUTABLES)/build_sepolicy $(base_system_ext_pub_policy.conf) $(reqd_policy_mask.cil)
-	@mkdir -p $(dir $@)
-	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $< -C -M -c $(POLICYVERS) -o $@ $(PRIVATE_POL_CONF)
-	$(hide) $(HOST_OUT_EXECUTABLES)/build_sepolicy -a $(HOST_OUT_EXECUTABLES) filter_out \
-		-f $(PRIVATE_REQD_MASK) -t $@
-
-
-################################################################################
-intermediates := $(call intermediates-dir-for,ETC,built_product_sepolicy,,,,)
-
-policy_files := $(call build_policy, $(sepolicy_build_files), \
-  $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(SYSTEM_EXT_PUBLIC_POLICY) $(SYSTEM_EXT_PRIVATE_POLICY) \
-  $(PRODUCT_PUBLIC_POLICY) $(PRODUCT_PRIVATE_POLICY))
-base_product_policy.conf := $(intermediates)/base_product_policy.conf
-$(base_product_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(base_product_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(base_product_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
-$(base_product_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
-$(base_product_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
-$(base_product_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(base_product_policy.conf): PRIVATE_SEPOLICY_SPLIT := true
-$(base_product_policy.conf): PRIVATE_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY)
-$(base_product_policy.conf): PRIVATE_TREBLE_SYSPROP_NEVERALLOW := $(treble_sysprop_neverallow)
-$(base_product_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
-$(base_product_policy.conf): $(policy_files) $(M4)
-	$(transform-policy-to-conf)
-	$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit
-
-built_product_sepolicy := $(intermediates)/built_product_sepolicy
-$(built_product_sepolicy): PRIVATE_ADDITIONAL_CIL_FILES := \
-  $(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY))
-$(built_product_sepolicy): PRIVATE_NEVERALLOW_ARG := $(NEVERALLOW_ARG)
-$(built_product_sepolicy): $(base_product_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy \
-$(HOST_OUT_EXECUTABLES)/secilc \
-$(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY)) \
-$(built_sepolicy_neverallows)
-	@mkdir -p $(dir $@)
-	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c \
-                $(POLICYVERS) -o $@ $<
-	$(hide) cat $(PRIVATE_ADDITIONAL_CIL_FILES) >> $@
-	$(hide) $(HOST_OUT_EXECUTABLES)/secilc -m -M true -G -c $(POLICYVERS) $(PRIVATE_NEVERALLOW_ARG) $@ -o $@ -f /dev/null
-
-
-policy_files := $(call build_policy, $(sepolicy_build_files), \
-$(PLAT_PUBLIC_POLICY) $(SYSTEM_EXT_PUBLIC_POLICY) $(PRODUCT_PUBLIC_POLICY) $(REQD_MASK_POLICY))
-base_product_pub_policy.conf := $(intermediates)/base_product_pub_policy.conf
-$(base_product_pub_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(base_product_pub_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(base_product_pub_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
-$(base_product_pub_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
-$(base_product_pub_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
-$(base_product_pub_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(base_product_pub_policy.conf): PRIVATE_SEPOLICY_SPLIT := true
-$(base_product_pub_policy.conf): PRIVATE_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY)
-$(base_product_pub_policy.conf): PRIVATE_TREBLE_SYSPROP_NEVERALLOW := $(treble_sysprop_neverallow)
-$(base_product_pub_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
-$(base_product_pub_policy.conf): $(policy_files) $(M4)
-	$(transform-policy-to-conf)
-
-base_product_pub_policy.cil := $(intermediates)/base_product_pub_policy.cil
-$(base_product_pub_policy.cil): PRIVATE_POL_CONF := $(base_product_pub_policy.conf)
-$(base_product_pub_policy.cil): PRIVATE_REQD_MASK := $(reqd_policy_mask.cil)
-$(base_product_pub_policy.cil): $(HOST_OUT_EXECUTABLES)/checkpolicy \
-$(HOST_OUT_EXECUTABLES)/build_sepolicy $(base_product_pub_policy.conf) $(reqd_policy_mask.cil)
-	@mkdir -p $(dir $@)
-	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $< -C -M -c $(POLICYVERS) -o $@ $(PRIVATE_POL_CONF)
-	$(hide) $(HOST_OUT_EXECUTABLES)/build_sepolicy -a $(HOST_OUT_EXECUTABLES) filter_out \
-                -f $(PRIVATE_REQD_MASK) -t $@
-
-ifeq ($(PRODUCT_SEPOLICY_SPLIT),true)
 # Tests for Treble compatibility of current platform policy and vendor policy of
 # given release version.
+ifeq ($(PRODUCT_SEPOLICY_SPLIT),true)
+
+built_plat_sepolicy       := $(call intermediates-dir-for,ETC,base_plat_sepolicy)/base_plat_sepolicy
+built_system_ext_sepolicy := $(call intermediates-dir-for,ETC,base_system_ext_sepolicy)/base_system_ext_sepolicy
+built_product_sepolicy    := $(call intermediates-dir-for,ETC,base_product_sepolicy)/base_product_sepolicy
+
+base_plat_pub_policy.cil      := $(call intermediates-dir-for,ETC,base_plat_pub_policy.cil)/base_plat_pub_policy.cil
+base_system_ext_pub_polcy.cil := $(call intermediates-dir-for,ETC,base_system_ext_pub_polcy.cil)/base_system_ext_pub_polcy.cil
+base_product_pub_policy.cil   := $(call intermediates-dir-for,ETC,base_product_pub_policy.cil)/base_product_pub_policy.cil
+
 version_under_treble_tests := 26.0
 include $(LOCAL_PATH)/treble_sepolicy_tests_for_release.mk
 version_under_treble_tests := 27.0
@@ -1524,9 +1343,12 @@
 version_under_treble_tests := 31.0
 include $(LOCAL_PATH)/compat.mk
 
-base_plat_policy.conf :=
-base_plat_pub_policy.conf :=
-plat_sepolicy :=
+built_plat_sepolicy :=
+built_system_ext_sepolicy :=
+built_product_sepolicy :=
+base_plat_pub_policy.cil :=
+base_system_ext_pub_polcy.cil :=
+base_product_pub_policy.cil :=
 all_fc_files :=
 all_fc_args :=
 
@@ -1550,7 +1372,6 @@
 built_sepolicy_neverallows :=
 built_plat_svc :=
 built_vendor_svc :=
-built_plat_sepolicy :=
 treble_sysprop_neverallow :=
 enforce_sysprop_owner :=
 enforce_debugfs_restriction :=
diff --git a/build/soong/policy.go b/build/soong/policy.go
index 604014f..82fabe3 100644
--- a/build/soong/policy.go
+++ b/build/soong/policy.go
@@ -34,6 +34,7 @@
 func init() {
 	android.RegisterModuleType("se_policy_conf", policyConfFactory)
 	android.RegisterModuleType("se_policy_cil", policyCilFactory)
+	android.RegisterModuleType("se_policy_binary", policyBinaryFactory)
 }
 
 type policyConfProperties struct {
@@ -361,3 +362,98 @@
 }
 
 var _ android.OutputFileProducer = (*policyCil)(nil)
+
+type policyBinaryProperties struct {
+	// Name of the output. Default is {module_name}
+	Stem *string
+
+	// Cil files to be compiled.
+	Srcs []string `android:"path"`
+
+	// Whether to ignore neverallow when running secilc check. Defaults to
+	// SELINUX_IGNORE_NEVERALLOWS.
+	Ignore_neverallow *bool
+
+	// Whether this module is directly installable to one of the partitions. Default is true
+	Installable *bool
+}
+
+type policyBinary struct {
+	android.ModuleBase
+
+	properties policyBinaryProperties
+
+	installSource android.Path
+	installPath   android.InstallPath
+}
+
+// se_policy_binary compiles cil files to a binary sepolicy file with secilc.  Usually sources of
+// se_policy_binary come from outputs of se_policy_cil modules.
+func policyBinaryFactory() android.Module {
+	c := &policyBinary{}
+	c.AddProperties(&c.properties)
+	android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
+	return c
+}
+
+func (c *policyBinary) Installable() bool {
+	return proptools.BoolDefault(c.properties.Installable, true)
+}
+
+func (c *policyBinary) stem() string {
+	return proptools.StringDefault(c.properties.Stem, c.Name())
+}
+
+func (c *policyBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if len(c.properties.Srcs) == 0 {
+		ctx.PropertyErrorf("srcs", "must be specified")
+		return
+	}
+	bin := android.PathForModuleOut(ctx, c.stem()).OutputPath
+	rule := android.NewRuleBuilder(pctx, ctx)
+	secilcCmd := rule.Command().BuiltTool("secilc").
+		Flag("-m").                 // Multiple decls
+		FlagWithArg("-M ", "true"). // Enable MLS
+		Flag("-G").                 // expand and remove auto generated attributes
+		FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
+		Inputs(android.PathsForModuleSrc(ctx, c.properties.Srcs)).
+		FlagWithOutput("-o ", bin).
+		FlagWithArg("-f ", os.DevNull)
+
+	if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
+		secilcCmd.Flag("-N")
+	}
+
+	rule.Build("secilc", "Compiling cil files for "+ctx.ModuleName())
+
+	if !c.Installable() {
+		c.SkipInstall()
+	}
+
+	c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
+	c.installSource = bin
+	ctx.InstallFile(c.installPath, c.stem(), c.installSource)
+}
+
+func (c *policyBinary) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
+		OutputFile: android.OptionalPathForPath(c.installSource),
+		Class:      "ETC",
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+				entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
+				entries.SetPath("LOCAL_MODULE_PATH", c.installPath.ToMakePath())
+				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
+			},
+		},
+	}}
+}
+
+func (c *policyBinary) OutputFiles(tag string) (android.Paths, error) {
+	if tag == "" {
+		return android.Paths{c.installSource}, nil
+	}
+	return nil, fmt.Errorf("Unknown tag %q", tag)
+}
+
+var _ android.OutputFileProducer = (*policyBinary)(nil)
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 42909d8..3c82d4b 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -227,24 +227,15 @@
     installable: false,
 }
 
-genrule {
-    name: "microdroid_precompiled_sepolicy_gen",
-    tools: ["secilc"],
+se_policy_binary {
+    name: "microdroid_precompiled_sepolicy",
+    stem: "precompiled_sepolicy",
     srcs: [
         ":microdroid_plat_sepolicy.cil",
         ":microdroid_plat_mapping_file",
         ":microdroid_plat_pub_versioned.cil",
         ":microdroid_vendor_sepolicy.cil",
     ],
-    out: ["precompiled_sepolicy"],
-    cmd: "$(location secilc) -m -M true -G -c 30 $(in) -o $(out) -f /dev/null",
-}
-
-prebuilt_etc {
-    name: "microdroid_precompiled_sepolicy",
-    src: ":microdroid_precompiled_sepolicy_gen",
-    filename: "precompiled_sepolicy",
-    relative_install_path: "selinux",
     installable: false,
 }