Merge changes I3a6f9db9,Ifb4453d0,I33d88b42 into main

* changes:
  Refactor contextsTestModule
  Fix private/file_contexts entry order
  checkfc: validate that all rules are matching
diff --git a/build/soong/selinux_contexts.go b/build/soong/selinux_contexts.go
index a7a2436..47a63d0 100644
--- a/build/soong/selinux_contexts.go
+++ b/build/soong/selinux_contexts.go
@@ -520,16 +520,23 @@
 type contextsTestModule struct {
 	android.ModuleBase
 
-	// Name of the test tool. "checkfc" or "property_info_checker"
-	tool string
-
-	// Additional flags to be passed to the tool.
-	flags []string
+	// The type of context.
+	context contextType
 
 	properties    contextsTestProperties
 	testTimestamp android.OutputPath
 }
 
+type contextType int
+
+const (
+	FileContext contextType = iota
+	PropertyContext
+	ServiceContext
+	HwServiceContext
+	VndServiceContext
+)
+
 // checkfc parses a context file and checks for syntax errors.
 // If -s is specified, the service backend is used to verify binder services.
 // If -l is specified, the service backend is used to verify hwbinder services.
@@ -538,7 +545,7 @@
 
 // file_contexts_test tests given file_contexts files with checkfc.
 func fileContextsTestFactory() android.Module {
-	m := &contextsTestModule{tool: "checkfc" /* no flags: file_contexts file check */}
+	m := &contextsTestModule{context: FileContext}
 	m.AddProperties(&m.properties)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
@@ -546,7 +553,7 @@
 
 // property_contexts_test tests given property_contexts files with property_info_checker.
 func propertyContextsTestFactory() android.Module {
-	m := &contextsTestModule{tool: "property_info_checker"}
+	m := &contextsTestModule{context: PropertyContext}
 	m.AddProperties(&m.properties)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
@@ -554,7 +561,7 @@
 
 // hwservice_contexts_test tests given hwservice_contexts files with checkfc.
 func hwserviceContextsTestFactory() android.Module {
-	m := &contextsTestModule{tool: "checkfc", flags: []string{"-e" /* allow empty */, "-l" /* hwbinder services */}}
+	m := &contextsTestModule{context: HwServiceContext}
 	m.AddProperties(&m.properties)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
@@ -563,7 +570,7 @@
 // service_contexts_test tests given service_contexts files with checkfc.
 func serviceContextsTestFactory() android.Module {
 	// checkfc -s: service_contexts test
-	m := &contextsTestModule{tool: "checkfc", flags: []string{"-s" /* binder services */}}
+	m := &contextsTestModule{context: ServiceContext}
 	m.AddProperties(&m.properties)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
@@ -571,16 +578,16 @@
 
 // vndservice_contexts_test tests given vndservice_contexts files with checkfc.
 func vndServiceContextsTestFactory() android.Module {
-	m := &contextsTestModule{tool: "checkfc", flags: []string{"-e" /* allow empty */, "-v" /* vnd service */}}
+	m := &contextsTestModule{context: VndServiceContext}
 	m.AddProperties(&m.properties)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
 }
 
 func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	tool := m.tool
-	if tool != "checkfc" && tool != "property_info_checker" {
-		panic(fmt.Errorf("%q: unknown tool name: %q", ctx.ModuleName(), tool))
+	tool := "checkfc"
+	if m.context == PropertyContext {
+		tool = "property_info_checker"
 	}
 
 	if len(m.properties.Srcs) == 0 {
@@ -593,12 +600,22 @@
 		return
 	}
 
+	flags := []string(nil)
+	switch m.context {
+	case ServiceContext:
+		flags = []string{"-s" /* binder services */}
+	case HwServiceContext:
+		flags = []string{"-e" /* allow empty */, "-l" /* hwbinder services */}
+	case VndServiceContext:
+		flags = []string{"-e" /* allow empty */, "-v" /* vnd service */}
+	}
+
 	srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
 	sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 	rule.Command().BuiltTool(tool).
-		Flags(m.flags).
+		Flags(flags).
 		Input(sepolicy).
 		Inputs(srcs)
 
diff --git a/tests/plat_file_contexts_test b/contexts/plat_file_contexts_test
similarity index 99%
rename from tests/plat_file_contexts_test
rename to contexts/plat_file_contexts_test
index 9d8d906..e707a75 100644
--- a/tests/plat_file_contexts_test
+++ b/contexts/plat_file_contexts_test
@@ -209,6 +209,7 @@
 /dev/socket/pdx/system/vr/display/vsync                           pdx_display_vsync_endpoint_socket
 /dev/socket/prng_seeder                                           prng_seeder_socket
 /dev/socket/property_service                                      property_socket
+/dev/socket/property_service_for_system                           property_socket
 /dev/socket/racoon                                                racoon_socket
 /dev/socket/recovery                                              recovery_socket
 /dev/socket/rild                                                  rild_socket
@@ -419,6 +420,7 @@
 /system/bin/profcollectd                                          profcollectd_exec
 /system/bin/profcollectctl                                        profcollectd_exec
 /system/bin/storaged                                              storaged_exec
+/system/bin/virtual_camera                                        virtual_camera_exec
 /system/bin/virtual_touchpad                                      virtual_touchpad_exec
 /system/bin/hw/android.frameworks.bufferhub@1.0-service           fwk_bufferhub_exec
 /system/bin/hw/android.system.suspend-service                     system_suspend_exec
diff --git a/private/file_contexts b/private/file_contexts
index 600c2b8..2d9b30d 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -561,7 +561,6 @@
 /data/gsi_persistent_data    u:object_r:gsi_persistent_data_file:s0
 /data/gsi/ota(/.*)?    u:object_r:ota_image_data_file:s0
 /data/tombstones(/.*)?	u:object_r:tombstone_data_file:s0
-/data/vendor/tombstones/wifi(/.*)? u:object_r:tombstone_wifi_data_file:s0
 /data/local/tests(/.*)?	u:object_r:shell_test_data_file:s0
 /data/local/tmp(/.*)?	u:object_r:shell_data_file:s0
 /data/local/tmp/ltp(/.*)?   u:object_r:nativetest_data_file:s0
@@ -636,8 +635,8 @@
 /data/misc/odrefresh(/.*)?      u:object_r:odrefresh_data_file:s0
 /data/misc/odsign(/.*)?         u:object_r:odsign_data_file:s0
 /data/misc/odsign/metrics(/.*)? u:object_r:odsign_metrics_file:s0
-/data/misc/perfetto-traces/bugreport(.*)? u:object_r:perfetto_traces_bugreport_data_file:s0
 /data/misc/perfetto-traces(/.*)?          u:object_r:perfetto_traces_data_file:s0
+/data/misc/perfetto-traces/bugreport(.*)? u:object_r:perfetto_traces_bugreport_data_file:s0
 /data/misc/perfetto-configs(/.*)?         u:object_r:perfetto_configs_data_file:s0
 /data/misc/prereboot(/.*)?      u:object_r:prereboot_data_file:s0
 /data/misc/profcollectd(/.*)?   u:object_r:profcollectd_data_file:s0
@@ -680,6 +679,7 @@
 /data/vendor_ce/.*              u:object_r:vendor_data_file:s0
 /data/vendor_de                 u:object_r:vendor_userdir_file:s0
 /data/vendor_de/.*              u:object_r:vendor_data_file:s0
+/data/vendor/tombstones/wifi(/.*)? u:object_r:tombstone_wifi_data_file:s0
 
 # storaged proto files
 /data/misc_de/[0-9]+/storaged(/.*)?       u:object_r:storaged_data_file:s0
diff --git a/tools/checkfc.c b/tools/checkfc.c
index 05826f9..051e24b 100644
--- a/tools/checkfc.c
+++ b/tools/checkfc.c
@@ -271,6 +271,19 @@
      printf("%s\n", result_str[result]);
 }
 
+static int warnings = 0;
+static int log_callback(int type, const char *fmt, ...) {
+    va_list ap;
+
+    if (type == SELINUX_WARNING) {
+        warnings += 1;
+    }
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    return 0;
+}
+
 static void do_test_data_and_die_on_error(struct selinux_opt opts[], unsigned int backend,
         char *paths[])
 {
@@ -329,7 +342,15 @@
 
     // Prints the coverage of file_contexts on the test data. It includes
     // warnings for rules that have not been hit by any test example.
+    union selinux_callback cb;
+    cb.func_log = log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
     selabel_stats(global_state.sepolicy.sehnd[0]);
+    if (warnings) {
+        fprintf(stderr, "No test entries were found for the contexts above. " \
+                        "You may need to update %s.\n", paths[1]);
+        exit(1);
+    }
 }
 
 static void do_fc_check_and_die_on_error(struct selinux_opt opts[], unsigned int backend, filemode mode,