Merge "Add Soong variable for optimizing SystemUI Java"
diff --git a/core/Makefile b/core/Makefile
index a580ac8..4c1ae51 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -908,8 +908,14 @@
 INTERNAL_BOOTIMAGE_ARGS := \
 	$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET))
 
+INTERNAL_INIT_BOOT_IMAGE_ARGS :=
+
 ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
-INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
+  ifneq ($(BUILDING_INIT_BOOT_IMAGE),true)
+    INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
+  else
+    INTERNAL_INIT_BOOT_IMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
+  endif
 endif
 
 ifndef BUILDING_VENDOR_BOOT_IMAGE
@@ -1089,6 +1095,58 @@
 my_installed_prebuilt_gki_apex :=
 
 # -----------------------------------------------------------------
+#  init boot image
+ifeq ($(BUILDING_INIT_BOOT_IMAGE),true)
+
+INSTALLED_INIT_BOOT_IMAGE_TARGET := $(PRODUCT_OUT)/init_boot.img
+$(INSTALLED_INIT_BOOT_IMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_RAMDISK_TARGET)
+
+ifdef BOARD_KERNEL_PAGESIZE
+  INTERNAL_INIT_BOOT_IMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
+endif
+
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(INSTALLED_INIT_BOOT_IMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_INIT_BOOT_IMAGE_KEY_PATH)
+	$(call pretty,"Target init_boot image: $@")
+	$(MKBOOTIMG) $(INTERNAL_INIT_BOOT_IMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_INIT_ARGS) --output $@
+	$(call assert-max-image-size,$@,$(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE))
+	$(AVBTOOL) add_hash_footer \
+           --image $@ \
+	   --partition_size $(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE) \
+	   --partition_name init_boot $(INTERNAL_AVB_INIT_BOOT_SIGNING_ARGS) \
+	   $(BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS)
+else
+$(INSTALLED_INIT_BOOT_IMAGE_TARGET):
+	$(call pretty,"Target init_boot image: $@")
+	$(MKBOOTIMG) $(INTERNAL_INIT_BOOT_IMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_INIT_ARGS) --output $@
+	$(call assert-max-image-size,$@,$(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE))
+endif
+
+else # BUILDING_INIT_BOOT_IMAGE is not true
+
+ifdef BOARD_PREBUILT_INIT_BOOT_IMAGE
+INTERNAL_PREBUILT_INIT_BOOT_IMAGE := $(BOARD_PREBUILT_INIT_BOOT_IMAGE)
+INSTALLED_INIT_BOOT_IMAGE_TARGET := $(PRODUCT_OUT)/init_boot.img
+
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(INSTALLED_INIT_BOOT_IMAGE_TARGET): $(INTERNAL_PREBUILT_INIT_BOOT_IMAGE) $(AVBTOOL) $(BOARD_AVB_INIT_BOOT_KEY_PATH)
+	cp $(INTERNAL_PREBUILT_INIT_BOOT_IMAGE) $@
+	$(AVBTOOL) add_hash_footer \
+	    --image $@ \
+	    --partition_size $(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE) \
+	    --partition_name boot $(INTERNAL_AVB_INIT_BOOT_SIGNING_ARGS) \
+	    $(BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS)
+else
+$(INSTALLED_INIT_BOOT_IMAGE_TARGET): $(INTERNAL_PREBUILT_INIT_BOOT_IMAGE)
+	cp $(INTERNAL_PREBUILT_INIT_BOOT_IMAGE) $@
+endif # BOARD_AVB_ENABLE
+
+else # BOARD_PREBUILT_INIT_BOOT_IMAGE not defined
+INSTALLED_INIT_BOOT_IMAGE_TARGET :=
+endif # BOARD_PREBUILT_INIT_BOOT_IMAGE
+
+endif # BUILDING_INIT_BOOT_IMAGE is not true
+# -----------------------------------------------------------------
 # vendor boot image
 ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
 
@@ -2728,6 +2786,19 @@
   INTERNAL_SYSTEMIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT)/system_ext,/system_ext,system_ext.img)
 endif
 
+# -----------------------------------------------------------------
+# system_dlkm partition image
+
+# Create symlinks for system_dlkm on devices with a system_dlkm partition:
+# /system/lib/modules -> /system_dlkm/lib/modules
+#
+# On devices with a system_dlkm partition,
+# - /system/lib/modules is a symlink to a directory that stores system DLKMs.
+# - The system_dlkm partition is mounted at /system_dlkm at runtime.
+ifdef BOARD_USES_SYSTEM_DLKM_PARTITION
+  INTERNAL_SYSTEMIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT)/lib/modules,/system_dlkm/lib/modules,system_dlkm.img)
+endif
+
 FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)
 
 # ASAN libraries in the system image - add dependency.
@@ -3621,9 +3692,13 @@
     --prop com.android.build.pvmfw.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
 
 # The following vendor- and odm-specific images needs explicit SPL set per board.
+# TODO(b/210875415) Is this security_patch property used? Should it be removed from
+# boot.img when there is no platform ramdisk included in it?
 ifdef BOOT_SECURITY_PATCH
 BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
     --prop com.android.build.boot.security_patch:$(BOOT_SECURITY_PATCH)
+BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.init_boot.security_patch:$(BOOT_SECURITY_PATCH)
 endif
 
 ifdef VENDOR_SECURITY_PATCH
@@ -3652,6 +3727,7 @@
 endif
 
 BOOT_FOOTER_ARGS := BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS
+INIT_BOOT_FOOTER_ARGS := BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS
 VENDOR_BOOT_FOOTER_ARGS := BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS
 DTBO_FOOTER_ARGS := BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS
 PVMFW_FOOTER_ARGS := BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS
@@ -3735,6 +3811,10 @@
 $(eval $(call check-and-set-avb-args,boot))
 endif
 
+ifdef INSTALLED_INIT_BOOT_IMAGE_TARGET
+$(eval $(call check-and-set-avb-args,init_boot))
+endif
+
 ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
 $(eval $(call check-and-set-avb-args,vendor_boot))
 endif
@@ -3831,6 +3911,9 @@
   $(if $(BOARD_AVB_BOOT_KEY_PATH),\
     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_BOOT_KEY_PATH) \
       --output $(1)/boot.avbpubkey)
+  $(if $(BOARD_AVB_INIT_BOOT_KEY_PATH),\
+    $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_INIT_BOOT_KEY_PATH) \
+      --output $(1)/init_boot.avbpubkey)
   $(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),\
     $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_BOOT_KEY_PATH) \
       --output $(1)/vendor_boot.avbpubkey)
@@ -3934,6 +4017,7 @@
 $(INSTALLED_VBMETAIMAGE_TARGET): \
 	    $(AVBTOOL) \
 	    $(INSTALLED_BOOTIMAGE_TARGET) \
+	    $(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
 	    $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
 	    $(INSTALLED_SYSTEMIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
@@ -4505,6 +4589,10 @@
 else
 	echo "boot_images=$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(notdir $(b)))" >> $@
 endif
+ifneq ($(INSTALLED_INIT_BOOT_IMAGE_TARGET),)
+	$(hide) echo "init_boot=true" >> $@
+	$(hide) echo "init_boot_size=$(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE)" >> $@
+endif
 ifeq ($(BOARD_RAMDISK_USE_LZ4),true)
 	echo "lz4_ramdisks=true" >> $@
 endif
@@ -4538,6 +4626,7 @@
 	$(hide) echo 'mkbootimg_args=$(BOARD_MKBOOTIMG_ARGS)' >> $@
 	$(hide) echo 'recovery_mkbootimg_args=$(BOARD_RECOVERY_MKBOOTIMG_ARGS)' >> $@
 	$(hide) echo 'mkbootimg_version_args=$(INTERNAL_MKBOOTIMG_VERSION_ARGS)' >> $@
+	$(hide) echo 'mkbootimg_init_args=$(BOARD_MKBOOTIMG_INIT_ARGS)' >> $@
 ifdef BOARD_GKI_SIGNING_KEY_PATH
 	$(hide) echo 'gki_signing_key_path=$(BOARD_GKI_SIGNING_KEY_PATH)' >> $@
 	$(hide) echo 'gki_signing_algorithm=$(BOARD_GKI_SIGNING_ALGORITHM)' >> $@
@@ -4915,9 +5004,10 @@
   $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
 endif
 
-ifdef BUILDING_BOOT_IMAGE
+ifneq (,$(BUILDING_BOOT_IMAGE)$(BUILDING_INIT_BOOT_IMAGE))
   $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_RAMDISK_FILES)
-endif
+endif  # BUILDING_BOOT_IMAGE != "" || BUILDING_INIT_BOOT_IMAGE != ""
+
 ifneq (,$(INTERNAL_PREBUILT_BOOTIMAGE) $(filter true,$(BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES)))
   $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_BOOTIMAGE_TARGET)
 endif
@@ -5239,6 +5329,10 @@
 	$(hide) mkdir -p $(zip_root)/IMAGES
 	$(hide) cp $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) $(zip_root)/IMAGES/
 endif
+ifdef BOARD_PREBUILT_INIT_BOOT_IMAGE
+	$(hide) mkdir -p $(zip_root)/IMAGES
+	$(hide) cp $(INSTALLED_INIT_BOOT_IMAGE_TARGET) $(zip_root)/IMAGES/
+endif
 ifndef BOARD_PREBUILT_BOOTIMAGE
 ifneq (,$(INTERNAL_PREBUILT_BOOTIMAGE) $(filter true,$(BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES)))
 ifdef INSTALLED_BOOTIMAGE_TARGET
@@ -5316,6 +5410,13 @@
 	@# BOOT/RAMDISK exists and contains the ramdisk for recovery if using BOARD_USES_RECOVERY_AS_BOOT.
 	$(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt
 endif
+ifdef BUILDING_INIT_BOOT_IMAGE
+	$(hide) $(call package_files-copy-root, $(TARGET_RAMDISK_OUT),$(zip_root)/INIT_BOOT/RAMDISK)
+	$(hide) $(call fs_config,$(zip_root)/INIT_BOOT/RAMDISK,) > $(zip_root)/META/init_boot_filesystem_config.txt
+ifdef BOARD_KERNEL_PAGESIZE
+	$(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/INIT_BOOT/pagesize
+endif # BOARD_KERNEL_PAGESIZE
+endif # BUILDING_INIT_BOOT_IMAGE
 ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
 	$(call fs_config,$(zip_root)/VENDOR_BOOT/RAMDISK,) > $(zip_root)/META/vendor_boot_filesystem_config.txt
 endif
@@ -5629,6 +5730,7 @@
     $(INSTALLED_SYSTEMIMAGE_TARGET) \
     $(INSTALLED_RAMDISK_TARGET) \
     $(INSTALLED_BOOTIMAGE_TARGET) \
+    $(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
     $(INSTALLED_USERDATAIMAGE_TARGET) \
     $(INSTALLED_VENDORIMAGE_TARGET) \
     $(INSTALLED_PRODUCTIMAGE_TARGET) \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 78ac809..0befbfa 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -27,6 +27,10 @@
 # Add variables to the namespace below:
 
 $(call add_soong_config_var,ANDROID,TARGET_ENABLE_MEDIADRM_64)
+$(call add_soong_config_var,ANDROID,IS_TARGET_MIXED_SEPOLICY)
+ifeq ($(IS_TARGET_MIXED_SEPOLICY),true)
+$(call add_soong_config_var_value,ANDROID,MIXED_SEPOLICY_VERSION,$(BOARD_SEPOLICY_VERS))
+endif
 $(call add_soong_config_var,ANDROID,BOARD_USES_ODMIMAGE)
 $(call add_soong_config_var,ANDROID,BOARD_USES_RECOVERY_AS_BOOT)
 $(call add_soong_config_var,ANDROID,BOARD_BUILD_SYSTEM_ROOT_IMAGE)
@@ -88,7 +92,7 @@
   # This sets the default for building ART APEXes from source rather than
   # prebuilts (in packages/modules/ArtPrebuilt and prebuilt/module_sdk/art) in
   # all other platform builds.
-  SOONG_CONFIG_art_module_source_build ?= false
+  SOONG_CONFIG_art_module_source_build ?= true
 endif
 
 # Apex build mode variables
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 134cb8f..8a5440f 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -1055,7 +1055,9 @@
 endif
 ALL_MODULES.$(my_register_name).FOR_HOST_CROSS := $(my_host_cross)
 ALL_MODULES.$(my_register_name).MODULE_NAME := $(LOCAL_MODULE)
-ALL_MODULES.$(my_register_name).COMPATIBILITY_SUITES := $(LOCAL_COMPATIBILITY_SUITE)
+ALL_MODULES.$(my_register_name).COMPATIBILITY_SUITES := \
+  $(ALL_MODULES.$(my_register_name).COMPATIBILITY_SUITES) \
+  $(filter-out $(ALL_MODULES.$(my_register_name).COMPATIBILITY_SUITES),$(LOCAL_COMPATIBILITY_SUITE))
 ALL_MODULES.$(my_register_name).TEST_CONFIG := $(test_config)
 ALL_MODULES.$(my_register_name).EXTRA_TEST_CONFIGS := $(LOCAL_EXTRA_FULL_TEST_CONFIGS)
 ALL_MODULES.$(my_register_name).TEST_MAINLINE_MODULES := $(LOCAL_TEST_MAINLINE_MODULES)
diff --git a/core/board_config.mk b/core/board_config.mk
index 6bbb3a0..95cbe3d 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -65,6 +65,7 @@
 # File system variables
 _board_strip_readonly_list += BOARD_FLASH_BLOCK_SIZE
 _board_strip_readonly_list += BOARD_BOOTIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE
 _board_strip_readonly_list += BOARD_RECOVERYIMAGE_PARTITION_SIZE
 _board_strip_readonly_list += BOARD_SYSTEMIMAGE_PARTITION_SIZE
 _board_strip_readonly_list += BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE
@@ -122,6 +123,9 @@
 _board_strip_readonly_list += BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT
 _board_strip_readonly_list += BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES
 
+# Prebuilt image variables
+_board_strip_readonly_list += BOARD_PREBUILT_INIT_BOOT_IMAGE
+
 # Defines the list of logical vendor ramdisk names to build or include in vendor_boot.
 _board_strip_readonly_list += BOARD_VENDOR_RAMDISK_FRAGMENTS
 
@@ -461,6 +465,25 @@
 endif
 .KATI_READONLY := BUILDING_BOOT_IMAGE
 
+# Are we building an init boot image
+BUILDING_INIT_BOOT_IMAGE :=
+ifeq ($(PRODUCT_BUILD_INIT_BOOT_IMAGE),)
+  ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+    BUILDING_INIT_BOOT_IMAGE :=
+  else ifdef BOARD_PREBUILT_INIT_BOOT_IMAGE
+    BUILDING_INIT_BOOT_IMAGE :=
+  else ifdef BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE
+    BUILDING_INIT_BOOT_IMAGE := true
+  endif
+else ifeq ($(PRODUCT_BUILD_INIT_BOOT_IMAGE),true)
+  ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+    $(error PRODUCT_BUILD_INIT_BOOT_IMAGE is true, but so is BOARD_USES_RECOVERY_AS_BOOT. Use only one option.)
+  else
+    BUILDING_INIT_BOOT_IMAGE := true
+  endif
+endif
+.KATI_READONLY := BUILDING_INIT_BOOT_IMAGE
+
 # Are we building a recovery image
 BUILDING_RECOVERY_IMAGE :=
 ifeq ($(PRODUCT_BUILD_RECOVERY_IMAGE),)
@@ -569,6 +592,11 @@
     $(warning PRODUCT_BUILD_DEBUG_BOOT_IMAGE is true, but we're not building a boot image. \
       Skip building the debug boot image.)
   endif
+else ifdef BUILDING_INIT_BOOT_IMAGE
+  ifeq ($(PRODUCT_BUILD_DEBUG_BOOT_IMAGE),true)
+    $(warning PRODUCT_BUILD_DEBUG_BOOT_IMAGE is true, but we don't have a ramdisk in the boot image. \
+      Skip building the debug boot image.)
+  endif
 else
   ifeq ($(PRODUCT_BUILD_DEBUG_BOOT_IMAGE),)
     BUILDING_DEBUG_BOOT_IMAGE := true
diff --git a/core/config.mk b/core/config.mk
index bfff84e..e146f64 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -840,6 +840,14 @@
 BOARD_SEPOLICY_VERS := $(PLATFORM_SEPOLICY_VERSION)
 endif
 
+ifeq ($(BOARD_SEPOLICY_VERS),$(PLATFORM_SEPOLICY_VERSION))
+IS_TARGET_MIXED_SEPOLICY :=
+else
+IS_TARGET_MIXED_SEPOLICY := true
+endif
+
+.KATI_READONLY := IS_TARGET_MIXED_SEPOLICY
+
 # A list of SEPolicy versions, besides PLATFORM_SEPOLICY_VERSION, that the framework supports.
 PLATFORM_SEPOLICY_COMPAT_VERSIONS := \
     28.0 \
diff --git a/core/main.mk b/core/main.mk
index f7cf8de..d17f0cb 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1603,6 +1603,9 @@
 .PHONY: bootimage
 bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
 
+.PHONY: initbootimage
+bootimage: $(INSTALLED_INIT_BOOT_IMAGE_TARGET)
+
 ifeq (true,$(PRODUCT_EXPORT_BOOT_IMAGE_TO_DIST))
 $(call dist-for-goals, bootimage, $(INSTALLED_BOOTIMAGE_TARGET))
 endif
@@ -1629,6 +1632,7 @@
     $(INSTALLED_SYSTEMIMAGE_TARGET) \
     $(INSTALLED_RAMDISK_TARGET) \
     $(INSTALLED_BOOTIMAGE_TARGET) \
+    $(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
     $(INSTALLED_RADIOIMAGE_TARGET) \
     $(INSTALLED_DEBUG_RAMDISK_TARGET) \
     $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) \
diff --git a/core/product.mk b/core/product.mk
index 31b1beb..04c59ff 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -395,6 +395,7 @@
 _product_single_value_vars += PRODUCT_BUILD_USERDATA_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_RECOVERY_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_BOOT_IMAGE
+_product_single_value_vars += PRODUCT_BUILD_INIT_BOOT_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_DEBUG_BOOT_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_VENDOR_BOOT_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_DEBUG_VENDOR_BOOT_IMAGE
diff --git a/core/product_config.mk b/core/product_config.mk
index 0e969fe..a376f74 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -412,7 +412,7 @@
 _psmc_modules :=
 
 # Reset ADB keys for non-debuggable builds
-ifeq (,$(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
+ifeq (,$(filter eng userdebug,$(TARGET_BUILD_VARIANT)))
   PRODUCT_ADB_KEYS :=
 endif
 ifneq ($(filter-out 0 1,$(words $(PRODUCT_ADB_KEYS))),)
diff --git a/core/product_config.rbc b/core/product_config.rbc
index f26b428..1ccffcc 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -476,6 +476,12 @@
     return sorted(["%s/%s:%s/%s" % (
         from_dir, f, to_dir, f) for f in rblf_find_files(from_dir, pattern, only_files=1)])
 
+def _findstring(needle, haystack):
+    """Equivalent to GNU make's $(findstring)."""
+    if haystack.find(needle) < 0:
+        return ""
+    return needle
+
 def _filter_out(pattern, text):
     """Return all the words from `text' that do not match any word in `pattern'.
 
@@ -727,6 +733,7 @@
     filter = _filter,
     filter_out = _filter_out,
     find_and_copy = _find_and_copy,
+    findstring = _findstring,
     inherit = _inherit,
     indirect = _indirect,
     mk2rbc_error = _mk2rbc_error,
@@ -748,4 +755,5 @@
     setdefault = _setdefault,
     shell = rblf_shell,
     warning = _mkwarning,
+    words = __words,
 )
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 617abdf..07dafc7 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -191,6 +191,10 @@
 
 $(call add_json_list, BoardPlatVendorPolicy,             $(BOARD_PLAT_VENDOR_POLICY))
 $(call add_json_list, BoardReqdMaskPolicy,               $(BOARD_REQD_MASK_POLICY))
+$(call add_json_list, BoardSystemExtPublicPrebuiltDirs,  $(BOARD_SYSTEM_EXT_PUBLIC_PREBUILT_DIRS))
+$(call add_json_list, BoardSystemExtPrivatePrebuiltDirs, $(BOARD_SYSTEM_EXT_PRIVATE_PREBUILT_DIRS))
+$(call add_json_list, BoardProductPublicPrebuiltDirs,    $(BOARD_PRODUCT_PUBLIC_PREBUILT_DIRS))
+$(call add_json_list, BoardProductPrivatePrebuiltDirs,   $(BOARD_PRODUCT_PRIVATE_PREBUILT_DIRS))
 $(call add_json_list, BoardVendorSepolicyDirs,           $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_SEPOLICY_DIRS))
 $(call add_json_list, BoardOdmSepolicyDirs,              $(BOARD_ODM_SEPOLICY_DIRS))
 $(call add_json_list, BoardVendorDlkmSepolicyDirs,       $(BOARD_VENDOR_DLKM_SEPOLICY_DIRS))
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 1f1ec3f..bf19c5c 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -85,7 +85,7 @@
     #  It must be of the form "YYYY-MM-DD" on production devices.
     #  It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
     #  If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
-      PLATFORM_SECURITY_PATCH := 2021-11-05
+      PLATFORM_SECURITY_PATCH := 2021-12-05
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index f98f7e2..1a0fc76 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -49,6 +49,7 @@
 
 # APEX boot jars. Keep the list sorted by module names and then library names.
 # Note: core-icu4j is moved back to PRODUCT_BOOT_JARS in product_config.mk at a later stage.
+# Note: For modules available in Q, DO NOT add new entries here.
 PRODUCT_APEX_BOOT_JARS := \
     com.android.appsearch:framework-appsearch \
     com.android.conscrypt:conscrypt \
@@ -67,6 +68,7 @@
 
 # List of system_server classpath jars delivered via apex.
 # Keep the list sorted by module names and then library names.
+# Note: For modules available in Q, DO NOT add new entries here.
 PRODUCT_APEX_SYSTEM_SERVER_JARS := \
     com.android.appsearch:service-appsearch \
     com.android.art:service-art \
@@ -81,6 +83,7 @@
 
 # List of jars delivered via apex that system_server loads dynamically using separate classloaders.
 # Keep the list sorted by module names and then library names.
+# Note: For modules available in Q, DO NOT add new entries here.
 PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS := \
     com.android.os.statsd:service-statsd \
     com.android.scheduling:service-scheduling \
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 52754d4..e618226 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -92,6 +92,7 @@
 VNDK-core: android.hardware.radio.sim-V1-ndk.so
 VNDK-core: android.hardware.radio.voice-V1-ndk.so
 VNDK-core: android.hardware.rebootescrow-V1-ndk.so
+VNDK-core: android.hardware.security.dice-V1-ndk.so
 VNDK-core: android.hardware.security.keymint-V1-ndk.so
 VNDK-core: android.hardware.security.secureclock-V1-ndk.so
 VNDK-core: android.hardware.security.sharedsecret-V1-ndk.so
@@ -100,6 +101,7 @@
 VNDK-core: android.hardware.vibrator-V2-ndk.so
 VNDK-core: android.hardware.weaver-V1-ndk.so
 VNDK-core: android.hardware.wifi.hostapd-V1-ndk.so
+VNDK-core: android.hardware.wifi.supplicant-V1-ndk.so
 VNDK-core: android.hidl.token@1.0-utils.so
 VNDK-core: android.hidl.token@1.0.so
 VNDK-core: android.system.keystore2-V1-ndk.so
diff --git a/target/product/gsi_keys.mk b/target/product/gsi_keys.mk
deleted file mode 100644
index 5a814db..0000000
--- a/target/product/gsi_keys.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-# Include GSI keys into first-stage ramdisk, so we can enable verified
-# boot when booting a GSI.
-PRODUCT_PACKAGES += \
-    q-gsi.avbpubkey \
-    r-gsi.avbpubkey \
-    s-gsi.avbpubkey \
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index a979a8e..bf7f9a0 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -553,6 +553,19 @@
     ],
 }
 
+python_binary_host {
+    name: "fsverity_metadata_generator",
+    srcs: [
+        "fsverity_metadata_generator.py",
+    ],
+    libs: [
+        "fsverity_digests_proto_python",
+    ],
+    required: [
+        "fsverity",
+    ],
+}
+
 //
 // Tests.
 //
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 2a4b56b..0c39827 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -759,6 +759,7 @@
 
   has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
   has_boot = OPTIONS.info_dict.get("no_boot") != "true"
+  has_init_boot = OPTIONS.info_dict.get("init_boot") == "true"
   has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true"
 
   # {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm, system, system_other}.img
@@ -819,6 +820,17 @@
           if output_zip:
             boot_image.AddToZip(output_zip)
 
+  if has_init_boot:
+    banner("init_boot")
+    init_boot_image = common.GetBootableImage(
+        "IMAGES/init_boot.img", "init_boot.img", OPTIONS.input_tmp, "INIT_BOOT")
+    if init_boot_image:
+      partitions['init_boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES", "init_boot.img")
+      if not os.path.exists(partitions['init_boot']):
+        init_boot_image.WriteToDir(OPTIONS.input_tmp)
+        if output_zip:
+          init_boot_image.AddToZip(output_zip)
+
   if has_vendor_boot:
     banner("vendor_boot")
     vendor_boot_image = common.GetVendorBootImage(
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 64ac95a..6ec1b94 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -111,7 +111,7 @@
 # descriptor into vbmeta.img. When adding a new entry here, the
 # AVB_FOOTER_ARGS_BY_PARTITION in sign_target_files_apks need to be updated
 # accordingly.
-AVB_PARTITIONS = ('boot', 'dtbo', 'odm', 'product', 'pvmfw', 'recovery',
+AVB_PARTITIONS = ('boot', 'init_boot', 'dtbo', 'odm', 'product', 'pvmfw', 'recovery',
                   'system', 'system_ext', 'vendor', 'vendor_boot',
                   'vendor_dlkm', 'odm_dlkm')
 
@@ -130,7 +130,7 @@
 ]
 
 # Partitions with a build.prop file
-PARTITIONS_WITH_BUILD_PROP = PARTITIONS_WITH_CARE_MAP + ['boot']
+PARTITIONS_WITH_BUILD_PROP = PARTITIONS_WITH_CARE_MAP + ['boot', 'init_boot']
 
 # See sysprop.mk. If file is moved, add new search paths here; don't remove
 # existing search paths.
@@ -935,9 +935,9 @@
   def FromInputFile(input_file, name, placeholder_values=None, ramdisk_format=RamdiskFormat.LZ4):
     """Loads the build.prop file and builds the attributes."""
 
-    if name == "boot":
+    if name in ("boot", "init_boot"):
       data = PartitionBuildProps._ReadBootPropFile(
-          input_file, ramdisk_format=ramdisk_format)
+          input_file, name, ramdisk_format=ramdisk_format)
     else:
       data = PartitionBuildProps._ReadPartitionPropFile(input_file, name)
 
@@ -946,15 +946,16 @@
     return props
 
   @staticmethod
-  def _ReadBootPropFile(input_file, ramdisk_format):
+  def _ReadBootPropFile(input_file, partition_name, ramdisk_format):
     """
     Read build.prop for boot image from input_file.
     Return empty string if not found.
     """
+    image_path = 'IMAGES/' + partition_name + '.img'
     try:
-      boot_img = ExtractFromInputFile(input_file, 'IMAGES/boot.img')
+      boot_img = ExtractFromInputFile(input_file, image_path)
     except KeyError:
-      logger.warning('Failed to read IMAGES/boot.img')
+      logger.warning('Failed to read %s', image_path)
       return ''
     prop_file = GetBootImageBuildProp(boot_img, ramdisk_format=ramdisk_format)
     if prop_file is None:
@@ -1539,6 +1540,8 @@
       logger.info("Excluded kernel binary from recovery image.")
     else:
       kernel = "kernel"
+  elif partition_name == "init_boot":
+    pass
   else:
     kernel = image_name.replace("boot", "kernel")
     kernel = kernel.replace(".img", "")
@@ -1593,6 +1596,8 @@
       # Fall back to "mkbootimg_args" for recovery image
       # in case "recovery_mkbootimg_args" is not set.
       args = info_dict.get("mkbootimg_args")
+  elif partition_name == "init_boot":
+    args = info_dict.get("mkbootimg_init_args")
   else:
     args = info_dict.get("mkbootimg_args")
   if args and args.strip():
@@ -1752,9 +1757,11 @@
   logger.info("building image from target_files %s...", tree_subdir)
 
   # With system_root_image == "true", we don't pack ramdisk into the boot image.
+  # With init_boot == "true", we don't pack the ramdisk into boot.img.
   # Unless "recovery_as_boot" is specified, in which case we carry the ramdisk
   # for recovery.
-  has_ramdisk = (info_dict.get("system_root_image") != "true" or
+  has_ramdisk = ((info_dict.get("system_root_image") != "true" and
+                  info_dict.get("init_boot") != "true") or
                  prebuilt_name != "boot.img" or
                  info_dict.get("recovery_as_boot") == "true")
 
diff --git a/tools/releasetools/fsverity_metadata_generator.py b/tools/releasetools/fsverity_metadata_generator.py
index 666efd5..a300d2e 100644
--- a/tools/releasetools/fsverity_metadata_generator.py
+++ b/tools/releasetools/fsverity_metadata_generator.py
@@ -55,6 +55,9 @@
     self.set_hash_alg("sha256")
     self.set_signature('none')
 
+  def set_key_format(self, key_format):
+    self._key_format = key_format
+
   def set_key(self, key):
     self._key = key
 
@@ -130,14 +133,17 @@
       cmd.append(input_file)
       cmd.append(sig_file)
 
-      # convert DER private key to PEM
-      pem_key = os.path.join(work_dir, 'key.pem')
-      key_cmd = ['openssl', 'pkcs8']
-      key_cmd.extend(['-inform', 'DER'])
-      key_cmd.extend(['-in', self._key])
-      key_cmd.extend(['-nocrypt'])
-      key_cmd.extend(['-out', pem_key])
-      subprocess.check_call(key_cmd)
+      # If key is DER, convert DER private key to PEM
+      if self._key_format == 'der':
+        pem_key = os.path.join(work_dir, 'key.pem')
+        key_cmd = ['openssl', 'pkcs8']
+        key_cmd.extend(['-inform', 'DER'])
+        key_cmd.extend(['-in', self._key])
+        key_cmd.extend(['-nocrypt'])
+        key_cmd.extend(['-out', pem_key])
+        subprocess.check_call(key_cmd)
+      else:
+        pem_key = self._key
 
       cmd.extend(['--key', pem_key])
       cmd.extend(['--cert', self._cert])
@@ -196,8 +202,13 @@
       'input',
       help='input file to be signed')
   p.add_argument(
+      '--key-format',
+      choices=['pem', 'der'],
+      default='der',
+      help='format of the input key. Default is der')
+  p.add_argument(
       '--key',
-      help='PKCS#8 private key file in DER format')
+      help='PKCS#8 private key file')
   p.add_argument(
       '--cert',
       help='x509 certificate file in PEM format')
@@ -227,5 +238,6 @@
       raise ValueError("To generate signature, key and cert must be set")
     generator.set_key(args.key)
     generator.set_cert(args.cert)
+  generator.set_key_format(args.key_format)
   generator.set_hash_alg(args.hash_alg)
   generator.generate(args.input, args.output)
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index cbb51e1..0b2b187 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -124,7 +124,7 @@
 
   for image_path in [name for name in namelist if name.startswith('IMAGES/')]:
     image = os.path.basename(image_path)
-    if OPTIONS.bootable_only and image not in('boot.img', 'recovery.img', 'bootloader'):
+    if OPTIONS.bootable_only and image not in('boot.img', 'recovery.img', 'bootloader', 'init_boot.img'):
       continue
     if not image.endswith('.img') and image != 'bootloader':
       continue
diff --git a/tools/releasetools/sign_apex.py b/tools/releasetools/sign_apex.py
index 679f57a..66f5e05 100755
--- a/tools/releasetools/sign_apex.py
+++ b/tools/releasetools/sign_apex.py
@@ -141,7 +141,7 @@
       signing_args=options.get('payload_extra_args'),
       codename_to_api_level_map=options.get(
           'codename_to_api_level_map', {}),
-      sign_tool=options['sign_tool'])
+      sign_tool=options.get('sign_tool', None))
   shutil.copyfile(signed_apex, args[1])
   logger.info("done.")
 
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 5626980..3f65df1 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -201,6 +201,7 @@
 
 AVB_FOOTER_ARGS_BY_PARTITION = {
     'boot': 'avb_boot_add_hash_footer_args',
+    'init_boot': 'avb_init_boot_add_hash_footer_args',
     'dtbo': 'avb_dtbo_add_hash_footer_args',
     'product': 'avb_product_add_hashtree_footer_args',
     'recovery': 'avb_recovery_add_hash_footer_args',
@@ -608,7 +609,7 @@
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
 
     # Replace the certs in *mac_permissions.xml (there could be multiple, such
-    # as {system,vendor}/etc/selinux/{plat,nonplat}_mac_permissions.xml).
+    # as {system,vendor}/etc/selinux/{plat,vendor}_mac_permissions.xml).
     elif filename.endswith("mac_permissions.xml"):
       print("Rewriting %s with new keys." % (filename,))
       new_data = ReplaceCerts(data.decode())
diff --git a/tools/releasetools/test_apex_utils.py b/tools/releasetools/test_apex_utils.py
index ed920f2..2aa6f6c 100644
--- a/tools/releasetools/test_apex_utils.py
+++ b/tools/releasetools/test_apex_utils.py
@@ -198,8 +198,9 @@
 
     # pass `false` as a sign_tool to see the invocation error
     with self.assertRaises(common.ExternalError) as cm:
-        signer = apex_utils.ApexApkSigner(apex_path, None, None, sign_tool='false')
-        signer.ProcessApexFile(apk_keys, self.payload_key)
+      signer = apex_utils.ApexApkSigner(
+          apex_path, None, None, sign_tool='false')
+      signer.ProcessApexFile(apk_keys, self.payload_key)
 
     the_exception = cm.exception
-    self.assertIn('Failed to run command \'[\'false\'', the_exception.message)
+    self.assertIn('Failed to run command \'[\'false\'', str(the_exception))
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 92dca9a..0f13add 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -62,6 +62,9 @@
       'avb_boot_add_hash_footer_args':
           ('--prop com.android.build.boot.os_version:R '
            '--prop com.android.build.boot.security_patch:2019-09-05'),
+      'avb_init_boot_add_hash_footer_args':
+          ('--prop com.android.build.boot.os_version:R '
+           '--prop com.android.build.boot.security_patch:2019-09-05'),
       'avb_system_add_hashtree_footer_args':
           ('--prop com.android.build.system.os_version:R '
            '--prop com.android.build.system.security_patch:2019-09-05 '
@@ -77,6 +80,9 @@
       'avb_boot_add_hash_footer_args':
           ('--prop com.android.build.boot.os_version:R '
            '--prop com.android.build.boot.security_patch:2019-09-05'),
+      'avb_init_boot_add_hash_footer_args':
+          ('--prop com.android.build.boot.os_version:R '
+           '--prop com.android.build.boot.security_patch:2019-09-05'),
       'avb_system_add_hashtree_footer_args':
           ('--prop com.android.build.system.os_version:R '
            '--prop com.android.build.system.security_patch:2019-09-05 '
diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java
index 232e119..c127dbe 100644
--- a/tools/signapk/src/com/android/signapk/SignApk.java
+++ b/tools/signapk/src/com/android/signapk/SignApk.java
@@ -204,26 +204,23 @@
      * If a console doesn't exist, reads the password from stdin
      * If a console exists, reads the password from console and returns it as a string.
      *
-     * @param keyFile The file containing the private key.  Used to prompt the user.
+     * @param keyFileName Name of the file containing the private key.  Used to prompt the user.
      */
-    private static String readPassword(File keyFile) {
+    private static char[] readPassword(String keyFileName) {
         Console console;
-        char[] pwd;
         if ((console = System.console()) == null) {
-            System.out.print("Enter password for " + keyFile + " (password will not be hidden): ");
+            System.out.print(
+                "Enter password for " + keyFileName + " (password will not be hidden): ");
             System.out.flush();
             BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
             try {
-                return stdin.readLine();
+                String result = stdin.readLine();
+                return result == null ? null : result.toCharArray();
             } catch (IOException ex) {
                 return null;
             }
         } else {
-            if ((pwd = console.readPassword("[%s]", "Enter password for " + keyFile)) != null) {
-                return String.valueOf(pwd);
-            } else {
-                return null;
-            }
+            return console.readPassword("[%s]", "Enter password for " + keyFileName);
         }
     }
 
@@ -246,11 +243,8 @@
             return null;
         }
 
-        char[] password = readPassword(keyFile).toCharArray();
-
         SecretKeyFactory skFactory = SecretKeyFactory.getInstance(epkInfo.getAlgName());
-        Key key = skFactory.generateSecret(new PBEKeySpec(password));
-
+        Key key = skFactory.generateSecret(new PBEKeySpec(readPassword(keyFile.getPath())));
         Cipher cipher = Cipher.getInstance(epkInfo.getAlgName());
         cipher.init(Cipher.DECRYPT_MODE, key, epkInfo.getAlgParameters());
 
@@ -305,10 +299,10 @@
 
     /** Get a PKCS#11 private key from keyStore */
     private static PrivateKey loadPrivateKeyFromKeyStore(
-            final KeyStore keyStore, final String keyName, final String password)
+            final KeyStore keyStore, final String keyName)
             throws CertificateException, KeyStoreException, NoSuchAlgorithmException,
                     UnrecoverableKeyException, UnrecoverableEntryException {
-        final Key key = keyStore.getKey(keyName, password == null ? null : password.toCharArray());
+        final Key key = keyStore.getKey(keyName, readPassword(keyName));
         final PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) keyStore.getEntry(keyName, null);
         if (privateKeyEntry == null) {
         throw new Error(
@@ -1201,10 +1195,8 @@
                 if (keyStore == null) {
                     privateKey[i] = readPrivateKey(new File(args[argNum]));
                 } else {
-                    String[] splits = args[argNum].split(":", 2);
-                    final String keyAlias = splits[0];
-                    final String password = splits.length > 1 ? splits[1] : null;
-                    privateKey[i] = loadPrivateKeyFromKeyStore(keyStore, keyAlias, password);
+                    final String keyAlias = args[argNum];
+                    privateKey[i] = loadPrivateKeyFromKeyStore(keyStore, keyAlias);
                 }
             }
             inputJar = new JarFile(new File(inputFilename), false);  // Don't verify.