Merge "Fix odm output directory for devices w/o vendor partition"
diff --git a/core/Makefile b/core/Makefile
index 1b6c532..368624f 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -3289,6 +3289,17 @@
   $(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 += \
@@ -3358,8 +3369,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/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/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/tools/releasetools/common.py b/tools/releasetools/common.py
index d73628f..b7a7f37 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -873,10 +873,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/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(