Merge "Allow bpfloader to read fuse's bpf_prog number"
diff --git a/Android.bp b/Android.bp
index b9c5808..a353831 100644
--- a/Android.bp
+++ b/Android.bp
@@ -494,8 +494,26 @@
     flatten_apex: {
         srcs: ["apex/*-file_contexts"],
     },
+}
 
-    recovery_available: true,
+file_contexts {
+    name: "plat_file_contexts.recovery",
+    srcs: [":file_contexts_files"],
+    stem: "plat_file_contexts",
+    product_variables: {
+        address_sanitize: {
+            srcs: [":file_contexts_asan_files"],
+        },
+        debuggable: {
+            srcs: [":file_contexts_overlayfs_files"],
+        },
+    },
+
+    flatten_apex: {
+        srcs: ["apex/*-file_contexts"],
+    },
+
+    recovery: true,
 }
 
 file_contexts {
@@ -559,7 +577,13 @@
 property_contexts {
     name: "plat_property_contexts",
     srcs: [":property_contexts_files"],
-    recovery_available: true,
+}
+
+property_contexts {
+    name: "plat_property_contexts.recovery",
+    srcs: [":property_contexts_files"],
+    stem: "plat_property_contexts",
+    recovery: true,
 }
 
 property_contexts {
@@ -594,7 +618,13 @@
 service_contexts {
     name: "plat_service_contexts",
     srcs: [":service_contexts_files"],
-    recovery_available: true,
+}
+
+service_contexts {
+    name: "plat_service_contexts.recovery",
+    srcs: [":service_contexts_files"],
+    stem: "plat_service_contexts",
+    recovery: true,
 }
 
 service_contexts {
@@ -1195,3 +1225,17 @@
 se_freeze_test {
     name: "sepolicy_freeze_test",
 }
+
+//////////////////////////////////
+// Makefile rules temporary imported to Soong
+// TODO(b/33691272): remove these after migrating seapp to Soong
+//////////////////////////////////
+makefile_goal {
+    name: "plat_seapp_contexts_rule",
+    product_out_path: "obj/ETC/plat_seapp_contexts_intermediates/plat_seapp_contexts",
+}
+
+makefile_goal {
+    name: "plat_seapp_neverallows_rule",
+    product_out_path: "obj/ETC/plat_seapp_neverallows_intermediates/plat_seapp_neverallows",
+}
diff --git a/build/soong/selinux_contexts.go b/build/soong/selinux_contexts.go
index 5859fc1..fefdd45 100644
--- a/build/soong/selinux_contexts.go
+++ b/build/soong/selinux_contexts.go
@@ -30,6 +30,9 @@
 	// Filenames under sepolicy directories, which will be used to generate contexts file.
 	Srcs []string `android:"path"`
 
+	// Output file name. Defaults to module name
+	Stem *string
+
 	Product_variables struct {
 		Debuggable struct {
 			Srcs []string
@@ -120,6 +123,10 @@
 	}
 }
 
+func (m *selinuxContextsModule) stem() string {
+	return proptools.StringDefault(m.properties.Stem, m.Name())
+}
+
 func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	if m.InRecovery() {
 		// Installing context files at the root of the recovery partition
@@ -133,7 +140,7 @@
 
 		if reuseDeps, ok := dep.(*selinuxContextsModule); ok {
 			m.outputPath = reuseDeps.outputPath
-			ctx.InstallFile(m.installPath, m.Name(), m.outputPath)
+			ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
 			return
 		}
 	}
@@ -185,7 +192,7 @@
 	}
 
 	m.outputPath = m.build(ctx, inputs)
-	ctx.InstallFile(m.installPath, ctx.ModuleName(), m.outputPath)
+	ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
 }
 
 func newModule() *selinuxContextsModule {
@@ -230,21 +237,21 @@
 		Extra: []android.AndroidMkExtraFunc{
 			func(w io.Writer, outputFile android.Path) {
 				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.ToMakePath().String())
-				fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.Name())
+				fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
 			},
 		},
 	}
 }
 
 func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
-	if proptools.Bool(m.properties.Recovery_available) && m.InstallInRecovery() {
+	if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() {
 		ctx.PropertyErrorf("recovery_available",
 			"doesn't make sense at the same time as `recovery: true`")
 	}
 }
 
 func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
-	return !m.InstallInRecovery()
+	return !m.ModuleBase.InstallInRecovery()
 }
 
 func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -260,7 +267,7 @@
 }
 
 func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
-	return m.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
+	return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
 }
 
 func (m *selinuxContextsModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
@@ -273,7 +280,7 @@
 var _ android.ImageInterface = (*selinuxContextsModule)(nil)
 
 func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
-	ret := android.PathForModuleGen(ctx, ctx.ModuleName()+"_m4out")
+	builtContext := android.PathForModuleGen(ctx, ctx.ModuleName()+"_m4out")
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 
@@ -282,37 +289,40 @@
 		Text("--fatal-warnings -s").
 		FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
 		Inputs(inputs).
-		FlagWithOutput("> ", ret)
+		FlagWithOutput("> ", builtContext)
 
 	if proptools.Bool(m.properties.Remove_comment) {
-		rule.Temporary(ret)
+		rule.Temporary(builtContext)
 
 		remove_comment_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_remove_comment")
 
 		rule.Command().
 			Text("sed -e 's/#.*$//' -e '/^$/d'").
-			Input(ret).
+			Input(builtContext).
 			FlagWithOutput("> ", remove_comment_output)
 
-		ret = remove_comment_output
+		builtContext = remove_comment_output
 	}
 
 	if proptools.Bool(m.properties.Fc_sort) {
-		rule.Temporary(ret)
+		rule.Temporary(builtContext)
 
 		sorted_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_sorted")
 
 		rule.Command().
 			Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
-			FlagWithInput("-i ", ret).
+			FlagWithInput("-i ", builtContext).
 			FlagWithOutput("-o ", sorted_output)
 
-		ret = sorted_output
+		builtContext = sorted_output
 	}
 
-	rule.Build("selinux_contexts", "building contexts: "+m.Name())
+	ret := android.PathForModuleGen(ctx, m.stem())
+	rule.Temporary(builtContext)
+	rule.Command().Text("cp").Input(builtContext).Output(ret)
 
 	rule.DeleteTemporaryFiles()
+	rule.Build("selinux_contexts", "building contexts: "+m.Name())
 
 	return ret
 }
@@ -500,3 +510,13 @@
 	m.build = m.buildGeneralContexts
 	return m
 }
+
+var _ android.OutputFileProducer = (*selinuxContextsModule)(nil)
+
+// Implements android.OutputFileProducer
+func (m *selinuxContextsModule) OutputFiles(tag string) (android.Paths, error) {
+	if tag == "" {
+		return []android.Path{m.outputPath}, nil
+	}
+	return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+}
diff --git a/prebuilts/api/31.0/plat_pub_versioned.cil b/prebuilts/api/31.0/plat_pub_versioned.cil
index 3f2c0be..9a086c5 100644
--- a/prebuilts/api/31.0/plat_pub_versioned.cil
+++ b/prebuilts/api/31.0/plat_pub_versioned.cil
@@ -138,6 +138,7 @@
 (type cache_private_backup_file)
 (type cache_recovery_file)
 (type cacheinfo_service)
+(type camera2_extensions_prop)
 (type camera_calibration_prop)
 (type camera_config_prop)
 (type camera_data_file)
@@ -518,6 +519,7 @@
 (type keystore_data_file)
 (type keystore_exec)
 (type keystore_maintenance_service)
+(type keystore_metrics_service)
 (type keystore_service)
 (type kmsg_debug_device)
 (type kmsg_device)
@@ -785,6 +787,7 @@
 (type proc_uid_procstat_set)
 (type proc_uid_time_in_state)
 (type proc_uptime)
+(type proc_vendor_sched)
 (type proc_version)
 (type proc_vmallocinfo)
 (type proc_vmstat)
@@ -943,6 +946,7 @@
 (type sysfs)
 (type sysfs_android_usb)
 (type sysfs_batteryinfo)
+(type sysfs_block)
 (type sysfs_bluetooth_writable)
 (type sysfs_devfreq_cur)
 (type sysfs_devfreq_dir)
@@ -978,6 +982,7 @@
 (type sysfs_uio)
 (type sysfs_usb)
 (type sysfs_usermodehelper)
+(type sysfs_vendor_sched)
 (type sysfs_vibrator)
 (type sysfs_wake_lock)
 (type sysfs_wakeup)
@@ -1797,6 +1802,9 @@
 (typeattribute base_typeattr_534_31_0)
 (typeattribute base_typeattr_535_31_0)
 (typeattribute base_typeattr_536_31_0)
+(typeattribute base_typeattr_537_31_0)
+(typeattribute base_typeattr_538_31_0)
+(typeattribute base_typeattr_539_31_0)
 (typeattribute base_typeattr_53_31_0)
 (typeattribute base_typeattr_54_31_0)
 (typeattribute base_typeattr_55_31_0)
@@ -1852,6 +1860,7 @@
 (typeattribute battery_service_31_0)
 (typeattribute batteryproperties_service_31_0)
 (typeattribute batterystats_service_31_0)
+(typeattribute bdev_type)
 (typeattribute binder_cache_bluetooth_server_prop_31_0)
 (typeattribute binder_cache_system_server_prop_31_0)
 (typeattribute binder_cache_telephony_server_prop_31_0)
@@ -1910,6 +1919,7 @@
 (typeattribute cache_private_backup_file_31_0)
 (typeattribute cache_recovery_file_31_0)
 (typeattribute cacheinfo_service_31_0)
+(typeattribute camera2_extensions_prop_31_0)
 (typeattribute camera_calibration_prop_31_0)
 (typeattribute camera_config_prop_31_0)
 (typeattribute camera_data_file_31_0)
@@ -2381,6 +2391,9 @@
 (typeattribute hal_usb_gadget_server)
 (typeattribute hal_usb_hwservice_31_0)
 (typeattribute hal_usb_server)
+(typeattribute hal_uwb)
+(typeattribute hal_uwb_client)
+(typeattribute hal_uwb_server)
 (typeattribute hal_vehicle)
 (typeattribute hal_vehicle_client)
 (typeattribute hal_vehicle_hwservice_31_0)
@@ -2496,6 +2509,7 @@
 (typeattribute keystore_data_file_31_0)
 (typeattribute keystore_exec_31_0)
 (typeattribute keystore_maintenance_service_31_0)
+(typeattribute keystore_metrics_service_31_0)
 (typeattribute keystore_service_31_0)
 (typeattribute kmsg_debug_device_31_0)
 (typeattribute kmsg_device_31_0)
@@ -2799,6 +2813,7 @@
 (typeattribute proc_uid_procstat_set_31_0)
 (typeattribute proc_uid_time_in_state_31_0)
 (typeattribute proc_uptime_31_0)
+(typeattribute proc_vendor_sched_31_0)
 (typeattribute proc_version_31_0)
 (typeattribute proc_vmallocinfo_31_0)
 (typeattribute proc_vmstat_31_0)
@@ -2968,6 +2983,8 @@
 (typeattribute sysfs_31_0)
 (typeattribute sysfs_android_usb_31_0)
 (typeattribute sysfs_batteryinfo_31_0)
+(typeattribute sysfs_block_31_0)
+(typeattribute sysfs_block_type)
 (typeattribute sysfs_bluetooth_writable_31_0)
 (typeattribute sysfs_devfreq_cur_31_0)
 (typeattribute sysfs_devfreq_dir_31_0)
@@ -3004,6 +3021,7 @@
 (typeattribute sysfs_uio_31_0)
 (typeattribute sysfs_usb_31_0)
 (typeattribute sysfs_usermodehelper_31_0)
+(typeattribute sysfs_vendor_sched_31_0)
 (typeattribute sysfs_vibrator_31_0)
 (typeattribute sysfs_wake_lock_31_0)
 (typeattribute sysfs_wakeup_31_0)
diff --git a/prebuilts/api/31.0/private/apexd.te b/prebuilts/api/31.0/private/apexd.te
index d43ed33..09799bd 100644
--- a/prebuilts/api/31.0/private/apexd.te
+++ b/prebuilts/api/31.0/private/apexd.te
@@ -86,7 +86,6 @@
 allow apexd apex_info_file:file relabelto;
 # apexd needs to update /apex/apex-info-list.xml after non-staged APEX update.
 allow apexd apex_info_file:file rw_file_perms;
-allow apexd apex_info_file:file mounton;
 
 # allow apexd to unlink apex files in /data/apex/active
 # note that apexd won't be able to unlink files in /data/app-staging/session_XXXX,
diff --git a/prebuilts/api/31.0/private/bpfloader.te b/prebuilts/api/31.0/private/bpfloader.te
index ae9b52c..343ec7a 100644
--- a/prebuilts/api/31.0/private/bpfloader.te
+++ b/prebuilts/api/31.0/private/bpfloader.te
@@ -27,13 +27,13 @@
 # TODO: get rid of init & vendor_init
 neverallow { domain -bpfloader -init -vendor_init } { fs_bpf fs_bpf_tethering }:file { map open setattr };
 neverallow { domain -bpfloader } { fs_bpf fs_bpf_tethering }:file create;
-neverallow { domain -bpfloader -gpuservice -init -netd -netutils_wrapper -network_stack -system_server -vendor_init } { fs_bpf fs_bpf_tethering }:file read;
+neverallow { domain -bpfloader -gpuservice -init -lmkd -netd -netutils_wrapper -network_stack -system_server -vendor_init } { fs_bpf fs_bpf_tethering }:file read;
 neverallow { domain -bpfloader -gpuservice -netd -netutils_wrapper -network_stack -system_server } { fs_bpf fs_bpf_tethering }:file write;
 neverallow domain { fs_bpf fs_bpf_tethering }:file ~{ create map open read setattr write };
 
 neverallow { domain -bpfloader } *:bpf { map_create prog_load };
 neverallow { domain -bpfloader -gpuservice -netd -netutils_wrapper -network_stack -system_server } *:bpf prog_run;
-neverallow { domain -bpfloader -gpuservice -netd -network_stack -system_server } *:bpf { map_read map_write };
+neverallow { domain -bpfloader -gpuservice -lmkd -netd -network_stack -system_server } *:bpf { map_read map_write };
 
 neverallow { domain -bpfloader -init } bpfloader_exec:file { execute execute_no_trans };
 
diff --git a/prebuilts/api/31.0/private/bug_map b/prebuilts/api/31.0/private/bug_map
index de7a4b5..5b042ae 100644
--- a/prebuilts/api/31.0/private/bug_map
+++ b/prebuilts/api/31.0/private/bug_map
@@ -25,7 +25,6 @@
 netd untrusted_app_27 unix_stream_socket b/77870037
 netd untrusted_app_29 unix_stream_socket b/77870037
 platform_app nfc_data_file dir b/74331887
-system_server apex_art_data_file file b/194054685
 system_server crash_dump process b/73128755
 system_server overlayfs_file file b/142390309
 system_server sdcardfs file b/77856826
diff --git a/prebuilts/api/31.0/private/compat/30.0/30.0.ignore.cil b/prebuilts/api/31.0/private/compat/30.0/30.0.ignore.cil
index ce2d58e..0c36aed 100644
--- a/prebuilts/api/31.0/private/compat/30.0/30.0.ignore.cil
+++ b/prebuilts/api/31.0/private/compat/30.0/30.0.ignore.cil
@@ -20,6 +20,7 @@
     arm64_memtag_prop
     authorization_service
     bootanim_config_prop
+    camera2_extensions_prop
     camerax_extensions_prop
     cgroup_desc_api_file
     cgroup_v2
@@ -148,4 +149,6 @@
     vpn_management_service
     watchdog_metadata_file
     wifi_key
-    zygote_config_prop))
+    zygote_config_prop
+    proc_vendor_sched
+    sysfs_vendor_sched))
diff --git a/prebuilts/api/31.0/private/genfs_contexts b/prebuilts/api/31.0/private/genfs_contexts
index 4644503..13bfb46 100644
--- a/prebuilts/api/31.0/private/genfs_contexts
+++ b/prebuilts/api/31.0/private/genfs_contexts
@@ -103,6 +103,7 @@
 genfscon proc /vmallocinfo u:object_r:proc_vmallocinfo:s0
 genfscon proc /vmstat u:object_r:proc_vmstat:s0
 genfscon proc /zoneinfo u:object_r:proc_zoneinfo:s0
+genfscon proc /vendor_sched u:object_r:proc_vendor_sched:s0
 
 genfscon fusectl / u:object_r:fusectlfs:s0
 
@@ -165,6 +166,7 @@
 genfscon sysfs /module/wlan/parameters/fwpath u:object_r:sysfs_wlan_fwpath:s0
 genfscon sysfs /devices/virtual/timed_output/vibrator/enable u:object_r:sysfs_vibrator:s0
 genfscon sysfs /devices/virtual/misc/uhid u:object_r:sysfs_uhid:s0
+genfscon sysfs /kernel/vendor_sched u:object_r:sysfs_vendor_sched:s0
 
 genfscon debugfs /kprobes                             u:object_r:debugfs_kprobes:s0
 genfscon debugfs /mmc0                                u:object_r:debugfs_mmc:s0
diff --git a/prebuilts/api/31.0/private/lmkd.te b/prebuilts/api/31.0/private/lmkd.te
index fef3a89..ec9a93e 100644
--- a/prebuilts/api/31.0/private/lmkd.te
+++ b/prebuilts/api/31.0/private/lmkd.te
@@ -8,4 +8,8 @@
 # Set lmkd.* properties.
 set_prop(lmkd, lmkd_prop)
 
+allow lmkd fs_bpf:dir search;
+allow lmkd fs_bpf:file read;
+allow lmkd bpfloader:bpf map_read;
+
 neverallow { domain -init -lmkd -vendor_init } lmkd_prop:property_service set;
diff --git a/prebuilts/api/31.0/private/property_contexts b/prebuilts/api/31.0/private/property_contexts
index 016f0b6..e0700fe 100644
--- a/prebuilts/api/31.0/private/property_contexts
+++ b/prebuilts/api/31.0/private/property_contexts
@@ -335,6 +335,9 @@
 
 ro.camerax.extensions.enabled u:object_r:camerax_extensions_prop:s0 exact bool
 
+ro.vendor.camera.extensions.package u:object_r:camera2_extensions_prop:s0 exact string
+ro.vendor.camera.extensions.service u:object_r:camera2_extensions_prop:s0 exact string
+
 # ART properties
 dalvik.vm.                 u:object_r:dalvik_config_prop:s0
 ro.dalvik.vm.              u:object_r:dalvik_config_prop:s0
@@ -515,6 +518,7 @@
 ro.lmk.critical_upgrade         u:object_r:lmkd_config_prop:s0 exact bool
 ro.lmk.debug                    u:object_r:lmkd_config_prop:s0 exact bool
 ro.lmk.downgrade_pressure       u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.filecache_min_kb         u:object_r:lmkd_config_prop:s0 exact int
 ro.lmk.kill_heaviest_task       u:object_r:lmkd_config_prop:s0 exact bool
 ro.lmk.kill_timeout_ms          u:object_r:lmkd_config_prop:s0 exact int
 ro.lmk.log_stats                u:object_r:lmkd_config_prop:s0 exact bool
@@ -565,6 +569,7 @@
 sys.usb.controller u:object_r:usb_control_prop:s0 exact string
 sys.usb.state      u:object_r:usb_control_prop:s0 exact string
 
+sys.usb.mtp.batchcancel u:object_r:usb_config_prop:s0 exact bool
 sys.usb.mtp.device_type u:object_r:usb_config_prop:s0 exact int
 
 sys.usb.config. u:object_r:usb_prop:s0
@@ -847,6 +852,7 @@
 ro.vendor.build.version.release             u:object_r:build_vendor_prop:s0 exact string
 ro.vendor.build.version.release_or_codename u:object_r:build_vendor_prop:s0 exact string
 ro.vendor.build.version.sdk                 u:object_r:build_vendor_prop:s0 exact int
+ro.vendor.build.dont_use_vabc               u:object_r:build_vendor_prop:s0 exact bool
 
 # All vendor CPU abilist props are set by /vendor/build.prop
 ro.vendor.product.cpu.abilist   u:object_r:build_vendor_prop:s0 exact string
@@ -1116,8 +1122,17 @@
 telephony.active_modems.max_count u:object_r:telephony_config_prop:s0 exact int
 telephony.lteOnCdmaDevice         u:object_r:telephony_config_prop:s0 exact int
 persist.dbg.volte_avail_ovr       u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.volte_avail_ovr0      u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.volte_avail_ovr1      u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.volte_avail_ovr2      u:object_r:telephony_config_prop:s0 exact int
 persist.dbg.vt_avail_ovr          u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.vt_avail_ovr0         u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.vt_avail_ovr1         u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.vt_avail_ovr2         u:object_r:telephony_config_prop:s0 exact int
 persist.dbg.wfc_avail_ovr         u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.wfc_avail_ovr0        u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.wfc_avail_ovr1        u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.wfc_avail_ovr2        u:object_r:telephony_config_prop:s0 exact int
 
 # System locale list filter configuration
 ro.localization.locale_filter u:object_r:localization_prop:s0 exact string
diff --git a/prebuilts/api/31.0/private/shell.te b/prebuilts/api/31.0/private/shell.te
index 16d25e4..40b19fd 100644
--- a/prebuilts/api/31.0/private/shell.te
+++ b/prebuilts/api/31.0/private/shell.te
@@ -114,8 +114,10 @@
 allow shell self:perf_event { open read write kernel };
 neverallow shell self:perf_event ~{ open read write kernel };
 
-# Allow shell to read /apex/apex-info-list.xml
+# Allow shell to read /apex/apex-info-list.xml and the vendor apexes
 allow shell apex_info_file:file r_file_perms;
+allow shell vendor_apex_file:file r_file_perms;
+allow shell vendor_apex_file:dir r_dir_perms;
 
 # Set properties.
 set_prop(shell, shell_prop)
@@ -169,9 +171,6 @@
 # Allow shell to read boot image timestamps and fingerprints.
 get_prop(shell, build_bootimage_prop)
 
-# Allow shell to read odsign verification properties
-get_prop(shell, odsign_prop)
-
 userdebug_or_eng(`set_prop(shell, persist_debug_prop)')
 
 # Allow to issue control commands to profcollectd binder service.
diff --git a/prebuilts/api/31.0/private/system_server.te b/prebuilts/api/31.0/private/system_server.te
index 04b5c76..73301c1 100644
--- a/prebuilts/api/31.0/private/system_server.te
+++ b/prebuilts/api/31.0/private/system_server.te
@@ -222,6 +222,9 @@
 # for dumpsys meminfo
 allow system_server dmabuf_heap_device:dir r_dir_perms;
 
+# Allow reading /proc/vmstat for the oom kill count
+allow system_server proc_vmstat:file r_file_perms;
+
 # The DhcpClient and WifiWatchdog use packet_sockets
 allow system_server self:packet_socket create_socket_perms_no_ioctl;
 
diff --git a/prebuilts/api/31.0/public/app.te b/prebuilts/api/31.0/public/app.te
index 5fa4710..5527f99 100644
--- a/prebuilts/api/31.0/public/app.te
+++ b/prebuilts/api/31.0/public/app.te
@@ -73,7 +73,7 @@
 allow { appdomain -isolated_app -mlstrustedsubject } { app_data_file privapp_data_file }:file create_file_perms;
 
 # Access via already open fds is ok even for mlstrustedsubject.
-allow { appdomain -isolated_app } { app_data_file privapp_data_file }:file { getattr map read write };
+allow { appdomain -isolated_app } { app_data_file privapp_data_file system_app_data_file }:file { getattr map read write };
 
 # Traverse into expanded storage
 allow appdomain mnt_expand_file:dir r_dir_perms;
@@ -596,5 +596,8 @@
 neverallow appdomain system_bootstrap_lib_file:dir
     { open read getattr search };
 
+# Allow to read ro.vendor.camera.extensions.enabled
+get_prop(appdomain, camera2_extensions_prop)
+
 # Allow to ro.camerax.extensions.enabled
 get_prop(appdomain, camerax_extensions_prop)
diff --git a/prebuilts/api/31.0/public/file.te b/prebuilts/api/31.0/public/file.te
index 767225f..dc788ac 100644
--- a/prebuilts/api/31.0/public/file.te
+++ b/prebuilts/api/31.0/public/file.te
@@ -77,6 +77,7 @@
 type proc_vmallocinfo, fs_type, proc_type;
 type proc_vmstat, fs_type, proc_type;
 type proc_zoneinfo, fs_type, proc_type;
+type proc_vendor_sched, proc_type, fs_type;
 type selinuxfs, fs_type, mlstrustedobject;
 type fusectlfs, fs_type;
 type cgroup, fs_type, mlstrustedobject;
@@ -117,6 +118,10 @@
 type sysfs_fs_f2fs, sysfs_type, fs_type;
 type sysfs_fs_incfs_features, sysfs_type, fs_type;
 type sysfs_fs_incfs_metrics, sysfs_type, fs_type;
+type sysfs_vendor_sched, sysfs_type, fs_type;
+userdebug_or_eng(`
+    typeattribute sysfs_vendor_sched mlstrustedobject;
+')
 type fs_bpf, fs_type;
 type fs_bpf_tethering, fs_type;
 type configfs, fs_type;
diff --git a/prebuilts/api/31.0/public/hal_neverallows.te b/prebuilts/api/31.0/public/hal_neverallows.te
index 45227e4..105689b 100644
--- a/prebuilts/api/31.0/public/hal_neverallows.te
+++ b/prebuilts/api/31.0/public/hal_neverallows.te
@@ -27,21 +27,7 @@
   -hal_wifi_supplicant_server
   -hal_telephony_server
   -hal_uwb_server
-} domain:{ udp_socket rawip_socket } *;
-
-neverallow {
-  halserverdomain
-  -hal_automotive_socket_exemption
-  -hal_can_controller_server
-  -hal_tetheroffload_server
-  -hal_wifi_server
-  -hal_wifi_hostapd_server
-  -hal_wifi_supplicant_server
-  -hal_telephony_server
-} {
-  domain
-  userdebug_or_eng(`-su')
-}:tcp_socket *;
+} domain:{ tcp_socket udp_socket rawip_socket } *;
 
 # The UWB HAL is not actually a networking HAL but may need to bring up and down
 # interfaces. Restrict it to only these networking operations.
@@ -49,7 +35,7 @@
 
 # Subset of socket_class_set likely to be usable for communication or accessible through net_admin.
 # udp_socket is required to use interface ioctls.
-neverallow hal_uwb_server domain:{ socket rawip_socket netlink_socket packet_socket key_socket netlink_route_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_dnrt_socket netlink_kobject_uevent_socket tun_socket netlink_iscsi_socket netlink_fib_lookup_socket netlink_connector_socket netlink_netfilter_socket netlink_scsitransport_socket netlink_rdma_socket netlink_crypto_socket qipcrtr_socket xdp_socket } *;
+neverallow hal_uwb_server domain:{ socket tcp_socket rawip_socket netlink_socket packet_socket key_socket netlink_route_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_dnrt_socket netlink_kobject_uevent_socket tun_socket netlink_iscsi_socket netlink_fib_lookup_socket netlink_connector_socket netlink_netfilter_socket netlink_scsitransport_socket netlink_rdma_socket netlink_crypto_socket qipcrtr_socket xdp_socket } *;
 
 ###
 # HALs are defined as an attribute and so a given domain could hypothetically
diff --git a/prebuilts/api/31.0/public/property.te b/prebuilts/api/31.0/public/property.te
index 57146a4..1d3f358 100644
--- a/prebuilts/api/31.0/public/property.te
+++ b/prebuilts/api/31.0/public/property.te
@@ -123,6 +123,7 @@
 system_vendor_config_prop(build_vendor_prop)
 system_vendor_config_prop(camera_calibration_prop)
 system_vendor_config_prop(camera_config_prop)
+system_vendor_config_prop(camera2_extensions_prop)
 system_vendor_config_prop(camerax_extensions_prop)
 system_vendor_config_prop(charger_config_prop)
 system_vendor_config_prop(codec2_config_prop)
diff --git a/prebuilts/api/31.0/public/vendor_init.te b/prebuilts/api/31.0/public/vendor_init.te
index b0e1da5..0999f48 100644
--- a/prebuilts/api/31.0/public/vendor_init.te
+++ b/prebuilts/api/31.0/public/vendor_init.te
@@ -218,6 +218,7 @@
 set_prop(vendor_init, apk_verity_prop)
 set_prop(vendor_init, bluetooth_a2dp_offload_prop)
 set_prop(vendor_init, bluetooth_audio_hal_prop)
+set_prop(vendor_init, camera2_extensions_prop)
 set_prop(vendor_init, camerax_extensions_prop)
 set_prop(vendor_init, cpu_variant_prop)
 set_prop(vendor_init, dalvik_runtime_prop)
diff --git a/private/compat/30.0/30.0.ignore.cil b/private/compat/30.0/30.0.ignore.cil
index 6521bde..ba0a494 100644
--- a/private/compat/30.0/30.0.ignore.cil
+++ b/private/compat/30.0/30.0.ignore.cil
@@ -147,6 +147,7 @@
     vd_device
     vendor_kernel_modules
     vendor_modprobe
+    vendor_uuid_mapping_config_file
     vibrator_manager_service
     virtualization_service
     vpn_management_service
diff --git a/private/compat/31.0/31.0.cil b/private/compat/31.0/31.0.cil
index eaf971b..ba6944e 100644
--- a/private/compat/31.0/31.0.cil
+++ b/private/compat/31.0/31.0.cil
@@ -5,6 +5,7 @@
 (type apex_wifi_data_file)
 (type healthd_exec)
 (type nonplat_service_contexts_file)
+(type sysfs_block)
 (type vr_hwc)
 (type vr_hwc_exec)
 
@@ -148,6 +149,7 @@
 (expandtypeattribute (cache_private_backup_file_31_0) true)
 (expandtypeattribute (cache_recovery_file_31_0) true)
 (expandtypeattribute (cacheinfo_service_31_0) true)
+(expandtypeattribute (camera2_extensions_prop_31_0) true)
 (expandtypeattribute (camera_calibration_prop_31_0) true)
 (expandtypeattribute (camera_config_prop_31_0) true)
 (expandtypeattribute (camera_data_file_31_0) true)
@@ -528,6 +530,7 @@
 (expandtypeattribute (keystore_data_file_31_0) true)
 (expandtypeattribute (keystore_exec_31_0) true)
 (expandtypeattribute (keystore_maintenance_service_31_0) true)
+(expandtypeattribute (keystore_metrics_service_31_0) true)
 (expandtypeattribute (keystore_service_31_0) true)
 (expandtypeattribute (kmsg_debug_device_31_0) true)
 (expandtypeattribute (kmsg_device_31_0) true)
@@ -795,6 +798,7 @@
 (expandtypeattribute (proc_uid_procstat_set_31_0) true)
 (expandtypeattribute (proc_uid_time_in_state_31_0) true)
 (expandtypeattribute (proc_uptime_31_0) true)
+(expandtypeattribute (proc_vendor_sched_31_0) true)
 (expandtypeattribute (proc_version_31_0) true)
 (expandtypeattribute (proc_vmallocinfo_31_0) true)
 (expandtypeattribute (proc_vmstat_31_0) true)
@@ -953,6 +957,7 @@
 (expandtypeattribute (sysfs_31_0) true)
 (expandtypeattribute (sysfs_android_usb_31_0) true)
 (expandtypeattribute (sysfs_batteryinfo_31_0) true)
+(expandtypeattribute (sysfs_block_31_0) true)
 (expandtypeattribute (sysfs_bluetooth_writable_31_0) true)
 (expandtypeattribute (sysfs_devfreq_cur_31_0) true)
 (expandtypeattribute (sysfs_devfreq_dir_31_0) true)
@@ -988,6 +993,7 @@
 (expandtypeattribute (sysfs_uio_31_0) true)
 (expandtypeattribute (sysfs_usb_31_0) true)
 (expandtypeattribute (sysfs_usermodehelper_31_0) true)
+(expandtypeattribute (sysfs_vendor_sched_31_0) true)
 (expandtypeattribute (sysfs_vibrator_31_0) true)
 (expandtypeattribute (sysfs_wake_lock_31_0) true)
 (expandtypeattribute (sysfs_wakeup_31_0) true)
@@ -1378,6 +1384,7 @@
 (typeattributeset cache_private_backup_file_31_0 (cache_private_backup_file))
 (typeattributeset cache_recovery_file_31_0 (cache_recovery_file))
 (typeattributeset cacheinfo_service_31_0 (cacheinfo_service))
+(typeattributeset camera2_extensions_prop_31_0 (camera2_extensions_prop))
 (typeattributeset camera_calibration_prop_31_0 (camera_calibration_prop))
 (typeattributeset camera_config_prop_31_0 (camera_config_prop))
 (typeattributeset camera_data_file_31_0 (camera_data_file))
@@ -1758,6 +1765,7 @@
 (typeattributeset keystore_data_file_31_0 (keystore_data_file))
 (typeattributeset keystore_exec_31_0 (keystore_exec))
 (typeattributeset keystore_maintenance_service_31_0 (keystore_maintenance_service))
+(typeattributeset keystore_metrics_service_31_0 (keystore_metrics_service))
 (typeattributeset keystore_service_31_0 (keystore_service))
 (typeattributeset kmsg_debug_device_31_0 (kmsg_debug_device))
 (typeattributeset kmsg_device_31_0 (kmsg_device))
@@ -2032,6 +2040,7 @@
 (typeattributeset proc_uid_procstat_set_31_0 (proc_uid_procstat_set))
 (typeattributeset proc_uid_time_in_state_31_0 (proc_uid_time_in_state))
 (typeattributeset proc_uptime_31_0 (proc_uptime))
+(typeattributeset proc_vendor_sched_31_0 (proc_vendor_sched))
 (typeattributeset proc_version_31_0 (proc_version))
 (typeattributeset proc_vmallocinfo_31_0 (proc_vmallocinfo))
 (typeattributeset proc_vmstat_31_0 (proc_vmstat))
@@ -2190,6 +2199,7 @@
 (typeattributeset sysfs_31_0 (sysfs))
 (typeattributeset sysfs_android_usb_31_0 (sysfs_android_usb))
 (typeattributeset sysfs_batteryinfo_31_0 (sysfs_batteryinfo))
+(typeattributeset sysfs_block_31_0 (sysfs_block))
 (typeattributeset sysfs_bluetooth_writable_31_0 (sysfs_bluetooth_writable))
 (typeattributeset sysfs_devfreq_cur_31_0 (sysfs_devfreq_cur))
 (typeattributeset sysfs_devfreq_dir_31_0 (sysfs_devfreq_dir))
@@ -2225,6 +2235,7 @@
 (typeattributeset sysfs_uio_31_0 (sysfs_uio))
 (typeattributeset sysfs_usb_31_0 (sysfs_usb))
 (typeattributeset sysfs_usermodehelper_31_0 (sysfs_usermodehelper))
+(typeattributeset sysfs_vendor_sched_31_0 (sysfs_vendor_sched))
 (typeattributeset sysfs_vibrator_31_0 (sysfs_vibrator))
 (typeattributeset sysfs_wake_lock_31_0 (sysfs_wake_lock))
 (typeattributeset sysfs_wakeup_31_0 (sysfs_wakeup))
diff --git a/private/compat/31.0/31.0.ignore.cil b/private/compat/31.0/31.0.ignore.cil
index c840081..aad01e1 100644
--- a/private/compat/31.0/31.0.ignore.cil
+++ b/private/compat/31.0/31.0.ignore.cil
@@ -49,6 +49,7 @@
     sysfs_fs_fuse_bpf
     sysfs_vendor_sched
     tv_iapp_service
+    vendor_uuid_mapping_config_file
     vendor_vm_file
     vendor_vm_data_file
     virtual_device_service
diff --git a/private/composd.te b/private/composd.te
index 5edea69..30e26f9 100644
--- a/private/composd.te
+++ b/private/composd.te
@@ -1,10 +1,11 @@
 type composd, domain, coredomain;
 type composd_exec, system_file_type, exec_type, file_type;
 
-# Host a dynamic AIDL service
+# Host dynamic AIDL services
 init_daemon_domain(composd)
 binder_use(composd)
 add_service(composd, compos_service)
+add_service(composd, compos_internal_service)
 
 # Call back into system server
 binder_call(composd, system_server)
diff --git a/private/crosvm.te b/private/crosvm.te
index 5ec50b5..90addc8 100644
--- a/private/crosvm.te
+++ b/private/crosvm.te
@@ -70,3 +70,14 @@
     -vendor_task_profiles_file
   }:file *;
 ')
+
+# app_data_file (and shell_data_file for debuggable builds) is the only
+# app_data_file_type that is allowed for crosvm to read.  Note that the use of
+# app_data_file is allowed only for the intance disk image.  This is enforced
+# inside the virtualizationservice by checking the file context of all disk
+# image files.
+neverallow crosvm {
+  app_data_file_type
+  -app_data_file
+  userdebug_or_eng(`-shell_data_file')
+}:file read;
diff --git a/private/domain.te b/private/domain.te
index a0e188b..5b9a5b1 100644
--- a/private/domain.te
+++ b/private/domain.te
@@ -511,6 +511,7 @@
     -vendor_public_framework_file
     -vendor_public_lib_file
     -vendor_task_profiles_file
+    -vendor_uuid_mapping_config_file
     -vndk_sp_file
   }:file *;
 ')
diff --git a/private/file_contexts b/private/file_contexts
index c1110cf..ea5f66f 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -412,6 +412,10 @@
 /(odm|vendor/odm)/overlay(/.*)?               u:object_r:vendor_overlay_file:s0
 /(odm|vendor/odm)/framework(/.*)?             u:object_r:vendor_framework_file:s0
 
+# secure-element service: vendor uuid mapping config file
+/(odm|vendor/odm|vendor|system/vendor)/etc/hal_uuid_map_(.*)?\.xml    u:object_r:vendor_uuid_mapping_config_file:s0
+
+
 # Input configuration
 /(odm|vendor/odm|vendor|system/vendor)/usr/keylayout(/.*)?\.kl        u:object_r:vendor_keylayout_file:s0
 /(odm|vendor/odm|vendor|system/vendor)/usr/keychars(/.*)?\.kcm        u:object_r:vendor_keychars_file:s0
@@ -439,7 +443,7 @@
 /(product|system/product)(/.*)?                                 u:object_r:system_file:s0
 /(product|system/product)/etc/group                             u:object_r:system_group_file:s0
 /(product|system/product)/etc/passwd                            u:object_r:system_passwd_file:s0
-/(product|system/product)/overlay(/.*)?                         u:object_r:vendor_overlay_file:s0
+/(product|system/product)/overlay(/.*)?                         u:object_r:system_file:s0
 
 /(product|system/product)/etc/selinux/product_file_contexts      u:object_r:file_contexts_file:s0
 /(product|system/product)/etc/selinux/product_hwservice_contexts u:object_r:hwservice_contexts_file:s0
diff --git a/private/init.te b/private/init.te
index 26aea2f..997a184 100644
--- a/private/init.te
+++ b/private/init.te
@@ -13,6 +13,7 @@
   domain_trans(init, rootfs, adbd)
   domain_trans(init, rootfs, charger)
   domain_trans(init, rootfs, fastbootd)
+  domain_trans(init, rootfs, hal_health_server)
   domain_trans(init, rootfs, recovery)
   domain_trans(init, rootfs, linkerconfig)
   domain_trans(init, rootfs, servicemanager)
diff --git a/private/odrefresh.te b/private/odrefresh.te
index c6ab7bb..e146938 100644
--- a/private/odrefresh.te
+++ b/private/odrefresh.te
@@ -54,7 +54,7 @@
 
 # Make binder calls back to composd
 binder_use(odrefresh)
-allow odrefresh compos_service:service_manager find;
+allow odrefresh compos_internal_service:service_manager find;
 binder_call(odrefresh, composd)
 
 # Run fd_server in its own domain
diff --git a/private/property_contexts b/private/property_contexts
index 7b5c5a9..1627014 100644
--- a/private/property_contexts
+++ b/private/property_contexts
@@ -294,8 +294,10 @@
 ro.virtual_ab.retrofit  u:object_r:virtual_ab_prop:s0 exact bool
 ro.virtual_ab.compression.enabled  u:object_r:virtual_ab_prop:s0 exact bool
 ro.virtual_ab.compression.xor.enabled   u:object_r:virtual_ab_prop:s0 exact bool
+ro.virtual_ab.userspace.snapshots.enabled u:object_r:virtual_ab_prop:s0 exact bool
 snapuserd.ready         u:object_r:snapuserd_prop:s0 exact bool
 snapuserd.proxy_ready   u:object_r:snapuserd_prop:s0 exact bool
+snapuserd.test.dm.snapshots u:object_r:snapuserd_prop:s0 exact bool
 
 ro.product.ab_ota_partitions u:object_r:ota_prop:s0 exact string
 # Property to set/clear the warm reset flag after an OTA update.
@@ -1127,6 +1129,8 @@
 framework_watchdog.fatal_count                u:object_r:framework_watchdog_config_prop:s0 exact int
 framework_watchdog.fatal_window.second        u:object_r:framework_watchdog_config_prop:s0 exact int
 
+gsm.operator.iso-country       u:object_r:telephony_status_prop:s0 exact string
+gsm.sim.operator.iso-country   u:object_r:telephony_status_prop:s0 exact string
 gsm.sim.operator.numeric       u:object_r:telephony_status_prop:s0 exact string
 persist.radio.airplane_mode_on u:object_r:telephony_status_prop:s0 exact bool
 
diff --git a/private/secure_element.te b/private/secure_element.te
index 57f512b..fd3b688 100644
--- a/private/secure_element.te
+++ b/private/secure_element.te
@@ -12,3 +12,5 @@
 # the secure element process, from a file in
 # /data/data/com.android.shell/files/bugreports/bugreport-*.
 allow secure_element shell_data_file:file read;
+
+allow secure_element vendor_uuid_mapping_config_file:file r_file_perms;
diff --git a/private/service.te b/private/service.te
index d192f12..c3bbd0d 100644
--- a/private/service.te
+++ b/private/service.te
@@ -6,9 +6,11 @@
 type mediatuner_service,            app_api_service, service_manager_type;
 type profcollectd_service,          service_manager_type;
 type resolver_service,              system_server_service, service_manager_type;
+type safety_center_service,         app_api_service, system_api_service, system_server_service, service_manager_type;
 type stats_service,                 service_manager_type;
 type statsbootstrap_service,        system_server_service, service_manager_type;
 type statscompanion_service,        system_server_service, service_manager_type;
 type statsmanager_service,          system_api_service, system_server_service, service_manager_type;
 type tracingproxy_service,          system_server_service, service_manager_type;
 type uce_service,                   service_manager_type;
+type compos_internal_service,       service_manager_type;
diff --git a/private/service_contexts b/private/service_contexts
index 032f680..4890af8 100644
--- a/private/service_contexts
+++ b/private/service_contexts
@@ -49,6 +49,7 @@
 android.hardware.wifi.hostapd.IHostapd/default                       u:object_r:hal_wifi_hostapd_service:s0
 android.hardware.wifi.supplicant.ISupplicant/default                 u:object_r:hal_wifi_supplicant_service:s0
 android.frameworks.stats.IStats/default                              u:object_r:fwk_stats_service:s0
+android.se.omapi.ISecureElementService/default                       u:object_r:secure_element_service:s0
 android.system.keystore2.IKeystoreService/default                    u:object_r:keystore_service:s0
 android.system.suspend.ISystemSuspend/default                        u:object_r:hal_system_suspend_service:s0
 
@@ -76,6 +77,7 @@
 android.security.remoteprovisioning       u:object_r:remoteprovisioning_service:s0
 android.service.gatekeeper.IGateKeeperService    u:object_r:gatekeeper_service:s0
 android.system.composd                    u:object_r:compos_service:s0
+android.system.composd.internal           u:object_r:compos_internal_service:s0
 android.system.virtualizationservice      u:object_r:virtualization_service:s0
 app_binding                               u:object_r:app_binding_service:s0
 app_hibernation                           u:object_r:app_hibernation_service:s0
@@ -264,6 +266,7 @@
 rollback                                  u:object_r:rollback_service:s0
 rttmanager                                u:object_r:rttmanager_service:s0
 runtime                                   u:object_r:runtime_service:s0
+safety_center                             u:object_r:safety_center_service:s0
 samplingprofiler                          u:object_r:samplingprofiler_service:s0
 scheduling_policy                         u:object_r:scheduling_policy_service:s0
 search                                    u:object_r:search_service:s0
diff --git a/private/snapuserd.te b/private/snapuserd.te
index f24986c..e3b43a1 100644
--- a/private/snapuserd.te
+++ b/private/snapuserd.te
@@ -40,6 +40,7 @@
 
 # snapuserd.* properties
 set_prop(snapuserd, snapuserd_prop)
+get_prop(snapuserd, virtual_ab_prop)
 
 # For inotify watching for /dev/socket/snapuserd_proxy to appear.
 allow snapuserd tmpfs:dir { read watch };
diff --git a/private/system_server.te b/private/system_server.te
index 5b67b70..68792e8 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -1250,10 +1250,13 @@
 # https://bugs.chromium.org/p/project-zero/issues/detail?id=955 for example.
 neverallow system_server data_file_type:file no_x_file_perms;
 
-# The only block device system_server should be accessing is
+# The only block device system_server should be writing to is
 # the frp_block_device. This helps avoid a system_server to root
 # escalation by writing to raw block devices.
-neverallow system_server { dev_type -frp_block_device }:blk_file no_rw_file_perms;
+# The system_server may need to read from vd_device if it uses
+# block apexes.
+neverallow system_server { dev_type -frp_block_device }:blk_file no_w_file_perms;
+neverallow system_server { dev_type -frp_block_device -vd_device }:blk_file r_file_perms;
 
 # system_server should never use JIT functionality
 # See https://googleprojectzero.blogspot.com/2016/12/bitunmap-attacking-android-ashmem.html
diff --git a/public/file.te b/public/file.te
index 1bde194..5850e7d 100644
--- a/public/file.te
+++ b/public/file.te
@@ -250,6 +250,9 @@
 type vendor_keychars_file, vendor_file_type, file_type;
 type vendor_idc_file, vendor_file_type, file_type;
 
+# Type for vendor uuid mapping config file
+type vendor_uuid_mapping_config_file, vendor_file_type, file_type;
+
 # SoC-specific virtual machine disk files
 type vendor_vm_file, vendor_file_type, file_type;
 # SoC-specific virtual machine disk files that are mutable
diff --git a/tests/Android.bp b/tests/Android.bp
index 6a86188..58d4c4f 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -28,7 +28,6 @@
     name: "py2_only",
     version: {
         py2: {
-            embedded_launcher: true,
             enabled: true,
         },
         py3: {
@@ -88,6 +87,18 @@
     defaults: ["py2_only"],
 }
 
+python_test_host {
+    name: "fc_sort_test",
+    srcs: [
+        "fc_sort.py",
+        "fc_sort_test.py",
+    ],
+    defaults: ["py2_only"],
+    test_options: {
+        unit_test: true,
+    }
+}
+
 python_binary_host {
     name: "check_prop_prefix",
     srcs: ["check_prop_prefix.py"],
diff --git a/tests/fc_sort.py b/tests/fc_sort.py
old mode 100755
new mode 100644
index cbb0e5e..2bad6fb
--- a/tests/fc_sort.py
+++ b/tests/fc_sort.py
@@ -1,142 +1,158 @@
-#!/usr/bin/env python
-import sys
-import os
+#!/usr/bin/env python2
+#
+# Copyright 2021 - 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.
+
 import argparse
+import os
+import sys
 
-class FileContextsNode:
-    path = None
-    fileType = None
-    context = None
-    Type = None
-    meta = None
-    stemLen = None
-    strLen = None
-    Type = None
-    line = None
-    def __init__(self, path, fileType, context, meta, stemLen, strLen, line):
-        self.path = path
-        self.fileType = fileType
-        self.context = context
-        self.meta = meta
-        self.stemLen = stemLen
-        self.strlen = strLen
-        self.Type = context.split(":")[2]
-        self.line = line
 
-metaChars = frozenset(['.', '^', '$', '?', '*', '+', '|', '[', '(', '{'])
-escapedMetaChars = frozenset(['\.', '\^', '\$', '\?', '\*', '\+', '\|', '\[', '\(', '\{'])
+META_CHARS = frozenset(['.', '^', '$', '?', '*', '+', '|', '[', '(', '{'])
+ESCAPED_META_CHARS = frozenset([ '\\{}'.format(c) for c in META_CHARS ])
 
-def getStemLen(path):
-    global metaChars
-    stemLen = 0
+
+def get_stem_len(path):
+    """Returns the length of the stem."""
+    stem_len = 0
     i = 0
     while i < len(path):
         if path[i] == "\\":
             i += 1
-        elif path[i] in metaChars:
+        elif path[i] in META_CHARS:
             break
-        stemLen += 1
+        stem_len += 1
         i += 1
-    return stemLen
+    return stem_len
 
 
-def getIsMeta(path):
-    global metaChars
-    global escapedMetaChars
-    metaCharsCount = 0
-    escapedMetaCharsCount = 0
-    for c in metaChars:
+def is_meta(path):
+    """Indicates if a path contains any metacharacter."""
+    meta_char_count = 0
+    escaped_meta_char_count = 0
+    for c in META_CHARS:
         if c in path:
-            metaCharsCount += 1
-    for c in escapedMetaChars:
+            meta_char_count += 1
+    for c in ESCAPED_META_CHARS:
         if c in path:
-            escapedMetaCharsCount += 1
-    return metaCharsCount > escapedMetaCharsCount
+            escaped_meta_char_count += 1
+    return meta_char_count > escaped_meta_char_count
 
-def CreateNode(line):
-    global metaChars
-    if (len(line) == 0) or (line[0] == '#'):
-        return None
 
-    split = line.split()
-    path = split[0].strip()
-    context = split[-1].strip()
-    fileType = None
-    if len(split) == 3:
-        fileType = split[1].strip()
-    meta = getIsMeta(path)
-    stemLen = getStemLen(path)
-    strLen = len(path.replace("\\", ""))
+class FileContextsNode(object):
+    """An entry in a file_context file."""
 
-    return FileContextsNode(path, fileType, context, meta, stemLen, strLen, line)
+    def __init__(self, path, file_type, context, meta, stem_len, str_len, line):
+        self.path = path
+        self.file_type = file_type
+        self.context = context
+        self.meta = meta
+        self.stem_len = stem_len
+        self.str_len = str_len
+        self.type = context.split(":")[2]
+        self.line = line
 
-def ReadFileContexts(files):
-    fc = []
-    for f in files:
-        fd = open(f)
-        for line in fd:
-            node = CreateNode(line.strip())
-            if node != None:
-                fc.append(node)
-    return fc
+    @classmethod
+    def create(cls, line):
+        if (len(line) == 0) or (line[0] == '#'):
+            return None
 
-# Comparator function for list.sort() based off of fc_sort.c
-# Compares two FileContextNodes a and b and returns 1 if a is more
-# specific or -1 if b is more specific.
-def compare(a, b):
-    # The regex without metachars is more specific
-    if a.meta and not b.meta:
-        return -1
-    if b.meta and not a.meta:
-        return 1
+        split = line.split()
+        path = split[0].strip()
+        context = split[-1].strip()
+        file_type = None
+        if len(split) == 3:
+            file_type = split[1].strip()
+        meta = is_meta(path)
+        stem_len = get_stem_len(path)
+        str_len = len(path.replace("\\", ""))
 
-    # The regex with longer stemlen (regex before any meta characters) is more specific.
-    if a.stemLen < b.stemLen:
-        return -1
-    if b.stemLen < a.stemLen:
-        return 1
+        return cls(path, file_type, context, meta, stem_len, str_len, line)
 
-    # The regex with longer string length is more specific
-    if a.strLen < b.strLen:
-        return -1
-    if b.strLen < a.strLen:
-        return 1
+    # Comparator function based off fc_sort.c
+    def __lt__(self, other):
+        # The regex without metachars is more specific.
+        if self.meta and not other.meta:
+            return True
+        if other.meta and not self.meta:
+            return False
 
-    # A regex with a fileType defined (e.g. file, dir) is more specific.
-    if a.fileType is None and b.fileType is not None:
-        return -1
-    if b.fileType is None and a.fileType is not None:
-        return 1
+        # The regex with longer stem_len (regex before any meta characters) is
+        # more specific.
+        if self.stem_len < other.stem_len:
+            return True
+        if other.stem_len < self.stem_len:
+            return False
 
-    # Regexes are equally specific.
-    return 0
+        # The regex with longer string length is more specific
+        if self.str_len < other.str_len:
+            return True
+        if other.str_len < self.str_len:
+            return False
 
-def FcSort(files):
+        # A regex with a file_type defined (e.g. file, dir) is more specific.
+        if self.file_type is None and other.file_type is not None:
+            return True
+        if other.file_type is None and self.file_type is not None:
+            return False
+
+        return False
+
+
+def read_file_contexts(file_descriptor):
+    file_contexts = []
+    for line in file_descriptor:
+        node = FileContextsNode.create(line.strip())
+        if node is not None:
+            file_contexts.append(node)
+    return file_contexts
+
+
+def read_multiple_file_contexts(files):
+    file_contexts = []
+    for filename in files:
+        with open(filename) as fd:
+            file_contexts.extend(read_file_contexts(fd))
+    return file_contexts
+
+
+def sort(files):
     for f in files:
         if not os.path.exists(f):
             sys.exit("Error: File_contexts file " + f + " does not exist\n")
+    file_contexts = read_multiple_file_contexts(files)
+    file_contexts.sort()
+    return file_contexts
 
-    Fc = ReadFileContexts(files)
-    Fc.sort(cmp=compare)
 
-    return Fc
-
-def PrintFc(Fc, out):
+def print_fc(fc, out):
     if not out:
         f = sys.stdout
     else:
         f = open(out, "w")
-    for node in Fc:
+    for node in fc:
         f.write(node.line + "\n")
 
+
 if __name__ == '__main__':
-    parser = argparse.ArgumentParser(description="SELinux file_contexts sorting tool.")
-    parser.add_argument("-i", dest="input", help="Path to the file_contexts file(s).", nargs="?", action='append')
-    parser.add_argument("-o", dest="output", help="Path to the output file", nargs=1)
+    parser = argparse.ArgumentParser(
+            description="SELinux file_contexts sorting tool.")
+    parser.add_argument("-i", dest="input", nargs="*",
+            help="Path to the file_contexts file(s).")
+    parser.add_argument("-o", dest="output", help="Path to the output file.")
     args = parser.parse_args()
     if not args.input:
         parser.error("Must include path to policy")
-    if not not args.output:
-        args.output = args.output[0]
 
-    PrintFc(FcSort(args.input),args.output)
+    print_fc(sort(args.input), args.output)
diff --git a/tests/fc_sort_test.py b/tests/fc_sort_test.py
new file mode 100644
index 0000000..2d8d2d8
--- /dev/null
+++ b/tests/fc_sort_test.py
@@ -0,0 +1,59 @@
+# Copyright 2021 - 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.
+
+import unittest
+
+import fc_sort
+
+class FcSortTest(unittest.TestCase):
+
+    def testGetStemLen(self):
+        self.assertEqual(fc_sort.get_stem_len("/data"), 5)
+        self.assertEqual(fc_sort.get_stem_len("/data/system"), 12)
+        self.assertEqual(fc_sort.get_stem_len("/data/(system)?"), 6)
+
+    def testIsMeta(self):
+        self.assertEqual(fc_sort.is_meta("/data"), False)
+        self.assertEqual(fc_sort.is_meta("/data$"), True)
+        self.assertEqual(fc_sort.is_meta(r"\$data"), False)
+
+    def testLesserThan(self):
+        n1 = fc_sort.FileContextsNode.create("/data  u:object_r:rootfs:s0")
+        # shorter stem_len
+        n2 = fc_sort.FileContextsNode.create("/d  u:object_r:rootfs:s0")
+        # is meta
+        n3 = fc_sort.FileContextsNode.create("/data/l(/.*)? u:object_r:log:s0")
+        # with file_type
+        n4 = fc_sort.FileContextsNode.create("/data -- u:object_r:rootfs:s0")
+        contexts = [n1, n2, n3, n4]
+        contexts.sort()
+        self.assertEqual(contexts, [n3, n2, n1, n4])
+
+    def testReadFileContexts(self):
+        content = """# comment
+/                                     u:object_r:rootfs:s0
+# another comment
+/adb_keys                     u:object_r:adb_keys_file:s0
+"""
+        fcs = fc_sort.read_file_contexts(content.splitlines())
+        self.assertEqual(len(fcs), 2)
+
+        self.assertEqual(fcs[0].path, "/")
+        self.assertEqual(fcs[0].type, "rootfs")
+
+        self.assertEqual(fcs[1].path, "/adb_keys")
+        self.assertEqual(fcs[1].type, "adb_keys_file")
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)
diff --git a/tests/policy.py b/tests/policy.py
index 40229b8..4648e30 100644
--- a/tests/policy.py
+++ b/tests/policy.py
@@ -271,7 +271,7 @@
         PathType = []
         for i in range(index, len(self.__FcSorted)):
             if MatchPathPrefix(self.__FcSorted[i].path, prefix):
-                PathType.append((self.__FcSorted[i].path, self.__FcSorted[i].Type))
+                PathType.append((self.__FcSorted[i].path, self.__FcSorted[i].type))
         return PathType
 
     # Return types that match MatchPrefixes but do not match
@@ -430,7 +430,7 @@
                     self.__FcDict[t] = [rec[0]]
             except:
                 pass
-        self.__FcSorted = fc_sort.FcSort(FcPaths)
+        self.__FcSorted = fc_sort.sort(FcPaths)
 
     # load policy
     def __InitPolicy(self, PolicyPath):