diff --git a/domain.te b/domain.te
index 59f49f2deb29da18cf7390bb77915d08963fa10f..1b81ed2eed44602afcf2850cd43de34bf1f53e63 100644
--- a/domain.te
+++ b/domain.te
@@ -378,6 +378,7 @@ neverallow {
   -postinstall_dexopt
   -cppreopts
   -dex2oat
+  -otapreopt_slot
 } dalvikcache_data_file:file no_w_file_perms;
 
 neverallow {
@@ -388,6 +389,7 @@ neverallow {
   -cppreopts
   -dex2oat
   -zygote
+  -otapreopt_slot
 } dalvikcache_data_file:dir no_w_dir_perms;
 
 # Only system_server should be able to send commands via the zygote socket
diff --git a/file_contexts b/file_contexts
index 3f1468eb86511083d85c4c5c7f59f2a201cc56ef..3d91e2b254b2db9d4531dcaede19fbfdb4a967d3 100644
--- a/file_contexts
+++ b/file_contexts
@@ -175,6 +175,7 @@
 /system/bin/mdnsd	u:object_r:mdnsd_exec:s0
 /system/bin/installd	u:object_r:installd_exec:s0
 /system/bin/otapreopt_chroot   u:object_r:otapreopt_chroot_exec:s0
+/system/bin/otapreopt_slot   u:object_r:otapreopt_slot_exec:s0
 /system/bin/keystore	u:object_r:keystore_exec:s0
 /system/bin/fingerprintd u:object_r:fingerprintd_exec:s0
 /system/bin/gatekeeperd u:object_r:gatekeeperd_exec:s0
diff --git a/otapreopt_slot.te b/otapreopt_slot.te
new file mode 100644
index 0000000000000000000000000000000000000000..b68b399d72da09f4f03377f0f502b2e094da9c87
--- /dev/null
+++ b/otapreopt_slot.te
@@ -0,0 +1,27 @@
+# otapreopt_slot
+#
+# This command set moves the artifact corresponding to the current slot
+# from /data/ota to /data/dalvik-cache.
+
+type otapreopt_slot, domain, mlstrustedsubject;
+type otapreopt_slot_exec, exec_type, file_type;
+
+# Technically not a daemon but we do want the transition from init domain to
+# cppreopts to occur.
+init_daemon_domain(otapreopt_slot)
+
+# The otapreopt_slot renames the OTA dalvik-cache to the regular dalvik-cache, and cleans up
+# the directory afterwards.
+allow otapreopt_slot ota_data_file:dir { rw_dir_perms rename reparent rmdir };
+
+# Delete old content of the dalvik-cache.
+allow otapreopt_slot dalvikcache_data_file:dir { add_name getattr open read remove_name rmdir search write };
+allow otapreopt_slot dalvikcache_data_file:file { getattr unlink };
+allow otapreopt_slot dalvikcache_data_file:lnk_file { getattr read unlink };
+
+# Allow cppreopts to execute itself using #!/system/bin/sh
+allow otapreopt_slot shell_exec:file rx_file_perms;
+
+# Allow running the mv and rm/rmdir commands using otapreopt_slot  permissions.
+# Needed so we can move artifacts into /data/dalvik-cache/dalvik-cache.
+allow otapreopt_slot toolbox_exec:file rx_file_perms;
diff --git a/zygote.te b/zygote.te
index 89dccfcf7bac6d4e68556ba0a22a46f2d73abb92..d8be1c01f14a431257e3b8a1891165af79acd94e 100644
--- a/zygote.te
+++ b/zygote.te
@@ -81,31 +81,6 @@ userdebug_or_eng(`
   allow zygote method_trace_data_file:file { create w_file_perms };
 ')
 
-###
-### A/B OTA
-###
-
-# The zygote is responsible for detecting A/B OTA artifacts and moving them into
-# the actual dalvik-cache.
-
-# Allow zygote access to files in /data/ota.
-# This includes reading symlinks in /data/ota/dalvik-cache. This is required for PIC mode boot
-# images, where the oat file is symlinked to the original file in /system.
-r_dir_file(zygote, ota_data_file)
-
-# The zygote renames the OTA dalvik-cache to the regular dalvik-cache.
-allow zygote ota_data_file:dir { rw_dir_perms rename reparent };
-
-# And needs to relabel the entries, so as to have the dalvikcache_data_file label.
-allow zygote ota_data_file:{ dir file lnk_file } relabelfrom;
-allow zygote dalvikcache_data_file:{ dir file lnk_file } relabelto;
-
-# The zygote also cleans up the now-empty dalvik-cache directory after an OTA.
-# In case something goes wrong in relabelling, we also need to be able to delete the files that
-# have already been moved.
-allow zygote ota_data_file:dir rmdir;
-allow zygote ota_data_file:{ file lnk_file } unlink;
-
 ###
 ### neverallow rules
 ###