Build mac_permissions.xml with Soong

Bug: 33691272
Test: build and compare
Change-Id: Iacbd5bcf77f0b1c0b5e2c6691efb4c62bc78fdf8
diff --git a/Android.bp b/Android.bp
index 5909f8d..d149c84 100644
--- a/Android.bp
+++ b/Android.bp
@@ -256,6 +256,16 @@
     srcs: ["technical_debt.cil"],
 }
 
+se_build_files {
+    name: "keys.conf",
+    srcs: ["keys.conf"],
+}
+
+se_build_files {
+    name: "mac_permissions.xml",
+    srcs: ["mac_permissions.xml"],
+}
+
 reqd_mask_policy          = [":se_build_files{.reqd_mask}"]
 plat_public_policy        = [":se_build_files{.plat_public}"]
 plat_private_policy       = [":se_build_files{.plat_private}"]
diff --git a/Android.mk b/Android.mk
index 50c265d..21bc6a9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -660,7 +660,6 @@
 file_contexts.modules.tmp :=
 
 ##################################
-include $(LOCAL_PATH)/mac_permissions.mk
 
 all_fc_files := $(TARGET_OUT)/etc/selinux/plat_file_contexts
 all_fc_files += $(TARGET_OUT_VENDOR)/etc/selinux/vendor_file_contexts
diff --git a/build/soong/Android.bp b/build/soong/Android.bp
index d1cead3..99dd662 100644
--- a/build/soong/Android.bp
+++ b/build/soong/Android.bp
@@ -35,6 +35,7 @@
         "build_files.go",
         "cil_compat_map.go",
         "compat_cil.go",
+        "mac_permissions.go",
         "policy.go",
         "selinux.go",
         "selinux_contexts.go",
diff --git a/build/soong/mac_permissions.go b/build/soong/mac_permissions.go
new file mode 100644
index 0000000..9615d12
--- /dev/null
+++ b/build/soong/mac_permissions.go
@@ -0,0 +1,144 @@
+// Copyright (C) 2019 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.
+
+package selinux
+
+import (
+	"fmt"
+	"io"
+
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+)
+
+var (
+	// Should be synced with keys.conf.
+	AllPlatformKeys = []string{
+		"platform",
+		"sdk_sandbox",
+		"media",
+		"networkstack",
+		"shared",
+		"testkey",
+		"bluetooth",
+	}
+)
+
+type macPermissionsProperties struct {
+	// keys.conf files to control the mapping of "tags" found in the mac_permissions.xml files.
+	Keys []string `android:"path"`
+
+	// Source files for the generated mac_permissions.xml file.
+	Srcs []string `android:"path"`
+
+	// Output file name. Defaults to module name
+	Stem *string
+}
+
+type macPermissionsModule struct {
+	android.ModuleBase
+
+	properties  macPermissionsProperties
+	outputPath  android.ModuleOutPath
+	installPath android.InstallPath
+}
+
+func init() {
+	android.RegisterModuleType("mac_permissions", macPermissionsFactory)
+}
+
+func getAllPlatformKeyPaths(ctx android.ModuleContext) android.Paths {
+	var platformKeys android.Paths
+
+	defaultCertificateDir := ctx.Config().DefaultAppCertificateDir(ctx)
+	for _, key := range AllPlatformKeys {
+		platformKeys = append(platformKeys, defaultCertificateDir.Join(ctx, key+".x509.pem"))
+	}
+
+	return platformKeys
+}
+
+func (m *macPermissionsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// do nothing
+}
+
+func (m *macPermissionsModule) stem() string {
+	return proptools.StringDefault(m.properties.Stem, m.Name())
+}
+
+func buildVariant(ctx android.ModuleContext) string {
+	if ctx.Config().Eng() {
+		return "eng"
+	}
+	if ctx.Config().Debuggable() {
+		return "userdebug"
+	}
+	return "user"
+}
+
+func (m *macPermissionsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	platformKeys := getAllPlatformKeyPaths(ctx)
+	keys := android.PathsForModuleSrc(ctx, m.properties.Keys)
+	srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
+
+	m4Keys := android.PathForModuleGen(ctx, "mac_perms_keys.tmp")
+	rule := android.NewRuleBuilder(pctx, ctx)
+	rule.Command().
+		Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
+		Text("--fatal-warnings -s").
+		FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
+		Inputs(keys).
+		FlagWithOutput("> ", m4Keys).
+		Implicits(platformKeys)
+
+	m.outputPath = android.PathForModuleOut(ctx, m.stem())
+	rule.Command().Text("DEFAULT_SYSTEM_DEV_CERTIFICATE="+ctx.Config().DefaultAppCertificateDir(ctx).String()).
+		Text("MAINLINE_SEPOLICY_DEV_CERTIFICATES="+ctx.Config().MainlineSepolicyDevCertificatesDir(ctx).String()).
+		BuiltTool("insertkeys").
+		FlagWithArg("-t ", buildVariant(ctx)).
+		Input(m4Keys).
+		FlagWithOutput("-o ", m.outputPath).
+		Inputs(srcs)
+
+	rule.Build("mac_permission", "build "+m.Name())
+
+	m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
+	ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
+}
+
+func (m *macPermissionsModule) AndroidMk() android.AndroidMkData {
+	return android.AndroidMkData{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(m.outputPath),
+		Extra: []android.AndroidMkExtraFunc{
+			func(w io.Writer, outputFile android.Path) {
+				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String())
+				fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
+			},
+		},
+	}
+}
+
+// mac_permissions module generates a mac_permissions.xml file from given keys.conf and
+// source files. The following variables are supported for keys.conf files.
+//
+//	DEFAULT_SYSTEM_DEV_CERTIFICATE
+//	MAINLINE_SEPOLICY_DEV_CERTIFICATES
+func macPermissionsFactory() android.Module {
+	m := &macPermissionsModule{}
+	m.AddProperties(&m.properties)
+	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+	return m
+}
diff --git a/mac_permissions.mk b/mac_permissions.mk
deleted file mode 100644
index ad17b8f..0000000
--- a/mac_permissions.mk
+++ /dev/null
@@ -1,175 +0,0 @@
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := plat_mac_permissions.xml
-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
-
-all_plat_mac_perms_keys := $(call build_policy, keys.conf, $(PLAT_PRIVATE_POLICY) $(SYSTEM_EXT_PRIVATE_POLICY) $(PRODUCT_PRIVATE_POLICY))
-all_plat_mac_perms_files := $(call build_policy, mac_permissions.xml, $(PLAT_PRIVATE_POLICY))
-
-# Build keys.conf
-plat_mac_perms_keys.tmp := $(intermediates)/plat_keys.tmp
-$(plat_mac_perms_keys.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(plat_mac_perms_keys.tmp): PRIVATE_KEYS := $(all_plat_mac_perms_keys)
-$(plat_mac_perms_keys.tmp): $(all_plat_mac_perms_keys) $(M4)
-	@mkdir -p $(dir $@)
-	$(hide) $(M4) --fatal-warnings -s $(PRIVATE_ADDITIONAL_M4DEFS) $(PRIVATE_KEYS) > $@
-
-# Should be synced with keys.conf.
-all_plat_keys := platform sdk_sandbox media networkstack shared testkey bluetooth
-all_plat_keys := $(all_plat_keys:%=$(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))/%.x509.pem)
-
-$(LOCAL_BUILT_MODULE): PRIVATE_MAC_PERMS_FILES := $(all_plat_mac_perms_files)
-$(LOCAL_BUILT_MODULE): $(plat_mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys \
-$(all_plat_mac_perms_files) $(all_plat_keys)
-	@mkdir -p $(dir $@)
-	$(hide) DEFAULT_SYSTEM_DEV_CERTIFICATE="$(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))" \
-		MAINLINE_SEPOLICY_DEV_CERTIFICATES="$(MAINLINE_SEPOLICY_DEV_CERTIFICATES)" \
-		$(HOST_OUT_EXECUTABLES)/insertkeys -t $(TARGET_BUILD_VARIANT) -c $(TOP) $< -o $@ $(PRIVATE_MAC_PERMS_FILES)
-
-all_plat_keys :=
-all_plat_mac_perms_files :=
-all_plat_mac_perms_keys :=
-plat_mac_perms_keys.tmp :=
-
-##################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := system_ext_mac_permissions.xml
-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
-
-all_system_ext_mac_perms_keys := $(call build_policy, keys.conf, $(SYSTEM_EXT_PRIVATE_POLICY) $(REQD_MASK_POLICY))
-all_system_ext_mac_perms_files := $(call build_policy, mac_permissions.xml, $(SYSTEM_EXT_PRIVATE_POLICY) $(REQD_MASK_POLICY))
-
-# Build keys.conf
-system_ext_mac_perms_keys.tmp := $(intermediates)/system_ext_keys.tmp
-$(system_ext_mac_perms_keys.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(system_ext_mac_perms_keys.tmp): PRIVATE_KEYS := $(all_system_ext_mac_perms_keys)
-$(system_ext_mac_perms_keys.tmp): $(all_system_ext_mac_perms_keys) $(M4)
-	@mkdir -p $(dir $@)
-	$(hide) $(M4) --fatal-warnings -s $(PRIVATE_ADDITIONAL_M4DEFS) $(PRIVATE_KEYS) > $@
-
-$(LOCAL_BUILT_MODULE): PRIVATE_MAC_PERMS_FILES := $(all_system_ext_mac_perms_files)
-$(LOCAL_BUILT_MODULE): $(system_ext_mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys \
-$(all_system_ext_mac_perms_files)
-	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/insertkeys -t $(TARGET_BUILD_VARIANT) -c $(TOP) $< -o $@ $(PRIVATE_MAC_PERMS_FILES)
-
-system_ext_mac_perms_keys.tmp :=
-all_system_ext_mac_perms_files :=
-all_system_ext_mac_perms_keys :=
-
-##################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := product_mac_permissions.xml
-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
-
-all_product_mac_perms_keys := $(call build_policy, keys.conf, $(PRODUCT_PRIVATE_POLICY) $(REQD_MASK_POLICY))
-all_product_mac_perms_files := $(call build_policy, mac_permissions.xml, $(PRODUCT_PRIVATE_POLICY) $(REQD_MASK_POLICY))
-
-# Build keys.conf
-product_mac_perms_keys.tmp := $(intermediates)/product_keys.tmp
-$(product_mac_perms_keys.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(product_mac_perms_keys.tmp): PRIVATE_KEYS := $(all_product_mac_perms_keys)
-$(product_mac_perms_keys.tmp): $(all_product_mac_perms_keys) $(M4)
-	@mkdir -p $(dir $@)
-	$(hide) $(M4) --fatal-warnings -s $(PRIVATE_ADDITIONAL_M4DEFS) $(PRIVATE_KEYS) > $@
-
-$(LOCAL_BUILT_MODULE): PRIVATE_MAC_PERMS_FILES := $(all_product_mac_perms_files)
-$(LOCAL_BUILT_MODULE): $(product_mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys \
-$(all_product_mac_perms_files)
-	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/insertkeys -t $(TARGET_BUILD_VARIANT) -c $(TOP) $< -o $@ $(PRIVATE_MAC_PERMS_FILES)
-
-product_mac_perms_keys.tmp :=
-all_product_mac_perms_files :=
-all_product_mac_perms_keys :=
-
-##################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := vendor_mac_permissions.xml
-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
-
-all_vendor_mac_perms_keys := $(call build_policy, keys.conf, $(BOARD_PLAT_VENDOR_POLICY) $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_REQD_MASK_POLICY))
-all_vendor_mac_perms_files := $(call build_policy, mac_permissions.xml, $(BOARD_PLAT_VENDOR_POLICY) $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_REQD_MASK_POLICY))
-
-# Build keys.conf
-vendor_mac_perms_keys.tmp := $(intermediates)/vendor_keys.tmp
-$(vendor_mac_perms_keys.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(vendor_mac_perms_keys.tmp): PRIVATE_KEYS := $(all_vendor_mac_perms_keys)
-$(vendor_mac_perms_keys.tmp): $(all_vendor_mac_perms_keys) $(M4)
-	@mkdir -p $(dir $@)
-	$(hide) $(M4) --fatal-warnings -s $(PRIVATE_ADDITIONAL_M4DEFS) $(PRIVATE_KEYS) > $@
-
-$(LOCAL_BUILT_MODULE): PRIVATE_MAC_PERMS_FILES := $(all_vendor_mac_perms_files)
-$(LOCAL_BUILT_MODULE): $(vendor_mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys \
-$(all_vendor_mac_perms_files)
-	@mkdir -p $(dir $@)
-	$(hide) DEFAULT_SYSTEM_DEV_CERTIFICATE="$(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))" \
-		$(HOST_OUT_EXECUTABLES)/insertkeys -t $(TARGET_BUILD_VARIANT) -c $(TOP) $< -o $@ $(PRIVATE_MAC_PERMS_FILES)
-
-vendor_mac_perms_keys.tmp :=
-all_vendor_mac_perms_files :=
-all_vendor_mac_perms_keys :=
-
-##################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := odm_mac_permissions.xml
-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
-
-all_odm_mac_perms_keys := $(call build_policy, keys.conf, $(BOARD_ODM_SEPOLICY_DIRS) $(REQD_MASK_POLICY))
-all_odm_mac_perms_files := $(call build_policy, mac_permissions.xml, $(BOARD_ODM_SEPOLICY_DIRS) $(REQD_MASK_POLICY))
-
-# Build keys.conf
-odm_mac_perms_keys.tmp := $(intermediates)/odm_keys.tmp
-$(odm_mac_perms_keys.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(odm_mac_perms_keys.tmp): PRIVATE_KEYS := $(all_odm_mac_perms_keys)
-$(odm_mac_perms_keys.tmp): $(all_odm_mac_perms_keys) $(M4)
-	@mkdir -p $(dir $@)
-	$(hide) $(M4) --fatal-warnings -s $(PRIVATE_ADDITIONAL_M4DEFS) $(PRIVATE_KEYS) > $@
-
-$(LOCAL_BUILT_MODULE): PRIVATE_MAC_PERMS_FILES := $(all_odm_mac_perms_files)
-$(LOCAL_BUILT_MODULE): $(odm_mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys \
-$(all_odm_mac_perms_files)
-	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/insertkeys -t $(TARGET_BUILD_VARIANT) -c $(TOP) $< -o $@ $(PRIVATE_MAC_PERMS_FILES)
-
-odm_mac_perms_keys.tmp :=
-all_odm_mac_perms_files :=
diff --git a/mac_permissions/Android.bp b/mac_permissions/Android.bp
new file mode 100644
index 0000000..02b3587
--- /dev/null
+++ b/mac_permissions/Android.bp
@@ -0,0 +1,79 @@
+// Copyright (C) 2022 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 contains module definitions for mac_permissions.xml files.
+
+mac_permissions {
+    name: "plat_mac_permissions.xml",
+    keys: [
+        ":keys.conf{.plat_private}",
+        ":keys.conf{.system_ext_private}",
+        ":keys.conf{.product_private}",
+    ],
+    srcs: [":mac_permissions.xml{.plat_private}"],
+}
+
+mac_permissions {
+    name: "system_ext_mac_permissions.xml",
+    keys: [
+        ":keys.conf{.system_ext_private}",
+        ":keys.conf{.reqd_mask}",
+    ],
+    srcs: [
+        ":mac_permissions.xml{.system_ext_private}",
+        ":mac_permissions.xml{.reqd_mask}",
+    ],
+    system_ext_specific: true,
+}
+
+mac_permissions {
+    name: "product_mac_permissions.xml",
+    keys: [
+        ":keys.conf{.product_private}",
+        ":keys.conf{.reqd_mask}",
+    ],
+    srcs: [
+        ":mac_permissions.xml{.product_private}",
+        ":mac_permissions.xml{.reqd_mask}",
+    ],
+    product_specific: true,
+}
+
+mac_permissions {
+    name: "vendor_mac_permissions.xml",
+    keys: [
+        ":keys.conf{.plat_vendor_for_vendor}",
+        ":keys.conf{.vendor}",
+        ":keys.conf{.reqd_mask_for_vendor}",
+    ],
+    srcs: [
+        ":mac_permissions.xml{.plat_vendor_for_vendor}",
+        ":mac_permissions.xml{.vendor}",
+        ":mac_permissions.xml{.reqd_mask_for_vendor}",
+    ],
+    vendor: true,
+}
+
+mac_permissions {
+    name: "odm_mac_permissions.xml",
+    keys: [
+        ":keys.conf{.odm}",
+        ":keys.conf{.reqd_mask_for_vendor}",
+    ],
+    srcs: [
+        ":mac_permissions.xml{.odm}",
+        ":mac_permissions.xml{.reqd_mask_for_vendor}",
+    ],
+    device_specific: true,
+}