AVB: decouple vbmeta.img from recovery.img for non-A/B devices

For following cases:
Case 1: A/B devices: no change
Case 2: non-A/B devices, with unsigned recovery image:
    not allowed anymore by mandating BOARD_AVB_RECOVERY_KEY_PATH
Case 3: non-A/B devices, with signed recovery image:
    vbmeta.img should not include ChainPartitionDescriptor of recovery.img,
    otherwise device can not even boot into normal mode if recovery partition
    is damaged

This CL will cause a build break if BOARD_AVB_RECOVERY_KEY_PATH
is not set for non-A/B targets with recovery.img
The following is an example to fix the build break by specifying
AVB signing configs for the recovery.img.

BOARD_AVB_RECOVERY_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_RECOVERY_ALGORITHM := SHA256_RSA2048
BOARD_AVB_RECOVERY_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION := 2

Also note that libavb in bootloader needs an update to include this
commit Iaa886037edb18c2ff6c60fa2a7f883ab7303ba1a, to support verifying
recovery.img independently (not through vbmeta.img).

Bug: 130351427
Test (Case 3):
  normal   mode: avb_slot_verify(flags=AVB_SLOT_VERIFY_FLAGS_NONE)
  recovery mode: avb_slot_verify(flags=AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)
Test: PYTHONPATH=build/make/tools/releasetools \
    python -m unittest test_validate_target_files
Test: Use a lunch'd target. `atest --host releasetools_test releasetools_py3_test`
Test: validate_target_files.py with Case-3 target files
Change-Id: I2a73252b385fa463b4abd444923a8acc473df0b4
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(