Merge "Call delta_generator to get the signature size"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 4e06d80..8219afc 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -678,6 +678,9 @@
 
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex)
 
+# Migrate preopt files to system_other for some devices
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/*/*app/*/oat)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 1b6c532..f02eb19 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -3289,29 +3289,55 @@
   $(error BOARD_AVB_VBMETA_SYSTEM and BOARD_AVB_VBMETA_VENDOR cannot have duplicates)
 endif
 
+# When building a standalone recovery image for non-A/B devices, recovery image must be self-signed
+# to be verified independently, and cannot be chained into vbmeta.img. See the link below for
+# details.
+ifneq ($(AB_OTA_UPDATER),true)
+ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
+$(if $(BOARD_AVB_RECOVERY_KEY_PATH),,\
+    $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for non-A/B devices. \
+            See https://android.googlesource.com/platform/external/avb/+/master/README.md#booting-into-recovery))
+endif
+endif
+
 # Appends os version and security patch level as a AVB property descriptor
 
 BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.system.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.system.os_version:$(PLATFORM_VERSION) \
     --prop com.android.build.system.security_patch:$(PLATFORM_SECURITY_PATCH)
 
 BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.product.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.product.os_version:$(PLATFORM_VERSION) \
     --prop com.android.build.product.security_patch:$(PLATFORM_SECURITY_PATCH)
 
 BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.system_ext.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.system_ext.os_version:$(PLATFORM_VERSION) \
     --prop com.android.build.system_ext.security_patch:$(PLATFORM_SECURITY_PATCH)
 
 BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.boot.os_version:$(PLATFORM_VERSION)
 
+BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.vendor_boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
+
+BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.recovery.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
+
 BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.vendor.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.vendor.os_version:$(PLATFORM_VERSION)
 
 BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.odm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.odm.os_version:$(PLATFORM_VERSION)
 
+BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.dtbo.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
+
 # The following vendor- and odm-specific images needs explicit SPL set per board.
 ifdef BOOT_SECURITY_PATCH
 BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
@@ -3358,8 +3384,11 @@
 $(eval $(_signing_args) := \
     --algorithm $($(_signing_algorithm)) --key $($(_key_path)))
 
-$(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
-    --chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey)
+# The recovery partition in non-A/B devices should be verified separately. Skip adding the chain
+# partition descriptor for recovery partition into vbmeta.img.
+$(if $(or $(filter true,$(AB_OTA_UPDATER)),$(filter-out recovery,$(part))),\
+    $(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
+        --chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey))
 
 # Set rollback_index via footer args for non-chained vbmeta image. Chained vbmeta image will pick up
 # the index via a separate flag (e.g. BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX).
diff --git a/core/board_config.mk b/core/board_config.mk
index 9032aaf..4c128f1 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -87,6 +87,7 @@
 _build_broken_var_list := \
   BUILD_BROKEN_DUP_RULES \
   BUILD_BROKEN_PREBUILT_ELF_FILES \
+  BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW \
   BUILD_BROKEN_USES_NETWORK \
 
 _build_broken_var_list += \
@@ -506,9 +507,9 @@
 ###########################################
 # Now we can substitute with the real value of TARGET_COPY_OUT_ODM
 ifeq ($(TARGET_COPY_OUT_ODM),$(_odm_path_placeholder))
-  TARGET_COPY_OUT_ODM := vendor/odm
-else ifeq ($(filter odm vendor/odm,$(TARGET_COPY_OUT_ODM)),)
-  $(error TARGET_COPY_OUT_ODM must be either 'odm' or 'vendor/odm', seeing '$(TARGET_COPY_OUT_ODM)'.)
+  TARGET_COPY_OUT_ODM := $(TARGET_COPY_OUT_VENDOR)/odm
+else ifeq ($(filter odm system/vendor/odm vendor/odm,$(TARGET_COPY_OUT_ODM)),)
+  $(error TARGET_COPY_OUT_ODM must be either 'odm', 'system/vendor/odm' or 'vendor/odm', seeing '$(TARGET_COPY_OUT_ODM)'.)
 endif
 PRODUCT_COPY_FILES := $(subst $(_odm_path_placeholder),$(TARGET_COPY_OUT_ODM),$(PRODUCT_COPY_FILES))
 
diff --git a/core/definitions.mk b/core/definitions.mk
index 7450d4f..a8bf4d5 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2279,7 +2279,7 @@
 # Align STORED entries of a package on 4-byte boundaries to make them easier to mmap.
 #
 define align-package
-$(hide) if ! $(ZIPALIGN) -c $(ZIPALIGN_PAGE_ALIGN_FLAGS) 4 $@ >/dev/null ; then \
+$(hide) if ! $(ZIPALIGN) -c -p 4 $@ >/dev/null ; then \
   mv $@ $@.unaligned; \
   $(ZIPALIGN) \
     -f \
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 69eaea1..cfe918f 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -4,7 +4,8 @@
 DEX_PREOPT_DEFAULT ?= true
 
 # The default filter for which files go into the system_other image (if it is
-# being used). To bundle everything one should set this to '%'
+# being used). Note that each pattern p here matches both '/<p>' and /system/<p>'.
+# To bundle everything one should set this to '%'.
 SYSTEM_OTHER_ODEX_FILTER ?= \
     app/% \
     priv-app/% \
diff --git a/core/main.mk b/core/main.mk
index e9d4390..29c5a4c 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -220,6 +220,9 @@
 ADDITIONAL_BUILD_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn
 endif
 
+# Define ro.sanitize.<name> properties for all global sanitizers.
+ADDITIONAL_BUILD_PROPERTIES += $(foreach s,$(SANITIZE_TARGET),ro.sanitize.$(s)=true)
+
 # Sets the default value of ro.postinstall.fstab.prefix to /system.
 # Device board config should override the value to /product when needed by:
 #
@@ -1138,6 +1141,7 @@
   libdt_socket.so \
   libicui18n.so \
   libicuuc.so \
+  libicu_jni.so \
   libjavacore.so \
   libjdwp.so \
   libm.so \
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 30890c0..ff5fb42 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -250,7 +250,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 := 2019-09-05
+      PLATFORM_SECURITY_PATCH := 2019-10-05
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index 2b288e6..93b0b15 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -154,7 +154,8 @@
     vndkprivate.libraries.txt \
     vndkcorevariant.libraries.txt \
     $(addsuffix .vendor,$(VNDK_CORE_LIBRARIES)) \
-    $(addsuffix .vendor,$(VNDK_SAMEPROCESS_LIBRARIES))
+    $(addsuffix .vendor,$(VNDK_SAMEPROCESS_LIBRARIES)) \
+    com.android.vndk.current
 endif
 include $(BUILD_PHONY_PACKAGE)
 
@@ -166,8 +167,11 @@
 _binder32 := _binder32
 endif
 endif
+# Phony targets are installed for **.libraries.txt files.
+# TODO(b/141450808): remove following VNDK phony targets when **.libraries.txt files are provided by apexes.
 LOCAL_REQUIRED_MODULES := \
     $(foreach vndk_ver,$(PRODUCT_EXTRA_VNDK_VERSIONS),vndk_v$(vndk_ver)_$(TARGET_ARCH)$(_binder32))
+LOCAL_REQUIRED_MODULES += $(foreach vndk_ver,$(PRODUCT_EXTRA_VNDK_VERSIONS),com.android.vndk.v$(vndk_ver))
 _binder32 :=
 include $(BUILD_PHONY_PACKAGE)
 
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 6649f28..3e44349 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -180,6 +180,7 @@
 VNDK-core: android.hardware.vibrator@1.1.so
 VNDK-core: android.hardware.vibrator@1.2.so
 VNDK-core: android.hardware.vibrator@1.3.so
+VNDK-core: android.hardware.vibrator@1.4.so
 VNDK-core: android.hardware.vr@1.0.so
 VNDK-core: android.hardware.weaver@1.0.so
 VNDK-core: android.hardware.wifi.hostapd@1.0.so
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index b8f2838..a71f9b8 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -64,8 +64,8 @@
 # For ringtones that rely on forward lock encryption
 PRODUCT_PACKAGES += libfwdlockengine
 
-# System libraries commonly depended on by things on the product partition.
-# This list will be pruned periodically.
+# System libraries commonly depended on by things on the system_ext or product partitions.
+# These lists will be pruned periodically.
 PRODUCT_PACKAGES += \
     android.hardware.biometrics.fingerprint@2.1 \
     android.hardware.radio@1.0 \
@@ -85,6 +85,13 @@
     libnl \
     libprotobuf-cpp-full \
 
+# These libraries are empty and have been combined into libhidlbase, but are still depended
+# on by things off /system.
+# TODO(b/135686713): remove these
+PRODUCT_PACKAGES += \
+    libhidltransport \
+    libhwbinder \
+
 # Camera service uses 'libdepthphoto' for adding dynamic depth
 # metadata inside depth jpegs.
 PRODUCT_PACKAGES += \
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index d73628f..f846b18 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -47,22 +47,23 @@
 
 
 class Options(object):
+
   def __init__(self):
-    base_out_path = os.getenv('OUT_DIR_COMMON_BASE')
-    if base_out_path is None:
-      base_search_path = "out"
-    else:
-      base_search_path = os.path.join(base_out_path,
-                                      os.path.basename(os.getcwd()))
+    # Set up search path, in order to find framework/ and lib64/. At the time of
+    # running this function, user-supplied search path (`--path`) hasn't been
+    # available. So the value set here is the default, which might be overridden
+    # by commandline flag later.
+    exec_path = sys.argv[0]
+    if exec_path.endswith('.py'):
+      script_name = os.path.basename(exec_path)
+      # logger hasn't been initialized yet at this point. Use print to output
+      # warnings.
+      print(
+          'Warning: releasetools script should be invoked as hermetic Python '
+          'executable -- build and run `{}` directly.'.format(script_name[:-3]),
+          file=sys.stderr)
+    self.search_path = os.path.realpath(os.path.join(exec_path, '..'))
 
-    # Python >= 3.3 returns 'linux', whereas Python 2.7 gives 'linux2'.
-    platform_search_path = {
-        "linux": os.path.join(base_search_path, "host/linux-x86"),
-        "linux2": os.path.join(base_search_path, "host/linux-x86"),
-        "darwin": os.path.join(base_search_path, "host/darwin-x86"),
-    }
-
-    self.search_path = platform_search_path.get(sys.platform)
     self.signapk_path = "framework/signapk.jar"  # Relative to search_path
     self.signapk_shared_library_path = "lib64"   # Relative to search_path
     self.extra_signapk_args = []
@@ -873,10 +874,20 @@
 
   # Check if chain partition is used.
   key_path = info_dict.get("avb_" + partition + "_key_path")
-  if key_path:
-    chained_partition_arg = GetAvbChainedPartitionArg(partition, info_dict)
-    return ["--chain_partition", chained_partition_arg]
-  return ["--include_descriptors_from_image", image]
+  if not key_path:
+    return ["--include_descriptors_from_image", image]
+
+  # For a non-A/B device, we don't chain /recovery nor include its descriptor
+  # into vbmeta.img. The recovery image will be configured on an independent
+  # boot chain, to be verified with AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION.
+  # See details at
+  # https://android.googlesource.com/platform/external/avb/+/master/README.md#booting-into-recovery.
+  if OPTIONS.info_dict.get("ab_update") != "true" and partition == "recovery":
+    return []
+
+  # Otherwise chain the partition into vbmeta.
+  chained_partition_arg = GetAvbChainedPartitionArg(partition, info_dict)
+  return ["--chain_partition", chained_partition_arg]
 
 
 def GetAvbChainedPartitionArg(partition, info_dict, key=None):
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 710147b..0ef698e 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -153,6 +153,20 @@
 OPTIONS.avb_extra_args = {}
 
 
+AVB_FOOTER_ARGS_BY_PARTITION = {
+    'boot' : 'avb_boot_add_hash_footer_args',
+    'dtbo' : 'avb_dtbo_add_hash_footer_args',
+    'recovery' : 'avb_recovery_add_hash_footer_args',
+    'system' : 'avb_system_add_hashtree_footer_args',
+    'system_other' : 'avb_system_other_add_hashtree_footer_args',
+    'vendor' : 'avb_vendor_add_hashtree_footer_args',
+    'vendor_boot' : 'avb_vendor_boot_add_hash_footer_args',
+    'vbmeta' : 'avb_vbmeta_args',
+    'vbmeta_system' : 'avb_vbmeta_system_args',
+    'vbmeta_vendor' : 'avb_vbmeta_vendor_args',
+}
+
+
 def GetApkCerts(certmap):
   # apply the key remapping to the contents of the file
   for apk, cert in certmap.items():
@@ -622,6 +636,10 @@
   # Replace the AVB signing keys, if any.
   ReplaceAvbSigningKeys(misc_info)
 
+  # Rewrite the props in AVB signing args.
+  if misc_info.get('avb_enable') == 'true':
+    RewriteAvbProps(misc_info)
+
   # Write back misc_info with the latest values.
   ReplaceMiscInfoTxt(input_tf_zip, output_tf_zip, misc_info)
 
@@ -910,18 +928,6 @@
 def ReplaceAvbSigningKeys(misc_info):
   """Replaces the AVB signing keys."""
 
-  AVB_FOOTER_ARGS_BY_PARTITION = {
-      'boot' : 'avb_boot_add_hash_footer_args',
-      'dtbo' : 'avb_dtbo_add_hash_footer_args',
-      'recovery' : 'avb_recovery_add_hash_footer_args',
-      'system' : 'avb_system_add_hashtree_footer_args',
-      'system_other' : 'avb_system_other_add_hashtree_footer_args',
-      'vendor' : 'avb_vendor_add_hashtree_footer_args',
-      'vbmeta' : 'avb_vbmeta_args',
-      'vbmeta_system' : 'avb_vbmeta_system_args',
-      'vbmeta_vendor' : 'avb_vbmeta_vendor_args',
-  }
-
   def ReplaceAvbPartitionSigningKey(partition):
     key = OPTIONS.avb_keys.get(partition)
     if not key:
@@ -946,6 +952,32 @@
     ReplaceAvbPartitionSigningKey(partition)
 
 
+def RewriteAvbProps(misc_info):
+  """Rewrites the props in AVB signing args."""
+  for partition, args_key in AVB_FOOTER_ARGS_BY_PARTITION.items():
+    args = misc_info.get(args_key)
+    if not args:
+      continue
+
+    tokens = []
+    changed = False
+    for token in args.split(' '):
+      fingerprint_key = 'com.android.build.{}.fingerprint'.format(partition)
+      if not token.startswith(fingerprint_key):
+        tokens.append(token)
+        continue
+      prefix, tag = token.rsplit('/', 1)
+      tokens.append('{}/{}'.format(prefix, EditTags(tag)))
+      changed = True
+
+    if changed:
+      result = ' '.join(tokens)
+      print('Rewriting AVB prop for {}:\n'.format(partition))
+      print('  replace: {}'.format(args))
+      print('     with: {}'.format(result))
+      misc_info[args_key] = result
+
+
 def BuildKeyMap(misc_info, key_mapping_options):
   for s, d in key_mapping_options:
     if s is None:   # -d option
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index e0a635a..2b84413 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -23,7 +23,8 @@
 import test_utils
 from sign_target_files_apks import (
     CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ReadApexKeysInfo,
-    ReplaceCerts, ReplaceVerityKeyId, RewriteProps, WriteOtacerts)
+    ReplaceCerts, ReplaceVerityKeyId, RewriteAvbProps, RewriteProps,
+    WriteOtacerts)
 
 
 class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
@@ -52,6 +53,40 @@
     # Tags are sorted.
     self.assertEqual(EditTags('xyz,abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
 
+  def test_RewriteAvbProps(self):
+    misc_info = {
+      '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_system_add_hashtree_footer_args':
+          ('--prop com.android.build.system.os_version:R '
+           '--prop com.android.build.system.security_patch:2019-09-05 '
+           '--prop com.android.build.system.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/test-keys'),
+      'avb_vendor_add_hashtree_footer_args':
+          ('--prop com.android.build.vendor.os_version:R '
+           '--prop com.android.build.vendor.security_patch:2019-09-05 '
+           '--prop com.android.build.vendor.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/dev-keys'),
+    }
+    expected_dict = {
+      '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_system_add_hashtree_footer_args':
+          ('--prop com.android.build.system.os_version:R '
+           '--prop com.android.build.system.security_patch:2019-09-05 '
+           '--prop com.android.build.system.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/release-keys'),
+      'avb_vendor_add_hashtree_footer_args':
+          ('--prop com.android.build.vendor.os_version:R '
+           '--prop com.android.build.vendor.security_patch:2019-09-05 '
+           '--prop com.android.build.vendor.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/release-keys'),
+    }
+    RewriteAvbProps(misc_info)
+    self.assertDictEqual(expected_dict, misc_info)
+
   def test_RewriteProps(self):
     props = (
         ('', ''),
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index 383ef7b..9c2bc51 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -346,20 +346,25 @@
       key = info_dict['avb_vbmeta_key_path']
 
     # avbtool verifies all the images that have descriptors listed in vbmeta.
+    # Using `--follow_chain_partitions` so it would additionally verify chained
+    # vbmeta partitions (e.g. vbmeta_system).
     image = os.path.join(input_tmp, 'IMAGES', 'vbmeta.img')
     cmd = [info_dict['avb_avbtool'], 'verify_image', '--image', image,
-           '--key', key]
+           '--key', key, '--follow_chain_partitions']
 
     # Append the args for chained partitions if any.
     for partition in common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS:
       key_name = 'avb_' + partition + '_key_path'
       if info_dict.get(key_name) is not None:
+        if info_dict.get('ab_update') != 'true' and partition == 'recovery':
+          continue
+
         # Use the key file from command line if specified; otherwise fall back
         # to the one in info dict.
         key_file = options.get(key_name, info_dict[key_name])
         chained_partition_arg = common.GetAvbChainedPartitionArg(
             partition, info_dict, key_file)
-        cmd.extend(["--expected_chain_partition", chained_partition_arg])
+        cmd.extend(['--expected_chain_partition', chained_partition_arg])
 
     proc = common.Run(cmd)
     stdoutdata, _ = proc.communicate()
@@ -371,6 +376,22 @@
         'Verified %s with avbtool (key: %s):\n%s', image, key,
         stdoutdata.rstrip())
 
+    # avbtool verifies recovery image for non-A/B devices.
+    if (info_dict.get('ab_update') != 'true' and
+        info_dict.get('no_recovery') != 'true'):
+      image = os.path.join(input_tmp, 'IMAGES', 'recovery.img')
+      key = info_dict['avb_recovery_key_path']
+      cmd = [info_dict['avb_avbtool'], 'verify_image', '--image', image,
+             '--key', key]
+      proc = common.Run(cmd)
+      stdoutdata, _ = proc.communicate()
+      assert proc.returncode == 0, \
+          'Failed to verify {} with avbtool (key: {}):\n{}'.format(
+              image, key, stdoutdata)
+      logging.info(
+          'Verified %s with avbtool (key: %s):\n%s', image, key,
+          stdoutdata.rstrip())
+
 
 def main():
   parser = argparse.ArgumentParser(