Merge "Add system_other partition, install odex files" into nyc-mr1-dev
diff --git a/core/Makefile b/core/Makefile
index 3b17767..a3bdc3a 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -516,7 +516,7 @@
 endif
 endif
 
-BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) $(VERITY_KEYID))
+BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
 ifdef BOARD_KERNEL_CMDLINE
 INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
 endif
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 59e907b..5886610 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -204,6 +204,8 @@
 # Used to replace the installed file of a presigned prebuilt apk in PDK fusion build,
 # to avoid installing the presigned apks with classes.dex unstripped.
 LOCAL_REPLACE_PREBUILT_APK_INSTALLED:=
+LOCAL_EXTRACT_APK:=
+LOCAL_EXTRACT_DPI_APK:=
 
 # arch specific variables
 LOCAL_SRC_FILES_$(TARGET_ARCH):=
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 6e96880..dbcf276 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -24,6 +24,31 @@
   my_sanitize := $(my_global_sanitize)
 endif
 
+# The sanitizer specified in the product configuration wins over the previous.
+ifneq ($(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG),)
+  my_sanitize := $(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG)
+  ifeq ($(my_sanitize),never)
+    my_sanitize :=
+  endif
+endif
+
+# Add a filter point for 32-bit vs 64-bit sanitization (to lighten the burden).
+SANITIZE_ARCH ?= 32 64
+ifeq ($(filter $(SANITIZE_ARCH),$(my_32_64_bit_suffix)),)
+  my_sanitize :=
+endif
+
+# Add a filter point based on module owner (to lighten the burden). The format is a space- or
+# colon-separated list of owner names.
+ifneq (,$(SANITIZE_NEVER_BY_OWNER))
+  ifneq (,$(LOCAL_MODULE_OWNER))
+    ifneq (,$(filter $(LOCAL_MODULE_OWNER),$(subst :, ,$(SANITIZE_NEVER_BY_OWNER))))
+      $(warning Not sanitizing $(LOCAL_MODULE) based on module owner.)
+      my_sanitize :=
+    endif
+  endif
+endif
+
 # Don't apply sanitizers to NDK code.
 ifdef LOCAL_SDK_VERSION
   my_sanitize :=
diff --git a/core/java.mk b/core/java.mk
index bc8ed64..2602daf 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -459,6 +459,8 @@
 	$(hide) $(ACP) -fp $< $@
 endif
 
+full_classes_jar_source := $(full_classes_jarjar_jar)
+ifndef LOCAL_JACK_ENABLED
 ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
 $(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILE := $(intermediates.COMMON)/coverage.emma.ignore
 $(full_classes_emma_jar): PRIVATE_EMMA_INTERMEDIATES_DIR := $(emma_intermediates_dir)
@@ -475,15 +477,12 @@
 # $(full_classes_emma_jar)
 $(full_classes_emma_jar): $(full_classes_jarjar_jar) | $(EMMA_JAR)
 	$(transform-classes.jar-to-emma)
-
-else
-$(full_classes_emma_jar): $(full_classes_jarjar_jar) | $(ACP)
-	@echo Copying: $@
-	$(copy-file-to-target)
+full_classes_jar_source := $(full_classes_emma_jar)
+endif
 endif
 
 # Keep a copy of the jar just before proguard processing.
-$(full_classes_jar): $(full_classes_emma_jar) | $(ACP)
+$(full_classes_jar): $(full_classes_jar_source) | $(ACP)
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index ee68427..d450373 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -152,6 +152,8 @@
 ifeq ($(LOCAL_MODULE_CLASS),APPS)
 PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
 
+my_extract_apk := $(strip $(LOCAL_EXTRACT_APK))
+
 # Select dpi-specific source
 ifdef LOCAL_DPI_VARIANTS
 my_dpi := $(firstword $(filter $(LOCAL_DPI_VARIANTS),$(PRODUCT_AAPT_PREF_CONFIG) $(PRODUCT_AAPT_PREBUILT_DPI)))
@@ -162,9 +164,27 @@
 my_prebuilt_dpi_file_stem := $(LOCAL_MODULE)_%.apk
 endif
 my_prebuilt_src_file := $(dir $(my_prebuilt_src_file))$(subst %,$(my_dpi),$(my_prebuilt_dpi_file_stem))
+
+ifneq ($(strip $(LOCAL_EXTRACT_DPI_APK)),)
+my_extract_apk := $(subst %,$(my_dpi),$(LOCAL_EXTRACT_DPI_APK))
+endif  # LOCAL_EXTRACT_DPI_APK
 endif  # my_dpi
 endif  # LOCAL_DPI_VARIANTS
 
+ifdef my_extract_apk
+my_extracted_apk := $(intermediates)/extracted.apk
+
+$(my_extracted_apk): PRIVATE_EXTRACT := $(my_extract_apk)
+$(my_extracted_apk): $(my_prebuilt_src_file)
+	@echo Extract APK: $@
+	$(hide) mkdir -p $(dir $@) && rm -f $@
+	$(hide) unzip -p $< $(PRIVATE_EXTRACT) >$@
+
+my_prebuilt_src_file := $(my_extracted_apk)
+my_extracted_apk :=
+my_extract_apk :=
+endif
+
 rs_compatibility_jni_libs :=
 include $(BUILD_SYSTEM)/install_jni_libs.mk
 
diff --git a/core/product.mk b/core/product.mk
index 94cc2e3..332b015 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -120,6 +120,7 @@
     PRODUCT_DEX_PREOPT_MODULE_CONFIGS \
     PRODUCT_DEX_PREOPT_DEFAULT_FLAGS \
     PRODUCT_DEX_PREOPT_BOOT_FLAGS \
+    PRODUCT_SANITIZER_MODULE_CONFIGS \
     PRODUCT_SYSTEM_BASE_FS_PATH \
     PRODUCT_VENDOR_BASE_FS_PATH \
     PRODUCT_SHIPPING_API_LEVEL \
@@ -333,3 +334,14 @@
 $(eval PRODUCT_DEX_PREOPT_MODULE_CONFIGS += \
   $(foreach m,$(1),$(m)=$(_c)))
 endef
+
+# whitespace placeholder when we record module's sanitizer config.
+_PSMC_SP_PLACE_HOLDER := |@SP@|
+# Set up sanitizer config for a module.
+# $(1) list of module names
+# $(2) the modules' sanitizer config
+define add-product-sanitizer-module-config
+$(eval _c := $(subst $(space),$(_PSMC_SP_PLACE_HOLDER),$(strip $(2))))\
+$(eval PRODUCT_SANITIZER_MODULE_CONFIGS += \
+  $(foreach m,$(1),$(m)=$(_c)))
+endef
diff --git a/core/product_config.mk b/core/product_config.mk
index ed38bc8..0d4ced3 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -392,7 +392,7 @@
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
 PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
-# Resolve and setup per-module dex-preopot configs.
+# Resolve and setup per-module dex-preopt configs.
 PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
 # If a module has multiple setups, the first takes precedence.
@@ -405,3 +405,17 @@
     $(eval cf := $(subst $(_PDPMC_SP_PLACE_HOLDER),$(space),$(cf)))\
     $(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
 _pdpmc_modules :=
+
+# Resolve and setup per-module sanitizer configs.
+PRODUCT_SANITIZER_MODULE_CONFIGS := \
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_psmc_modules :=
+$(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
+  $(eval m := $(firstword $(subst =,$(space),$(c))))\
+  $(if $(filter $(_psmc_modules),$(m)),,\
+    $(eval _psmc_modules += $(m))\
+    $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+    $(eval cf := $(subst $(_PSMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+    $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_psmc_modules :=
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index bdfc65a..f6e2bee 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -113,7 +113,7 @@
   # Must be of the form "YYYY-MM-DD" on production devices.
   #
   # If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
-  PLATFORM_SECURITY_PATCH := 2016-07-05
+  PLATFORM_SECURITY_PATCH := 2016-08-05
 endif
 
 ifeq "" "$(PLATFORM_BASE_OS)"
diff --git a/target/product/core.mk b/target/product/core.mk
index 75cf649..0a4e0fd 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -53,6 +53,7 @@
     QuickSearchBox \
     Settings \
     SharedStorageBackup \
+    StorageManager \
     Telecom \
     TeleService \
     VpnDialogs \
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index f6ccd2a..5c48358 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -27,6 +27,7 @@
     OneTimeInitializer \
     Provision \
     SystemUI \
+    EasterEgg \
     WallpaperCropper
 
 PRODUCT_PACKAGES += \
diff --git a/target/product/languages_full.mk b/target/product/languages_full.mk
index 36c3de8..98d8c3c 100644
--- a/target/product/languages_full.mk
+++ b/target/product/languages_full.mk
@@ -21,4 +21,4 @@
 
 # These are all the locales that have translations and are displayable
 # by TextView in this branch.
-PRODUCT_LOCALES := en_US en_AU en_IN fr_FR it_IT es_ES et_EE de_DE nl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN zh_HK ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TR pt_PT pt_BR sv_SE bg_BG ca_ES en_GB fi_FI hi_IN hr_HR hu_HU in_ID iw_IL lt_LT lv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH ar_EG fa_IR th_TH sw_TZ ms_MY af_ZA zu_ZA am_ET en_XA ar_XB fr_CA km_KH lo_LA ne_NP si_LK mn_MN hy_AM az_AZ ka_GE my_MM mr_IN ml_IN is_IS mk_MK ky_KG eu_ES gl_ES bn_BD ta_IN kn_IN te_IN uz_UZ ur_PK kk_KZ sq_AL gu_IN pa_IN be_BY bs_BA sr_Latn_RS
+PRODUCT_LOCALES := en_US en_AU en_IN fr_FR it_IT es_ES et_EE de_DE nl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN zh_HK ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TR pt_PT pt_BR sv_SE bg_BG ca_ES en_GB fi_FI hi_IN hr_HR hu_HU in_ID iw_IL lt_LT lv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH ar_EG fa_IR th_TH sw_TZ ms_MY af_ZA zu_ZA am_ET en_XA ar_XB fr_CA km_KH lo_LA ne_NP si_LK mn_MN hy_AM az_AZ ka_GE my_MM mr_IN ml_IN is_IS mk_MK ky_KG eu_ES gl_ES bn_BD ta_IN kn_IN te_IN uz_UZ ur_PK kk_KZ sq_AL gu_IN pa_IN be_BY bs_BA
diff --git a/target/product/sdk_base.mk b/target/product/sdk_base.mk
index ebe3708..fa257ae 100644
--- a/target/product/sdk_base.mk
+++ b/target/product/sdk_base.mk
@@ -44,6 +44,7 @@
 	SoftKeyboard \
 	sqlite3 \
 	SystemUI \
+	EasterEgg \
 	WidgetPreview
 
 # Define the host tools and libs that are parts of the SDK.
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index a7a4098..0d9aabd 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -342,6 +342,22 @@
     return ctx.hexdigest()
 
   def WriteTransfers(self, prefix):
+    def WriteSplitTransfers(out, style, target_blocks):
+      """Limit the size of operand in command 'new' and 'zero' to 1024 blocks.
+
+      This prevents the target size of one command from being too large; and
+      might help to avoid fsync errors on some devices."""
+
+      assert (style == "new" or style == "zero")
+      blocks_limit = 1024
+      total = 0
+      while target_blocks:
+        blocks_to_write = target_blocks.first(blocks_limit)
+        out.append("%s %s\n" % (style, blocks_to_write.to_string_raw()))
+        total += blocks_to_write.size()
+        target_blocks = target_blocks.subtract(blocks_to_write)
+      return total
+
     out = []
 
     total = 0
@@ -463,7 +479,7 @@
 
       if xf.style == "new":
         assert xf.tgt_ranges
-        out.append("%s %s\n" % (xf.style, xf.tgt_ranges.to_string_raw()))
+        assert tgt_size == WriteSplitTransfers(out, xf.style, xf.tgt_ranges)
         total += tgt_size
       elif xf.style == "move":
         assert xf.tgt_ranges
@@ -523,9 +539,8 @@
       elif xf.style == "zero":
         assert xf.tgt_ranges
         to_zero = xf.tgt_ranges.subtract(xf.src_ranges)
-        if to_zero:
-          out.append("%s %s\n" % (xf.style, to_zero.to_string_raw()))
-          total += to_zero.size()
+        assert WriteSplitTransfers(out, xf.style, to_zero) == to_zero.size()
+        total += to_zero.size()
       else:
         raise ValueError("unknown transfer style '%s'\n" % xf.style)
 
@@ -554,7 +569,8 @@
 
     # Zero out extended blocks as a workaround for bug 20881595.
     if self.tgt.extended:
-      out.append("zero %s\n" % (self.tgt.extended.to_string_raw(),))
+      assert (WriteSplitTransfers(out, "zero", self.tgt.extended) ==
+              self.tgt.extended.size())
       total += self.tgt.extended.size()
 
     # We erase all the blocks on the partition that a) don't contain useful
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 0a0173d..915a29e 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -121,6 +121,9 @@
       directly, a payload signer that knows how to do that should be specified.
       The signer will be supplied with "-inkey <path_to_key>",
       "-in <input_file>" and "-out <output_file>" parameters.
+
+  --payload_signer_args <args>
+      Specify the arguments needed for payload signer.
 """
 
 import sys
@@ -132,6 +135,7 @@
 import multiprocessing
 import os
 import subprocess
+import shlex
 import tempfile
 import zipfile
 
@@ -169,6 +173,7 @@
 OPTIONS.gen_verify = False
 OPTIONS.log_diff = None
 OPTIONS.payload_signer = None
+OPTIONS.payload_signer_args = []
 
 def MostPopularKey(d, default):
   """Given a dict, return the key corresponding to the largest
@@ -1246,22 +1251,23 @@
                                                  suffix=".bin")
   # 3a. Sign the payload hash.
   if OPTIONS.payload_signer is not None:
-    cmd = [OPTIONS.payload_signer,
-           "-inkey", OPTIONS.package_key + OPTIONS.private_key_suffix]
+    cmd = [OPTIONS.payload_signer]
+    cmd.extend(OPTIONS.payload_signer_args)
   else:
     cmd = ["openssl", "pkeyutl", "-sign",
            "-inkey", rsa_key,
            "-pkeyopt", "digest:sha256"]
   cmd.extend(["-in", payload_sig_file,
               "-out", signed_payload_sig_file])
+
   p1 = common.Run(cmd, stdout=subprocess.PIPE)
   p1.wait()
   assert p1.returncode == 0, "openssl sign payload failed"
 
   # 3b. Sign the metadata hash.
   if OPTIONS.payload_signer is not None:
-    cmd = [OPTIONS.payload_signer,
-           "-inkey", OPTIONS.package_key + OPTIONS.private_key_suffix]
+    cmd = [OPTIONS.payload_signer]
+    cmd.extend(OPTIONS.payload_signer_args)
   else:
     cmd = ["openssl", "pkeyutl", "-sign",
            "-inkey", rsa_key,
@@ -1926,6 +1932,8 @@
       OPTIONS.log_diff = a
     elif o == "--payload_signer":
       OPTIONS.payload_signer = a
+    elif o == "--payload_signer_args":
+      OPTIONS.payload_signer_args = shlex.split(a)
     else:
       return False
     return True
@@ -1956,6 +1964,7 @@
                                  "gen_verify",
                                  "log_diff=",
                                  "payload_signer=",
+                                 "payload_signer_args=",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index e67a166..3341f9f 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -65,6 +65,19 @@
       removed.  Changes are processed in the order they appear.
       Default value is "-test-keys,-dev-keys,+release-keys".
 
+  --replace_verity_private_key <key>
+      Replace the private key used for verity signing. It expects a filename
+      WITHOUT the extension (e.g. verity_key).
+
+  --replace_verity_public_key <key>
+      Replace the certificate (public key) used for verity verification. The
+      key file replaces the one at BOOT/RAMDISK/verity_key (or ROOT/verity_key
+      for devices using system_root_image). It expects the key filename WITH
+      the extension (e.g. verity_key.pub).
+
+  --replace_verity_keyid <path_to_X509_PEM_cert_file>
+      Replace the veritykeyid in BOOT/cmdline of input_target_file_zip
+      with keyid of the cert pointed by <path_to_X509_PEM_cert_file>.
 """
 
 import sys
@@ -94,6 +107,7 @@
 OPTIONS.replace_ota_keys = False
 OPTIONS.replace_verity_public_key = False
 OPTIONS.replace_verity_private_key = False
+OPTIONS.replace_verity_keyid = False
 OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys")
 
 def GetApkCerts(tf_zip):
@@ -200,18 +214,6 @@
     data = input_tf_zip.read(info.filename)
     out_info = copy.copy(info)
 
-    # Replace keys if requested.
-    if (info.filename == "META/misc_info.txt" and
-        OPTIONS.replace_verity_private_key):
-      ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info,
-                              OPTIONS.replace_verity_private_key[1])
-    elif (info.filename in ("BOOT/RAMDISK/verity_key",
-                            "BOOT/verity_key") and
-          OPTIONS.replace_verity_public_key):
-      new_data = ReplaceVerityPublicKey(output_tf_zip, info.filename,
-                                        OPTIONS.replace_verity_public_key[1])
-      write_to_temp(info.filename, info.external_attr, new_data)
-
     # Sign APKs.
     if info.filename.endswith(".apk"):
       name = os.path.basename(info.filename)
@@ -258,15 +260,20 @@
               "SYSTEM/etc/update_engine/update-payload-key.pub.pem")):
       pass
 
-    # Skip verity keys since they have been processed above.
-    # TODO: verity_key is at a wrong location (BOOT/verity_key). Will fix and
-    # clean up verity related lines in a separate CL.
+    # Skip META/misc_info.txt if we will replace the verity private key later.
     elif (OPTIONS.replace_verity_private_key and
           info.filename == "META/misc_info.txt"):
       pass
+
+    # Skip verity public key if we will replace it.
     elif (OPTIONS.replace_verity_public_key and
           info.filename in ("BOOT/RAMDISK/verity_key",
-                            "BOOT/verity_key")):
+                            "ROOT/verity_key")):
+      pass
+
+    # Skip verity keyid (for system_root_image use) if we will replace it.
+    elif (OPTIONS.replace_verity_keyid and
+          info.filename == "BOOT/cmdline"):
       pass
 
     # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch. This case
@@ -295,6 +302,32 @@
       # tmpdir in case we need to regenerate the recovery-from-boot patch.
       write_to_temp(recovery_keys_location, 0o755 << 16, new_recovery_keys)
 
+  # Replace the keyid string in META/misc_info.txt.
+  if OPTIONS.replace_verity_private_key:
+    ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info,
+                            OPTIONS.replace_verity_private_key[1])
+
+  if OPTIONS.replace_verity_public_key:
+    if system_root_image:
+      dest = "ROOT/verity_key"
+    else:
+      dest = "BOOT/RAMDISK/verity_key"
+    # We are replacing the one in boot image only, since the one under
+    # recovery won't ever be needed.
+    new_data = ReplaceVerityPublicKey(
+        output_tf_zip, dest, OPTIONS.replace_verity_public_key[1])
+    write_to_temp(dest, 0o755 << 16, new_data)
+
+  # Replace the keyid string in BOOT/cmdline.
+  if OPTIONS.replace_verity_keyid:
+    new_cmdline = ReplaceVerityKeyId(input_tf_zip, output_tf_zip,
+      OPTIONS.replace_verity_keyid[1])
+    # Writing the new cmdline to tmpdir is redundant as the bootimage
+    # gets build in the add_image_to_target_files and rebuild_recovery
+    # is not exercised while building the boot image for the A/B
+    # path
+    write_to_temp("BOOT/cmdline", 0o755 << 16, new_cmdline)
+
   if rebuild_recovery:
     recovery_img = common.GetBootableImage(
         "recovery.img", "recovery.img", tmpdir, "RECOVERY", info_dict=misc_info)
@@ -476,6 +509,7 @@
 
   return new_recovery_keys
 
+
 def ReplaceVerityPublicKey(targetfile_zip, filename, key_path):
   print "Replacing verity public key with %s" % key_path
   with open(key_path) as f:
@@ -483,6 +517,7 @@
   common.ZipWriteStr(targetfile_zip, filename, data)
   return data
 
+
 def ReplaceVerityPrivateKey(targetfile_input_zip, targetfile_output_zip,
                             misc_info, key_path):
   print "Replacing verity private key with %s" % key_path
@@ -492,6 +527,32 @@
   common.ZipWriteStr(targetfile_output_zip, "META/misc_info.txt", new_misc_info)
   misc_info["verity_key"] = key_path
 
+
+def ReplaceVerityKeyId(targetfile_input_zip, targetfile_output_zip, keypath):
+  in_cmdline = targetfile_input_zip.read("BOOT/cmdline")
+  # copy in_cmdline to output_zip if veritykeyid is not present in in_cmdline
+  if "veritykeyid" not in in_cmdline:
+    common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", in_cmdline)
+    return in_cmdline
+  out_cmdline = []
+  for param in in_cmdline.split():
+    if "veritykeyid" in param:
+      # extract keyid using openssl command
+      p = common.Run(["openssl", "x509", "-in", keypath, "-text"], stdout=subprocess.PIPE)
+      keyid, stderr = p.communicate()
+      keyid = re.search(r'keyid:([0-9a-fA-F:]*)', keyid).group(1).replace(':', '').lower()
+      print "Replacing verity keyid with %s error=%s" % (keyid, stderr)
+      out_cmdline.append("veritykeyid=id:%s" % (keyid,))
+    else:
+      out_cmdline.append(param)
+
+  out_cmdline = ' '.join(out_cmdline)
+  out_cmdline = out_cmdline.strip()
+  print "out_cmdline %s" % (out_cmdline)
+  common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", out_cmdline)
+  return out_cmdline
+
+
 def BuildKeyMap(misc_info, key_mapping_options):
   for s, d in key_mapping_options:
     if s is None:   # -d option
@@ -589,6 +650,8 @@
       OPTIONS.replace_verity_public_key = (True, a)
     elif o == "--replace_verity_private_key":
       OPTIONS.replace_verity_private_key = (True, a)
+    elif o == "--replace_verity_keyid":
+      OPTIONS.replace_verity_keyid = (True, a)
     else:
       return False
     return True
@@ -601,7 +664,8 @@
                                               "replace_ota_keys",
                                               "tag_changes=",
                                               "replace_verity_public_key=",
-                                              "replace_verity_private_key="],
+                                              "replace_verity_private_key=",
+                                              "replace_verity_keyid="],
                              extra_option_handler=option_handler)
 
   if len(args) != 2: