Merge "Add new llndk library, libneuralnetworks_shim.so"
diff --git a/core/Makefile b/core/Makefile
index 191c0eb..99df084 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -856,6 +856,23 @@
     --os_version $(PLATFORM_VERSION_LAST_STABLE) \
     --os_patch_level $(PLATFORM_SECURITY_PATCH)
 
+ifdef BOARD_GKI_SIGNING_KEY_PATH
+ifndef BOARD_GKI_SIGNING_ALGORITHM
+$(error BOARD_GKI_SIGNING_ALGORITHM should be defined with BOARD_GKI_SIGNING_KEY_PATH)
+endif
+INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS := \
+    --gki_signing_key $(BOARD_GKI_SIGNING_KEY_PATH) \
+    --gki_signing_algorithm $(BOARD_GKI_SIGNING_ALGORITHM) \
+    --gki_signing_avbtool_path $(AVBTOOL)
+endif
+
+# Using double quote to pass BOARD_GKI_SIGNING_SIGNATURE_ARGS as a single string
+# to MKBOOTIMG, although it may contain multiple args.
+ifdef BOARD_GKI_SIGNING_SIGNATURE_ARGS
+INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS += \
+    --gki_signing_signature_args "$(BOARD_GKI_SIGNING_SIGNATURE_ARGS)"
+endif
+
 # Define these only if we are building boot
 ifdef BUILDING_BOOT_IMAGE
 INSTALLED_BOOTIMAGE_TARGET := $(BUILT_BOOTIMAGE_TARGET)
@@ -870,7 +887,8 @@
 
 # $1: boot image target
 define build_boot_board_avb_enabled
-  $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
+  $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
+               $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
   $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot)))
   $(AVBTOOL) add_hash_footer \
           --image $(1) \
@@ -879,12 +897,12 @@
           $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
 endef
 
-$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH)
+$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) $(BOARD_GKI_SIGNING_KEY_PATH)
 	$(call pretty,"Target boot image: $@")
 	$(call build_boot_board_avb_enabled,$@)
 
 .PHONY: bootimage-nodeps
-bootimage-nodeps: $(MKBOOTIMG) $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH)
+bootimage-nodeps: $(MKBOOTIMG) $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH) $(BOARD_GKI_SIGNING_KEY_PATH)
 	@echo "make $@: ignoring dependencies"
 	$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_board_avb_enabled,$(b)))
 
@@ -2149,8 +2167,8 @@
                  $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_RECOVERY_MKBOOTIMG_ARGS) \
                  --output $(1).unsigned, \
     $(MKBOOTIMG) $(if $(strip $(2)),--kernel $(strip $(2))) $(INTERNAL_RECOVERYIMAGE_ARGS) \
-                 $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_RECOVERY_MKBOOTIMG_ARGS) \
-                 --output $(1))
+                 $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) \
+                 $(BOARD_RECOVERY_MKBOOTIMG_ARGS) --output $(1))
   $(if $(filter true,$(PRODUCT_SUPPORTS_BOOT_SIGNER)),\
     $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
       $(BOOT_SIGNER) /boot $(1) $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1),\
@@ -2178,6 +2196,9 @@
 ifeq (true,$(BOARD_AVB_ENABLE))
   recoveryimage-deps += $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH)
 endif
+ifdef BOARD_GKI_SIGNING_KEY_PATH
+  recoveryimage-deps += $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
+endif
 ifdef BOARD_INCLUDE_RECOVERY_DTBO
   ifdef BOARD_PREBUILT_RECOVERY_DTBOIMAGE
     recoveryimage-deps += $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE)
@@ -2353,17 +2374,18 @@
 # $(1): output file
 define build-debug-bootimage-target
   $(MKBOOTIMG) --kernel $(PRODUCT_OUT)/$(subst .img,,$(subst boot-debug,kernel,$(notdir $(1)))) \
-    $(INTERNAL_DEBUG_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $1
+    $(INTERNAL_DEBUG_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
+    $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $1
   $(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$1,boot-debug))
 endef
 
 # Depends on original boot.img and ramdisk-debug.img, to build the new boot-debug.img
-$(INSTALLED_DEBUG_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_DEBUG_RAMDISK_TARGET)
+$(INSTALLED_DEBUG_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_DEBUG_RAMDISK_TARGET) $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
 	$(call pretty,"Target boot debug image: $@")
 	$(call build-debug-bootimage-target, $@)
 
 .PHONY: bootimage_debug-nodeps
-bootimage_debug-nodeps: $(MKBOOTIMG)
+bootimage_debug-nodeps: $(MKBOOTIMG) $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
 	echo "make $@: ignoring dependencies"
 	$(foreach b,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),$(call build-debug-bootimage-target,$b))
 
@@ -2528,17 +2550,19 @@
 # $(1): output file
 define build-boot-test-harness-target
   $(MKBOOTIMG) --kernel $(PRODUCT_OUT)/$(subst .img,,$(subst boot-test-harness,kernel,$(notdir $(1)))) \
-    $(INTERNAL_TEST_HARNESS_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
+    $(INTERNAL_TEST_HARNESS_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
+    $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
   $(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$@,boot-test-harness))
 endef
 
 # Build the new boot-test-harness.img, based on boot-debug.img and ramdisk-test-harness.img.
-$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
+$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET) \
+$(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
 	$(call pretty,"Target boot test harness image: $@")
 	$(call build-boot-test-harness-target,$@)
 
 .PHONY: bootimage_test_harness-nodeps
-bootimage_test_harness-nodeps: $(MKBOOTIMG)
+bootimage_test_harness-nodeps: $(MKBOOTIMG) $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
 	echo "make $@: ignoring dependencies"
 	$(foreach b,$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET),$(call build-boot-test-harness-target,$b))
 
@@ -3883,24 +3907,6 @@
 endif # check_vintf_vendor_deps
 check_vintf_vendor_deps :=
 
-# -- Check VINTF compatibility of build.
-# Skip partial builds; only check full builds. Only check if:
-# - PRODUCT_ENFORCE_VINTF_MANIFEST is true
-# - system / vendor VINTF metadata exists
-# - Building product / system_ext / odm images if board has product / system_ext / odm images
-ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
-ifeq ($(check_vintf_has_system),true)
-ifeq ($(check_vintf_has_vendor),true)
-ifeq ($(filter true,$(BUILDING_ODM_IMAGE)),$(filter true,$(BOARD_USES_ODMIMAGE)))
-ifeq ($(filter true,$(BUILDING_PRODUCT_IMAGE)),$(filter true,$(BOARD_USES_PRODUCTIMAGE)))
-ifeq ($(filter true,$(BUILDING_SYSTEM_EXT_IMAGE)),$(filter true,$(BOARD_USES_SYSTEM_EXTIMAGE)))
-
-check_vintf_compatible_log := $(intermediates)/check_vintf_compatible.log
-check_vintf_all_deps += $(check_vintf_compatible_log)
-
-check_vintf_compatible_args :=
-check_vintf_compatible_deps := $(check_vintf_common_srcs)
-
 # -- Kernel version and configurations.
 ifeq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),true)
 
@@ -3954,9 +3960,29 @@
 
 endif # INSTALLED_KERNEL_TARGET
 
+endif # PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
+
+# -- Check VINTF compatibility of build.
+# Skip partial builds; only check full builds. Only check if:
+# - PRODUCT_ENFORCE_VINTF_MANIFEST is true
+# - system / vendor VINTF metadata exists
+# - Building product / system_ext / odm images if board has product / system_ext / odm images
+ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
+ifeq ($(check_vintf_has_system),true)
+ifeq ($(check_vintf_has_vendor),true)
+ifeq ($(filter true,$(BUILDING_ODM_IMAGE)),$(filter true,$(BOARD_USES_ODMIMAGE)))
+ifeq ($(filter true,$(BUILDING_PRODUCT_IMAGE)),$(filter true,$(BOARD_USES_PRODUCTIMAGE)))
+ifeq ($(filter true,$(BUILDING_SYSTEM_EXT_IMAGE)),$(filter true,$(BOARD_USES_SYSTEM_EXTIMAGE)))
+
+check_vintf_compatible_log := $(intermediates)/check_vintf_compatible.log
+check_vintf_all_deps += $(check_vintf_compatible_log)
+
+check_vintf_compatible_args :=
+check_vintf_compatible_deps := $(check_vintf_common_srcs)
+
+ifeq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),true)
 check_vintf_compatible_args += --kernel $(BUILT_KERNEL_VERSION_FILE):$(BUILT_KERNEL_CONFIGS_FILE)
 check_vintf_compatible_deps += $(BUILT_KERNEL_CONFIGS_FILE) $(BUILT_KERNEL_VERSION_FILE)
-
 endif # PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
 
 check_vintf_compatible_args += \
@@ -4324,6 +4350,13 @@
 	$(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)' >> $@
+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)' >> $@
+endif
+ifdef BOARD_GKI_SIGNING_SIGNATURE_ARGS
+	$(hide) echo 'gki_signing_signature_args=$(BOARD_GKI_SIGNING_SIGNATURE_ARGS)' >> $@
+endif
 	$(hide) echo "multistage_support=1" >> $@
 	$(hide) echo "blockimgdiff_versions=3,4" >> $@
 ifeq ($(PRODUCT_BUILD_GENERIC_OTA_PACKAGE),true)
diff --git a/core/app_prebuilt_internal.mk b/core/app_prebuilt_internal.mk
index 829a640..fe04b84 100644
--- a/core/app_prebuilt_internal.mk
+++ b/core/app_prebuilt_internal.mk
@@ -92,55 +92,6 @@
 endif
 endif
 
-# Verify LOCAL_USES_LIBRARIES/LOCAL_OPTIONAL_USES_LIBRARIES
-# If LOCAL_ENFORCE_USES_LIBRARIES is not set, default to true if either of LOCAL_USES_LIBRARIES or
-# LOCAL_OPTIONAL_USES_LIBRARIES are specified.
-# Will change the default to true unconditionally in the future.
-ifndef LOCAL_ENFORCE_USES_LIBRARIES
-  ifneq (,$(strip $(LOCAL_USES_LIBRARIES)$(LOCAL_OPTIONAL_USES_LIBRARIES)))
-    LOCAL_ENFORCE_USES_LIBRARIES := true
-  endif
-endif
-
-# Disable verify_uses_libraries check if dexpreopt is globally disabled.
-# Without dexpreopt the check is not necessary, and although it is good to have,
-# it is difficult to maintain on non-linux build platforms where dexpreopt is
-# generally disabled (the check may fail due to various unrelated reasons, such
-# as a failure to get manifest from an APK).
-ifneq ($(WITH_DEXPREOPT),true)
-  LOCAL_ENFORCE_USES_LIBRARIES :=
-endif
-
-my_enforced_uses_libraries :=
-ifdef LOCAL_ENFORCE_USES_LIBRARIES
-  my_verify_script := build/soong/scripts/manifest_check.py
-  my_uses_libs := $(patsubst %,--uses-library %,$(LOCAL_USES_LIBRARIES))
-  my_optional_uses_libs := $(patsubst %,--optional-uses-library %, \
-    $(LOCAL_OPTIONAL_USES_LIBRARIES))
-  my_relax_check := $(if $(filter true,$(RELAX_USES_LIBRARY_CHECK)), \
-    --enforce-uses-libraries-relax,)
-  my_enforced_uses_libraries := $(intermediates.COMMON)/enforce_uses_libraries.status
-  $(my_enforced_uses_libraries): PRIVATE_USES_LIBRARIES := $(my_uses_libs)
-  $(my_enforced_uses_libraries): PRIVATE_OPTIONAL_USES_LIBRARIES := $(my_optional_uses_libs)
-  $(my_enforced_uses_libraries): PRIVATE_RELAX_CHECK := $(my_relax_check)
-  $(my_enforced_uses_libraries): $(AAPT)
-  $(my_enforced_uses_libraries): $(my_verify_script)
-  $(my_enforced_uses_libraries): $(my_prebuilt_src_file)
-	@echo Verifying uses-libraries: $<
-	rm -f $@
-	$(my_verify_script) \
-	  --enforce-uses-libraries \
-	  --enforce-uses-libraries-status $@ \
-	  --aapt $(AAPT) \
-	  $(PRIVATE_USES_LIBRARIES) \
-	  $(PRIVATE_OPTIONAL_USES_LIBRARIES) \
-	  $(PRIVATE_RELAX_CHECK) \
-	  $<
-  $(built_module) : $(my_enforced_uses_libraries)
-endif
-
-dex_preopt_profile_src_file := $(my_prebuilt_src_file)
-
 rs_compatibility_jni_libs :=
 include $(BUILD_SYSTEM)/install_jni_libs.mk
 
@@ -218,6 +169,8 @@
 endif
 
 my_dex_jar := $(my_prebuilt_src_file)
+my_manifest_or_apk := $(my_prebuilt_src_file)
+dex_preopt_profile_src_file := $(my_prebuilt_src_file)
 
 #######################################
 # defines built_odex along with rule to install odex
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index cbd3069..560a555 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -1,5 +1,6 @@
 # dexpreopt_odex_install.mk is used to define odex creation rules for JARs and APKs
 # This file depends on variables set in base_rules.mk
+# Input variables: my_manifest_or_apk
 # Output variables: LOCAL_DEX_PREOPT, LOCAL_UNCOMPRESS_DEX
 
 ifeq (true,$(LOCAL_USE_EMBEDDED_DEX))
@@ -30,8 +31,9 @@
   LOCAL_DEX_PREOPT :=
 endif
 
-# Only enable preopt for non tests.
+# Disable <uses-library> checks and preopt for tests.
 ifneq (,$(filter $(LOCAL_MODULE_TAGS),tests))
+  LOCAL_ENFORCE_USES_LIBRARIES := false
   LOCAL_DEX_PREOPT :=
 endif
 
@@ -45,8 +47,14 @@
   LOCAL_DEX_PREOPT :=
 endif
 
-# Disable preopt if not WITH_DEXPREOPT
+# Disable <uses-library> checks and preopt if not WITH_DEXPREOPT
+#
+# Without dexpreopt the check is not necessary, and although it is good to have,
+# it is difficult to maintain on non-linux build platforms where dexpreopt is
+# generally disabled (the check may fail due to various unrelated reasons, such
+# as a failure to get manifest from an APK).
 ifneq (true,$(WITH_DEXPREOPT))
+  LOCAL_ENFORCE_USES_LIBRARIES := false
   LOCAL_DEX_PREOPT :=
 endif
 
@@ -54,7 +62,9 @@
   LOCAL_DEX_PREOPT :=
 endif
 
-ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file)$(LOCAL_SOONG_DEX_JAR))) # contains no java code
+# Disable <uses-library> checks and preopt if the app contains no java code.
+ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file)$(LOCAL_SOONG_DEX_JAR)))
+  LOCAL_ENFORCE_USES_LIBRARIES := false
   LOCAL_DEX_PREOPT :=
 endif
 
@@ -108,6 +118,137 @@
   endif
 endif
 
+################################################################################
+# Local module variables and functions used in dexpreopt and manifest_check.
+################################################################################
+
+my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \
+  $(LOCAL_OPTIONAL_USES_LIBRARIES))
+
+# TODO(b/132357300): This may filter out too much, as PRODUCT_PACKAGES doesn't
+# include all packages (the full list is unknown until reading all Android.mk
+# makefiles). As a consequence, a library may be present but not included in
+# dexpreopt, which will result in class loader context mismatch and a failure
+# to load dexpreopt code on device. We should fix this, either by deferring
+# dependency computation until the full list of product packages is known, or
+# by adding product-specific lists of missing libraries.
+my_filtered_optional_uses_libraries := $(filter $(PRODUCT_PACKAGES), \
+  $(my_filtered_optional_uses_libraries))
+
+ifeq ($(LOCAL_MODULE_CLASS),APPS)
+  # compatibility libraries are added to class loader context of an app only if
+  # targetSdkVersion in the app's manifest is lower than the given SDK version
+
+  my_dexpreopt_libs_compat_28 := \
+    org.apache.http.legacy
+
+  my_dexpreopt_libs_compat_29 := \
+    android.hidl.manager-V1.0-java \
+    android.hidl.base-V1.0-java
+
+  my_dexpreopt_libs_compat_30 := \
+    android.test.base \
+    android.test.mock
+
+  my_dexpreopt_libs_compat := \
+    $(my_dexpreopt_libs_compat_28) \
+    $(my_dexpreopt_libs_compat_29) \
+    $(my_dexpreopt_libs_compat_30)
+else
+  my_dexpreopt_libs_compat :=
+endif
+
+my_dexpreopt_libs := \
+  $(LOCAL_USES_LIBRARIES) \
+  $(my_filtered_optional_uses_libraries)
+
+# Module dexpreopt.config depends on dexpreopt.config files of each
+# <uses-library> dependency, because these libraries may be processed after
+# the current module by Make (there's no topological order), so the dependency
+# information (paths, class loader context) may not be ready yet by the time
+# this dexpreopt.config is generated. So it's necessary to add file-level
+# dependencies between dexpreopt.config files.
+my_dexpreopt_dep_configs := $(foreach lib, \
+  $(filter-out $(my_dexpreopt_libs_compat),$(LOCAL_USES_LIBRARIES) $(my_filtered_optional_uses_libraries)), \
+  $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,)/dexpreopt.config)
+
+# 1: SDK version
+# 2: list of libraries
+#
+# Make does not process modules in topological order wrt. <uses-library>
+# dependencies, therefore we cannot rely on variables to get the information
+# about dependencies (in particular, their on-device path and class loader
+# context). This information is communicated via dexpreopt.config files: each
+# config depends on configs for <uses-library> dependencies of this module,
+# and the dex_preopt_config_merger.py script reads all configs and inserts the
+# missing bits from dependency configs into the module config.
+#
+# By default on-device path is /system/framework/*.jar, and class loader
+# subcontext is empty. These values are correct for compatibility libraries,
+# which are special and not handled by dex_preopt_config_merger.py.
+#
+add_json_class_loader_context = \
+  $(call add_json_array, $(1)) \
+  $(foreach lib, $(2),\
+    $(call add_json_map_anon) \
+    $(call add_json_str, Name, $(lib)) \
+    $(call add_json_str, Host, $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \
+    $(call add_json_str, Device, /system/framework/$(lib).jar) \
+    $(call add_json_val, Subcontexts, null) \
+    $(call end_json_map)) \
+  $(call end_json_array)
+
+################################################################################
+# Verify <uses-library> coherence between the build system and the manifest.
+################################################################################
+
+# Verify LOCAL_USES_LIBRARIES/LOCAL_OPTIONAL_USES_LIBRARIES
+# If LOCAL_ENFORCE_USES_LIBRARIES is not set, default to true if either of LOCAL_USES_LIBRARIES or
+# LOCAL_OPTIONAL_USES_LIBRARIES are specified.
+# Will change the default to true unconditionally in the future.
+ifndef LOCAL_ENFORCE_USES_LIBRARIES
+  ifneq (,$(strip $(LOCAL_USES_LIBRARIES)$(LOCAL_OPTIONAL_USES_LIBRARIES)))
+    LOCAL_ENFORCE_USES_LIBRARIES := true
+  endif
+endif
+
+my_enforced_uses_libraries :=
+ifeq (true,$(LOCAL_ENFORCE_USES_LIBRARIES))
+  my_verify_script := build/soong/scripts/manifest_check.py
+  my_uses_libs_args := $(patsubst %,--uses-library %,$(LOCAL_USES_LIBRARIES))
+  my_optional_uses_libs_args := $(patsubst %,--optional-uses-library %, \
+    $(LOCAL_OPTIONAL_USES_LIBRARIES))
+  my_relax_check_arg := $(if $(filter true,$(RELAX_USES_LIBRARY_CHECK)), \
+    --enforce-uses-libraries-relax,)
+  my_dexpreopt_config_args := $(patsubst %,--dexpreopt-config %,$(my_dexpreopt_dep_configs))
+
+  my_enforced_uses_libraries := $(intermediates.COMMON)/enforce_uses_libraries.status
+  $(my_enforced_uses_libraries): PRIVATE_USES_LIBRARIES := $(my_uses_libs_args)
+  $(my_enforced_uses_libraries): PRIVATE_OPTIONAL_USES_LIBRARIES := $(my_optional_uses_libs_args)
+  $(my_enforced_uses_libraries): PRIVATE_DEXPREOPT_CONFIGS := $(my_dexpreopt_config_args)
+  $(my_enforced_uses_libraries): PRIVATE_RELAX_CHECK := $(my_relax_check_arg)
+  $(my_enforced_uses_libraries): $(AAPT)
+  $(my_enforced_uses_libraries): $(my_verify_script)
+  $(my_enforced_uses_libraries): $(my_dexpreopt_dep_configs)
+  $(my_enforced_uses_libraries): $(my_manifest_or_apk)
+	@echo Verifying uses-libraries: $<
+	rm -f $@
+	$(my_verify_script) \
+	  --enforce-uses-libraries \
+	  --enforce-uses-libraries-status $@ \
+	  --aapt $(AAPT) \
+	  $(PRIVATE_USES_LIBRARIES) \
+	  $(PRIVATE_OPTIONAL_USES_LIBRARIES) \
+	  $(PRIVATE_DEXPREOPT_CONFIGS) \
+	  $(PRIVATE_RELAX_CHECK) \
+	  $<
+  $(built_module) : $(my_enforced_uses_libraries)
+endif
+
+################################################################################
+# Dexpreopt command.
+################################################################################
+
 my_dexpreopt_archs :=
 my_dexpreopt_images :=
 my_dexpreopt_images_deps :=
@@ -186,72 +327,6 @@
 
   my_dexpreopt_image_locations += $(DEXPREOPT_IMAGE_LOCATIONS_$(my_dexpreopt_infix))
 
-  my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \
-    $(LOCAL_OPTIONAL_USES_LIBRARIES))
-
-  # TODO(b/132357300): This may filter out too much, as PRODUCT_PACKAGES doesn't
-  # include all packages (the full list is unknown until reading all Android.mk
-  # makefiles). As a consequence, a library may be present but not included in
-  # dexpreopt, which will result in class loader context mismatch and a failure
-  # to load dexpreopt code on device. We should fix this, either by deferring
-  # dependency computation until the full list of product packages is known, or
-  # by adding product-specific lists of missing libraries.
-  my_filtered_optional_uses_libraries := $(filter $(PRODUCT_PACKAGES), \
-    $(my_filtered_optional_uses_libraries))
-
-  ifeq ($(LOCAL_MODULE_CLASS),APPS)
-    # compatibility libraries are added to class loader context of an app only if
-    # targetSdkVersion in the app's manifest is lower than the given SDK version
-
-    my_dexpreopt_libs_compat_28 := \
-      org.apache.http.legacy
-
-    my_dexpreopt_libs_compat_29 := \
-      android.hidl.base-V1.0-java \
-      android.hidl.manager-V1.0-java
-
-    my_dexpreopt_libs_compat_30 := \
-      android.test.base \
-      android.test.mock
-
-    my_dexpreopt_libs_compat := \
-      $(my_dexpreopt_libs_compat_28) \
-      $(my_dexpreopt_libs_compat_29) \
-      $(my_dexpreopt_libs_compat_30)
-  else
-    my_dexpreopt_libs_compat :=
-  endif
-
-  my_dexpreopt_libs := \
-    $(LOCAL_USES_LIBRARIES) \
-    $(my_filtered_optional_uses_libraries)
-
-  # 1: SDK version
-  # 2: list of libraries
-  #
-  # Make does not process modules in topological order wrt. <uses-library>
-  # dependencies, therefore we cannot rely on variables to get the information
-  # about dependencies (in particular, their on-device path and class loader
-  # context). This information is communicated via dexpreopt.config files: each
-  # config depends on configs for <uses-library> dependencies of this module,
-  # and the dex_preopt_config_merger.py script reads all configs and inserts the
-  # missing bits from dependency configs into the module config.
-  #
-  # By default on-device path is /system/framework/*.jar, and class loader
-  # subcontext is empty. These values are correct for compatibility libraries,
-  # which are special and not handled by dex_preopt_config_merger.py.
-  #
-  add_json_class_loader_context = \
-    $(call add_json_array, $(1)) \
-    $(foreach lib, $(2),\
-      $(call add_json_map_anon) \
-      $(call add_json_str, Name, $(lib)) \
-      $(call add_json_str, Host, $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \
-      $(call add_json_str, Device, /system/framework/$(lib).jar) \
-      $(call add_json_val, Subcontexts, null) \
-      $(call end_json_map)) \
-    $(call end_json_array)
-
   # Record dex-preopt config.
   DEXPREOPT.$(LOCAL_MODULE).DEX_PREOPT := $(LOCAL_DEX_PREOPT)
   DEXPREOPT.$(LOCAL_MODULE).MULTILIB := $(LOCAL_MULTILIB)
@@ -278,7 +353,7 @@
   $(call add_json_list, PreoptFlags,                    $(LOCAL_DEX_PREOPT_FLAGS))
   $(call add_json_str,  ProfileClassListing,            $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE)))
   $(call add_json_bool, ProfileIsTextListing,           $(my_profile_is_text_listing))
-  $(call add_json_str,  EnforceUsesLibrariesStatusFile, $(intermediates.COMMON)/enforce_uses_libraries.status)
+  $(call add_json_str,  EnforceUsesLibrariesStatusFile, $(my_enforced_uses_libraries))
   $(call add_json_bool, EnforceUsesLibraries,           $(LOCAL_ENFORCE_USES_LIBRARIES))
   $(call add_json_str,  ProvidesUsesLibrary,            $(firstword $(LOCAL_PROVIDES_USES_LIBRARY) $(LOCAL_MODULE)))
   $(call add_json_map,  ClassLoaderContexts)
@@ -304,16 +379,6 @@
   my_dexpreopt_zip := $(intermediates)/dexpreopt.zip
   my_dexpreopt_config_merger := $(BUILD_SYSTEM)/dex_preopt_config_merger.py
 
-  # Module dexpreopt.config depends on dexpreopt.config files of each
-  # <uses-library> dependency, because these libraries may be processed after
-  # the current module by Make (there's no topological order), so the dependency
-  # information (paths, class loader context) may not be ready yet by the time
-  # this dexpreopt.config is generated. So it's necessary to add file-level
-  # dependencies between dexpreopt.config files.
-  my_dexpreopt_dep_configs := $(foreach lib, \
-    $(filter-out $(my_dexpreopt_libs_compat),$(LOCAL_USES_LIBRARIES) $(my_filtered_optional_uses_libraries)), \
-    $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,)/dexpreopt.config)
-
   $(my_dexpreopt_config): $(my_dexpreopt_dep_configs) $(my_dexpreopt_config_merger)
   $(my_dexpreopt_config): PRIVATE_MODULE := $(LOCAL_MODULE)
   $(my_dexpreopt_config): PRIVATE_CONTENTS := $(json_contents)
diff --git a/core/java.mk b/core/java.mk
index d28c0c4..3f147ba 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -176,7 +176,9 @@
 
 #######################################
 # defines built_odex along with rule to install odex
+my_manifest_or_apk := $(full_android_manifest)
 include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
+my_manifest_or_apk :=
 #######################################
 
 # Make sure there's something to build.
diff --git a/core/java_prebuilt_internal.mk b/core/java_prebuilt_internal.mk
index 279b0e4..990b7d4 100644
--- a/core/java_prebuilt_internal.mk
+++ b/core/java_prebuilt_internal.mk
@@ -33,6 +33,7 @@
 
 ifeq ($(prebuilt_module_is_dex_javalib),true)
 my_dex_jar := $(my_prebuilt_src_file)
+my_manifest_or_apk := $(my_prebuilt_src_file)
 # This is a target shared library, i.e. a jar with classes.dex.
 
 $(foreach pair,$(PRODUCT_BOOT_JARS), \
@@ -43,7 +44,9 @@
 
 #######################################
 # defines built_odex along with rule to install odex
+my_manifest_or_apk := $(my_prebuilt_src_file)
 include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
+my_manifest_or_apk :=
 #######################################
 $(built_module) : $(my_prebuilt_src_file)
 	$(call copy-file-to-target)
diff --git a/core/main.mk b/core/main.mk
index e2dde2d..56950ec 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1870,7 +1870,7 @@
 ndk: $(SOONG_OUT_DIR)/ndk.timestamp
 .PHONY: ndk
 
-# Checks that build/soong/apex/allowed_deps.txt remains up to date
+# Checks that allowed_deps.txt remains up to date
 ifneq ($(UNSAFE_DISABLE_APEX_ALLOWED_DEPS_CHECK),true)
   droidcore: ${APEX_ALLOWED_DEPS_CHECK}
 endif
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 346ca24..9f5a599 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -472,31 +472,6 @@
 # Set a actual_partition_tag (calculated in base_rules.mk) for the package.
 PACKAGES.$(LOCAL_PACKAGE_NAME).PARTITION := $(actual_partition_tag)
 
-# Verify LOCAL_USES_LIBRARIES/LOCAL_OPTIONAL_USES_LIBRARIES
-# If LOCAL_ENFORCE_USES_LIBRARIES is not set, default to true if either of LOCAL_USES_LIBRARIES or
-# LOCAL_OPTIONAL_USES_LIBRARIES are specified.
-# Will change the default to true unconditionally in the future.
-ifndef LOCAL_ENFORCE_USES_LIBRARIES
-  ifneq (,$(strip $(LOCAL_USES_LIBRARIES)$(LOCAL_OPTIONAL_USES_LIBRARIES)))
-    LOCAL_ENFORCE_USES_LIBRARIES := true
-  endif
-endif
-
-my_enforced_uses_libraries :=
-ifdef LOCAL_ENFORCE_USES_LIBRARIES
-  my_manifest_check := $(intermediates.COMMON)/manifest/AndroidManifest.xml.check
-  $(my_manifest_check): $(MANIFEST_CHECK)
-  $(my_manifest_check): PRIVATE_USES_LIBRARIES := $(LOCAL_USES_LIBRARIES)
-  $(my_manifest_check): PRIVATE_OPTIONAL_USES_LIBRARIES := $(LOCAL_OPTIONAL_USES_LIBRARIES)
-  $(my_manifest_check): $(full_android_manifest)
-	@echo Checking manifest: $<
-	$(MANIFEST_CHECK) --enforce-uses-libraries \
-	  $(addprefix --uses-library ,$(PRIVATE_USES_LIBRARIES)) \
-	  $(addprefix --optional-uses-library ,$(PRIVATE_OPTIONAL_USES_LIBRARIES)) \
-	  $< -o $@
-  $(LOCAL_BUILT_MODULE): $(my_manifest_check)
-endif
-
 # Define the rule to build the actual package.
 # PRIVATE_JNI_SHARED_LIBRARIES is a list of <abi>:<path_of_built_lib>.
 $(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index b4992fe..597ea78 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -199,6 +199,8 @@
 $(call add_json_list, BoardSepolicyM4Defs,               $(BOARD_SEPOLICY_M4DEFS))
 $(call add_json_str,  BoardSepolicyVers,                 $(BOARD_SEPOLICY_VERS))
 
+$(call add_json_str,  PlatformSepolicyVersion,           $(PLATFORM_SEPOLICY_VERSION))
+
 $(call add_json_bool, Flatten_apex,                      $(filter true,$(TARGET_FLATTEN_APEX)))
 $(call add_json_bool, ForceApexSymlinkOptimization,      $(filter true,$(TARGET_FORCE_APEX_SYMLINK_OPTIMIZATION)))
 
diff --git a/target/product/OWNERS b/target/product/OWNERS
index 259c8f4..82e6e88 100644
--- a/target/product/OWNERS
+++ b/target/product/OWNERS
@@ -1 +1,5 @@
 per-file runtime_libart.mk = calin@google.com, mast@google.com, ngeoffray@google.com, oth@google.com, rpl@google.com, vmarko@google.com
+
+# GSI
+per-file gsi_release.mk = file:/target/product/gsi/OWNERS
+per-file gsi_keys.mk = file:/target/product/gsi/OWNERS
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 09864bc..c87fb73 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -403,6 +403,6 @@
 
 # This property allows enabling Keystore 2.0 selectively for testing.
 # TODO Remove when Keystore 2.0 migration is complete. b/171563717
-PRODUCT_SYSTEM_PROPERTIES += persist.android.security.keystore2.enable=false
+PRODUCT_SYSTEM_PROPERTIES += persist.android.security.keystore2.enable=true
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk)
diff --git a/target/product/gsi/OWNERS b/target/product/gsi/OWNERS
index 3fdd5af..39f97de 100644
--- a/target/product/gsi/OWNERS
+++ b/target/product/gsi/OWNERS
@@ -1,3 +1,6 @@
+bowgotsai@google.com
 jiyong@google.com
 justinyun@google.com
 smoreland@google.com
+szuweilin@google.com
+yochiang@google.com
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 25716ce..539dbfa 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -59,3 +59,9 @@
 
 # Support additional P, Q and R VNDK packages
 PRODUCT_EXTRA_VNDK_VERSIONS := 28 29 30
+
+# Do not build non-GSI partition images.
+PRODUCT_BUILD_CACHE_IMAGE := false
+PRODUCT_BUILD_USERDATA_IMAGE := false
+PRODUCT_BUILD_VENDOR_IMAGE := false
+PRODUCT_BUILD_SUPER_PARTITION := false
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 0061819..414ab97 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1339,6 +1339,35 @@
   RunAndCheckOutput(verify_cmd)
 
 
+def AppendGkiSigningArgs(cmd):
+  """Append GKI signing arguments for mkbootimg."""
+  # e.g., --gki_signing_key path/to/signing_key
+  #       --gki_signing_algorithm SHA256_RSA4096"
+
+  key_path = OPTIONS.info_dict.get("gki_signing_key_path")
+  # It's fine that a non-GKI boot.img has no gki_signing_key_path.
+  if not key_path:
+    return
+
+  if not os.path.exists(key_path) and OPTIONS.search_path:
+    new_key_path = os.path.join(OPTIONS.search_path, key_path)
+    if os.path.exists(new_key_path):
+      key_path = new_key_path
+
+  # Checks key_path exists, before appending --gki_signing_* args.
+  if not os.path.exists(key_path):
+    raise ExternalError('gki_signing_key_path: "{}" not found'.format(key_path))
+
+  algorithm = OPTIONS.info_dict.get("gki_signing_algorithm")
+  if key_path and algorithm:
+    cmd.extend(["--gki_signing_key", key_path,
+                "--gki_signing_algorithm", algorithm])
+
+    signature_args = OPTIONS.info_dict.get("gki_signing_signature_args")
+    if signature_args:
+      cmd.extend(["--gki_signing_signature_args", signature_args])
+
+
 def BuildVBMeta(image_path, partitions, name, needed_partitions):
   """Creates a VBMeta image.
 
@@ -1520,6 +1549,8 @@
   if has_ramdisk:
     cmd.extend(["--ramdisk", ramdisk_img.name])
 
+  AppendGkiSigningArgs(cmd)
+
   img_unsigned = None
   if info_dict.get("vboot"):
     img_unsigned = tempfile.NamedTemporaryFile()
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 00acd98..3db5559 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -123,6 +123,17 @@
       mounted on the partition (e.g. "--signing_helper /path/to/helper"). The
       args will be appended to the existing ones in info dict.
 
+  --gki_signing_algorithm <algorithm>
+  --gki_signing_key <key>
+      Use the specified algorithm (e.g. SHA256_RSA4096) and the key to generate
+      'boot signature' in a v4 boot.img. Otherwise it uses the existing values
+      in info dict.
+
+  --gki_signing_extra_args <args>
+      Specify any additional args that are needed to generate 'boot signature'
+      (e.g. --prop foo:bar). The args will be appended to the existing ones
+      in info dict.
+
   --android_jar_path <path>
       Path to the android.jar to repack the apex file.
 """
@@ -174,6 +185,9 @@
 OPTIONS.avb_keys = {}
 OPTIONS.avb_algorithms = {}
 OPTIONS.avb_extra_args = {}
+OPTIONS.gki_signing_key = None
+OPTIONS.gki_signing_algorithm = None
+OPTIONS.gki_signing_extra_args = None
 OPTIONS.android_jar_path = None
 
 
@@ -677,6 +691,9 @@
   if misc_info.get('avb_enable') == 'true':
     RewriteAvbProps(misc_info)
 
+  # Replace the GKI signing key for boot.img, if any.
+  ReplaceGkiSigningKey(misc_info)
+
   # Write back misc_info with the latest values.
   ReplaceMiscInfoTxt(input_tf_zip, output_tf_zip, misc_info)
 
@@ -995,6 +1012,28 @@
       misc_info[args_key] = result
 
 
+def ReplaceGkiSigningKey(misc_info):
+  """Replaces the GKI signing key."""
+
+  key = OPTIONS.gki_signing_key
+  if not key:
+    return
+
+  algorithm = OPTIONS.gki_signing_algorithm
+  if not algorithm:
+    raise ValueError("Missing --gki_signing_algorithm")
+
+  print('Replacing GKI signing key with "%s" (%s)' % (key, algorithm))
+  misc_info["gki_signing_algorithm"] = algorithm
+  misc_info["gki_signing_key_path"] = key
+
+  extra_args = OPTIONS.gki_signing_extra_args
+  if extra_args:
+    print('Setting extra GKI signing args: "%s"' % (extra_args))
+    misc_info["gki_signing_signature_args"] = (
+        misc_info.get("gki_signing_signature_args", '') + ' ' + extra_args)
+
+
 def BuildKeyMap(misc_info, key_mapping_options):
   for s, d in key_mapping_options:
     if s is None:   # -d option
@@ -1226,6 +1265,12 @@
       # 'oem=--signing_helper_with_files=/tmp/avbsigner.sh'.
       partition, extra_args = a.split("=", 1)
       OPTIONS.avb_extra_args[partition] = extra_args
+    elif o == "--gki_signing_key":
+      OPTIONS.gki_signing_key = a
+    elif o == "--gki_signing_algorithm":
+      OPTIONS.gki_signing_algorithm = a
+    elif o == "--gki_signing_extra_args":
+      OPTIONS.gki_signing_extra_args = a
     else:
       return False
     return True
@@ -1273,6 +1318,9 @@
           "avb_extra_custom_image_key=",
           "avb_extra_custom_image_algorithm=",
           "avb_extra_custom_image_extra_args=",
+          "gki_signing_key=",
+          "gki_signing_algorithm=",
+          "gki_signing_extra_args=",
       ],
       extra_option_handler=option_handler)
 
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index ecd759c..a516366 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -1670,6 +1670,127 @@
                   common.OPTIONS.aftl_key_path]
     common.RunAndCheckOutput(verify_cmd)
 
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_AppendGkiSigningArgs_NoSigningKeyPath(self):
+    # A non-GKI boot.img has no gki_signing_key_path.
+    common.OPTIONS.info_dict = {
+        # 'gki_signing_key_path': pubkey,
+        'gki_signing_algorithm': 'SHA256_RSA4096',
+        'gki_signing_signature_args': '--prop foo:bar',
+    }
+
+    # Tests no --gki_signing_* args are appended if there is no
+    # gki_signing_key_path.
+    cmd = ['mkbootimg', '--header_version', '4']
+    expected_cmd = ['mkbootimg', '--header_version', '4']
+    common.AppendGkiSigningArgs(cmd)
+    self.assertEqual(cmd, expected_cmd)
+
+  def test_AppendGkiSigningArgs_NoSigningAlgorithm(self):
+    pubkey = os.path.join(self.testdata_dir, 'testkey_gki.pem')
+    with open(pubkey, 'wb') as f:
+      f.write(b'\x00' * 100)
+    self.assertTrue(os.path.exists(pubkey))
+
+    # Tests no --gki_signing_* args are appended if there is no
+    # gki_signing_algorithm.
+    common.OPTIONS.info_dict = {
+        'gki_signing_key_path': pubkey,
+        # 'gki_signing_algorithm': 'SHA256_RSA4096',
+        'gki_signing_signature_args': '--prop foo:bar',
+    }
+
+    cmd = ['mkbootimg', '--header_version', '4']
+    expected_cmd = ['mkbootimg', '--header_version', '4']
+    common.AppendGkiSigningArgs(cmd)
+    self.assertEqual(cmd, expected_cmd)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_AppendGkiSigningArgs(self):
+    pubkey = os.path.join(self.testdata_dir, 'testkey_gki.pem')
+    with open(pubkey, 'wb') as f:
+      f.write(b'\x00' * 100)
+    self.assertTrue(os.path.exists(pubkey))
+
+    common.OPTIONS.info_dict = {
+        'gki_signing_key_path': pubkey,
+        'gki_signing_algorithm': 'SHA256_RSA4096',
+        'gki_signing_signature_args': '--prop foo:bar',
+    }
+    cmd = ['mkbootimg', '--header_version', '4']
+    common.AppendGkiSigningArgs(cmd)
+
+    expected_cmd = [
+      'mkbootimg', '--header_version', '4',
+      '--gki_signing_key', pubkey,
+      '--gki_signing_algorithm', 'SHA256_RSA4096',
+      '--gki_signing_signature_args', '--prop foo:bar'
+    ]
+    self.assertEqual(cmd, expected_cmd)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_AppendGkiSigningArgs_KeyPathNotFound(self):
+    pubkey = os.path.join(self.testdata_dir, 'no_testkey_gki.pem')
+    self.assertFalse(os.path.exists(pubkey))
+
+    common.OPTIONS.info_dict = {
+        'gki_signing_key_path': pubkey,
+        'gki_signing_algorithm': 'SHA256_RSA4096',
+        'gki_signing_signature_args': '--prop foo:bar',
+    }
+    cmd = ['mkbootimg', '--header_version', '4']
+    self.assertRaises(common.ExternalError, common.AppendGkiSigningArgs, cmd)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_AppendGkiSigningArgs_SearchKeyPath(self):
+    pubkey = 'testkey_gki.pem'
+    self.assertFalse(os.path.exists(pubkey))
+
+    # Tests it should replace the pubkey with an existed key under
+    # OPTIONS.search_path, i.e., os.path.join(OPTIONS.search_path, pubkey).
+    search_path_dir = common.MakeTempDir()
+    search_pubkey = os.path.join(search_path_dir, pubkey)
+    with open(search_pubkey, 'wb') as f:
+      f.write(b'\x00' * 100)
+    self.assertTrue(os.path.exists(search_pubkey))
+
+    common.OPTIONS.search_path = search_path_dir
+    common.OPTIONS.info_dict = {
+        'gki_signing_key_path': pubkey,
+        'gki_signing_algorithm': 'SHA256_RSA4096',
+        'gki_signing_signature_args': '--prop foo:bar',
+    }
+    cmd = ['mkbootimg', '--header_version', '4']
+    common.AppendGkiSigningArgs(cmd)
+
+    expected_cmd = [
+      'mkbootimg', '--header_version', '4',
+      '--gki_signing_key', search_pubkey,
+      '--gki_signing_algorithm', 'SHA256_RSA4096',
+      '--gki_signing_signature_args', '--prop foo:bar'
+    ]
+    self.assertEqual(cmd, expected_cmd)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_AppendGkiSigningArgs_SearchKeyPathNotFound(self):
+    pubkey = 'no_testkey_gki.pem'
+    self.assertFalse(os.path.exists(pubkey))
+
+    # Tests it should raise ExternalError if no key found under
+    # OPTIONS.search_path.
+    search_path_dir = common.MakeTempDir()
+    search_pubkey = os.path.join(search_path_dir, pubkey)
+    self.assertFalse(os.path.exists(search_pubkey))
+
+    common.OPTIONS.search_path = search_path_dir
+    common.OPTIONS.info_dict = {
+        'gki_signing_key_path': pubkey,
+        'gki_signing_algorithm': 'SHA256_RSA4096',
+        'gki_signing_signature_args': '--prop foo:bar',
+    }
+    cmd = ['mkbootimg', '--header_version', '4']
+    self.assertRaises(common.ExternalError, common.AppendGkiSigningArgs, cmd)
+
 
 class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
   """Checks the format of install-recovery.sh.
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 18e4858..64e27a2 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -23,8 +23,8 @@
 import test_utils
 from sign_target_files_apks import (
     CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ReadApexKeysInfo,
-    ReplaceCerts, ReplaceVerityKeyId, RewriteAvbProps, RewriteProps,
-    WriteOtacerts)
+    ReplaceCerts, ReplaceGkiSigningKey, ReplaceVerityKeyId, RewriteAvbProps,
+    RewriteProps, WriteOtacerts)
 
 
 class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
@@ -588,3 +588,52 @@
             'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
             'build/make/target/product/security/testkey'),
         }, keys_info)
+
+  def test_ReplaceGkiSigningKey(self):
+    common.OPTIONS.gki_signing_key = 'release_gki_key'
+    common.OPTIONS.gki_signing_algorithm = 'release_gki_algorithm'
+    common.OPTIONS.gki_signing_extra_args = 'release_gki_signature_extra_args'
+
+    misc_info = {
+        'gki_signing_key_path': 'default_gki_key',
+        'gki_signing_algorithm': 'default_gki_algorithm',
+        'gki_signing_signature_args': 'default_gki_signature_args',
+    }
+    expected_dict = {
+        'gki_signing_key_path': 'release_gki_key',
+        'gki_signing_algorithm': 'release_gki_algorithm',
+        'gki_signing_signature_args': 'default_gki_signature_args release_gki_signature_extra_args',
+    }
+    ReplaceGkiSigningKey(misc_info)
+    self.assertDictEqual(expected_dict, misc_info)
+
+  def test_ReplaceGkiSigningKey_MissingSigningAlgorithm(self):
+    common.OPTIONS.gki_signing_key = 'release_gki_key'
+    common.OPTIONS.gki_signing_algorithm = None
+    common.OPTIONS.gki_signing_extra_args = 'release_gki_signature_extra_args'
+
+    misc_info = {
+        'gki_signing_key_path': 'default_gki_key',
+        'gki_signing_algorithm': 'default_gki_algorithm',
+        'gki_signing_signature_args': 'default_gki_signature_args',
+    }
+    self.assertRaises(ValueError, ReplaceGkiSigningKey, misc_info)
+
+  def test_ReplaceGkiSigningKey_MissingSigningKeyNop(self):
+    common.OPTIONS.gki_signing_key = None
+    common.OPTIONS.gki_signing_algorithm = 'release_gki_algorithm'
+    common.OPTIONS.gki_signing_extra_args = 'release_gki_signature_extra_args'
+
+    # No change to misc_info if common.OPTIONS.gki_signing_key is missing.
+    misc_info = {
+        'gki_signing_key_path': 'default_gki_key',
+        'gki_signing_algorithm': 'default_gki_algorithm',
+        'gki_signing_signature_args': 'default_gki_signature_args',
+    }
+    expected_dict = {
+        'gki_signing_key_path': 'default_gki_key',
+        'gki_signing_algorithm': 'default_gki_algorithm',
+        'gki_signing_signature_args': 'default_gki_signature_args',
+    }
+    ReplaceGkiSigningKey(misc_info)
+    self.assertDictEqual(expected_dict, misc_info)