diff --git a/private/adbd.te b/private/adbd.te
index 0b42672a35c74c9c73dd9a73c33457b20c83319b..5bbf2dda69c17a7982739f9e0d804f39646c8aa2 100644
--- a/private/adbd.te
+++ b/private/adbd.te
@@ -85,6 +85,9 @@ get_prop(adbd, device_logging_prop)
 # Read device's serial number from system properties
 get_prop(adbd, serialno_prop)
 
+# Read whether or not Test Harness Mode is enabled
+get_prop(adbd, test_harness_prop)
+
 # Read device's overlayfs related properties and files
 userdebug_or_eng(`
   get_prop(adbd, persistent_properties_ready_prop)
diff --git a/private/app.te b/private/app.te
index 876406ffe529664f4c55295a7672902bb954d073..4e433eb58fc0c95c7f803ed4ff28268d1b6124cd 100644
--- a/private/app.te
+++ b/private/app.te
@@ -10,6 +10,10 @@ allow appdomain system_server_tmpfs:file read;
 # info etc.
 allow appdomain priv_app_tmpfs:file read;
 
+# Allow apps to read the Test Harness Mode property. This property is used in
+# the implementation of ActivityManager.isDeviceInTestHarnessMode()
+get_prop(appdomain, test_harness_prop)
+
 neverallow appdomain system_server:udp_socket {
         accept append bind create ioctl listen lock name_bind
         relabelfrom relabelto setattr shutdown };
diff --git a/private/compat/28.0/28.0.ignore.cil b/private/compat/28.0/28.0.ignore.cil
index 23a8a005e1b8adb0e8d00727e4bd3e945d7c4189..4ae2071f343beb9063580e01921b3430ad9e7928 100644
--- a/private/compat/28.0/28.0.ignore.cil
+++ b/private/compat/28.0/28.0.ignore.cil
@@ -90,6 +90,8 @@
     system_lmk_prop
     system_suspend_hwservice
     staging_data_file
+    testharness_service
+    test_harness_prop
     time_prop
     timedetector_service
     timezonedetector_service
diff --git a/private/service_contexts b/private/service_contexts
index 5448183a1deb58917d8540f700ba340a1d2d4f5f..2ad99eb46da183d5c568d69eb7e5abc64f1179e7 100644
--- a/private/service_contexts
+++ b/private/service_contexts
@@ -181,6 +181,7 @@ system_update                             u:object_r:system_update_service:s0
 task                                      u:object_r:task_service:s0
 telecom                                   u:object_r:telecom_service:s0
 telephony.registry                        u:object_r:registry_service:s0
+testharness                               u:object_r:testharness_service:s0
 textclassification                        u:object_r:textclassification_service:s0
 textservices                              u:object_r:textservices_service:s0
 time_detector                             u:object_r:timedetector_service:s0
diff --git a/private/system_server.te b/private/system_server.te
index 0baf4d6f82c29741a446e37f39859279c9afd334..bb69796069c21f7bb90d66b2cc201cfb4e4cca23 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -605,6 +605,9 @@ get_prop(system_server, exported_audio_prop)
 # reset during current boot.
 get_prop(system_server, device_config_reset_performed_prop)
 
+# Read/write the property that enables Test Harness Mode
+set_prop(system_server, test_harness_prop)
+
 # Create a socket for connections from debuggerd.
 allow system_server system_ndebug_socket:sock_file create_file_perms;
 
diff --git a/public/property.te b/public/property.te
index f67a50664c40416c413f43b481934674b7d4883a..91d1a113f15a6f8c95b8e8af819fa45719df61af 100644
--- a/public/property.te
+++ b/public/property.te
@@ -71,6 +71,7 @@ type system_boot_reason_prop, property_type;
 type system_prop, property_type, core_property_type;
 type system_radio_prop, property_type, core_property_type;
 type test_boot_reason_prop, property_type;
+type test_harness_prop, property_type;
 type time_prop, property_type;
 type traced_enabled_prop, property_type;
 type vold_prop, property_type, core_property_type;
@@ -432,6 +433,7 @@ compatible_property_only(`
     -system_prop
     -system_radio_prop
     -test_boot_reason_prop
+    -test_harness_prop
     -time_prop
     -traced_enabled_prop
     -vendor_default_prop
diff --git a/public/property_contexts b/public/property_contexts
index e871b11ca9e8ad5e7ea66ec3a295a55a8dfbef79..2b1b0e97081370fc5c85e1039a81d3596f695a2b 100644
--- a/public/property_contexts
+++ b/public/property_contexts
@@ -188,6 +188,7 @@ libc.debug.malloc.program u:object_r:exported2_default_prop:s0 exact string
 libc.debug.hooks.enable u:object_r:exported2_default_prop:s0 exact string
 persist.sys.locale u:object_r:exported_system_prop:s0 exact string
 persist.sys.timezone u:object_r:exported_system_prop:s0 exact string
+persist.sys.test_harness u:object_r:test_harness_prop:s0 exact bool
 ro.adb.secure u:object_r:exported_secure_prop:s0 exact int
 ro.arch u:object_r:exported2_default_prop:s0 exact string
 ro.audio.ignore_effects u:object_r:exported2_default_prop:s0 exact bool
diff --git a/public/service.te b/public/service.te
index eb5a60849879416574460a9f61cf1ae988ffeb64..21f7648fe59e9870d8b179c89e0fc1585369705a 100644
--- a/public/service.te
+++ b/public/service.te
@@ -157,6 +157,7 @@ type statusbar_service, app_api_service, ephemeral_app_api_service, system_serve
 type storagestats_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
 type system_update_service, system_server_service, service_manager_type;
 type task_service, system_server_service, service_manager_type;
+type testharness_service, system_server_service, service_manager_type;
 type textclassification_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
 type textservices_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
 type telecom_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;