Always set a avb salt for hermetic build

When building images via `m` , build_image.py is invoked directly
without going through add_img_to_target_files. To ensure images built in
either way are identical, move uuid/salt computation to build_image.py,
so that the same uuid/salt will be used.

Bug: 281960439
Test: m installclean && m && m target-files-dir , maks sure images in
$OUT and $OUT/obj/PACKING/target_files_intermediates are identical

Change-Id: Icdab29df84f5a0ec7c080f99f9fdbdc3c9b10b90
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 8d660f8..465d222 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -68,6 +68,7 @@
 from concurrent.futures import ThreadPoolExecutor
 from apex_utils import GetApexInfoFromTargetFiles
 from common import ZipDelete, PARTITIONS_WITH_CARE_MAP, ExternalError, RunAndCheckOutput, IsSparseImage, MakeTempFile, ZipWrite
+from build_image import FIXED_FILE_TIMESTAMP
 
 if sys.hexversion < 0x02070000:
   print("Python 2.7 or newer is required.", file=sys.stderr)
@@ -81,12 +82,6 @@
 OPTIONS.replace_updated_files_list = []
 OPTIONS.is_signing = False
 
-# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
-# images. (b/24377993, b/80600931)
-FIXED_FILE_TIMESTAMP = int((
-    datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
-    datetime.datetime.utcfromtimestamp(0)).total_seconds())
-
 
 def ParseAvbFooter(img_path) -> avbtool.AvbFooter:
   with open(img_path, 'rb') as fp:
@@ -594,15 +589,6 @@
   if block_list:
     image_props["block_list"] = block_list.name
 
-  # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
-  # build fingerprint). Also use the legacy build id, because the vbmeta digest
-  # isn't available at this point.
-  build_info = common.BuildInfo(info_dict, use_legacy_id=True)
-  uuid_seed = what + "-" + build_info.GetPartitionFingerprint(what)
-  image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
-  hash_seed = "hash_seed-" + uuid_seed
-  image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
-
   build_image.BuildImage(
       os.path.join(input_dir, what.upper()), image_props, output_file.name)
 
@@ -1144,14 +1130,18 @@
           item for item in vbmeta_partitions
           if item not in vbmeta_vendor.split()]
       vbmeta_partitions.append("vbmeta_vendor")
-    custom_avb_partitions = OPTIONS.info_dict.get("avb_custom_vbmeta_images_partition_list", "").strip().split()
+    custom_avb_partitions = OPTIONS.info_dict.get(
+        "avb_custom_vbmeta_images_partition_list", "").strip().split()
     if custom_avb_partitions:
       for avb_part in custom_avb_partitions:
         partition_name = "vbmeta_" + avb_part
-        included_partitions = OPTIONS.info_dict.get("avb_vbmeta_{}".format(avb_part), "").strip().split()
-        assert included_partitions, "Custom vbmeta partition {0} missing avb_vbmeta_{0} prop".format(avb_part)
+        included_partitions = OPTIONS.info_dict.get(
+            "avb_vbmeta_{}".format(avb_part), "").strip().split()
+        assert included_partitions, "Custom vbmeta partition {0} missing avb_vbmeta_{0} prop".format(
+            avb_part)
         banner(partition_name)
-        logger.info("VBMeta partition {} needs {}".format(partition_name, included_partitions))
+        logger.info("VBMeta partition {} needs {}".format(
+            partition_name, included_partitions))
         partitions[partition_name] = AddVBMeta(
             output_zip, partitions, partition_name, included_partitions)
         vbmeta_partitions = [
@@ -1159,7 +1149,6 @@
             if item not in included_partitions]
         vbmeta_partitions.append(partition_name)
 
-
     if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
       banner("vbmeta")
       AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 9064136..11bd784 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -23,24 +23,34 @@
 """
 
 from __future__ import print_function
+import datetime
 
 import glob
 import logging
 import os
 import os.path
 import re
+import shlex
 import shutil
 import sys
+import uuid
 
 import common
 import verity_utils
 
+
 logger = logging.getLogger(__name__)
 
 OPTIONS = common.OPTIONS
 BLOCK_SIZE = common.BLOCK_SIZE
 BYTES_IN_MB = 1024 * 1024
 
+# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
+# images. (b/24377993, b/80600931)
+FIXED_FILE_TIMESTAMP = int((
+    datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
+    datetime.datetime.utcfromtimestamp(0)).total_seconds())
+
 
 class BuildImageError(Exception):
   """An Exception raised during image building."""
@@ -487,6 +497,20 @@
     raise
 
 
+def SetUUIDIfNotExist(image_props):
+
+  # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
+  # build fingerprint). Also use the legacy build id, because the vbmeta digest
+  # isn't available at this point.
+  what = image_props["mount_point"]
+  fingerprint = image_props.get("fingerprint", "")
+  uuid_seed = what + "-" + fingerprint
+  logger.info("Using fingerprint %s for partition %s", fingerprint, what)
+  image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
+  hash_seed = "hash_seed-" + uuid_seed
+  image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
+
+
 def BuildImage(in_dir, prop_dict, out_file, target_out=None):
   """Builds an image for the files under in_dir and writes it to out_file.
 
@@ -504,6 +528,7 @@
     BuildImageError: On build image failures.
   """
   in_dir, fs_config = SetUpInDirAndFsConfig(in_dir, prop_dict)
+  SetUUIDIfNotExist(prop_dict)
 
   build_command = []
   fs_type = prop_dict.get("fs_type", "")
@@ -635,6 +660,19 @@
     verity_image_builder.Build(out_file)
 
 
+def TryParseFingerprint(glob_dict: dict):
+  for (key, val) in glob_dict.items():
+    if not key.endswith("_add_hashtree_footer_args") and not key.endswith("_add_hash_footer_args"):
+      continue
+    for arg in shlex.split(val):
+      m = re.match(r"^com\.android\.build\.\w+\.fingerprint:", arg)
+      if m is None:
+        continue
+      fingerprint = arg[len(m.group()):]
+      glob_dict["fingerprint"] = fingerprint
+      return
+
+
 def ImagePropFromGlobalDict(glob_dict, mount_point):
   """Build an image property dictionary from the global dictionary.
 
@@ -643,7 +681,9 @@
     mount_point: such as "system", "data" etc.
   """
   d = {}
+  TryParseFingerprint(glob_dict)
 
+  d["timestamp"] = FIXED_FILE_TIMESTAMP
   if "build.prop" in glob_dict:
     timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
     if timestamp:
@@ -680,6 +720,7 @@
       "avb_enable",
       "avb_avbtool",
       "use_dynamic_partition_size",
+      "fingerprint",
   )
   for p in common_props:
     copy_prop(p, p)
@@ -870,10 +911,9 @@
           if item not in vbmeta_vendor.split()]
       vbmeta_partitions.append("vbmeta_vendor")
 
-
   partitions = {part: os.path.join(in_dir, part + ".img")
                 for part in vbmeta_partitions}
-  partitions = {part:path for (part, path) in partitions.items() if os.path.exists(path)}
+  partitions = {part: path for (part, path) in partitions.items() if os.path.exists(path)}
   common.BuildVBMeta(output_path, partitions, name, vbmeta_partitions)
 
 
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 7adc9fa..1293e90 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -928,20 +928,7 @@
         input_file, partition, ramdisk_format=ramdisk_format)
   d["build.prop"] = d["system.build.prop"]
 
-  # Set up the salt (based on fingerprint) that will be used when adding AVB
-  # hash / hashtree footers.
   if d.get("avb_enable") == "true":
-    build_info = BuildInfo(d, use_legacy_id=True)
-    for partition in PARTITIONS_WITH_BUILD_PROP:
-      fingerprint = build_info.GetPartitionFingerprint(partition)
-      if fingerprint:
-        d["avb_{}_salt".format(partition)] = sha256(
-            fingerprint.encode()).hexdigest()
-
-    # Set up the salt for partitions without build.prop
-    if build_info.fingerprint:
-      d["avb_salt"] = sha256(build_info.fingerprint.encode()).hexdigest()
-
     # Set the vbmeta digest if exists
     try:
       d["vbmeta_digest"] = read_helper("META/vbmeta_digest.txt").rstrip()
diff --git a/tools/releasetools/verity_utils.py b/tools/releasetools/verity_utils.py
index dddb7f4..7caeed4 100644
--- a/tools/releasetools/verity_utils.py
+++ b/tools/releasetools/verity_utils.py
@@ -31,6 +31,7 @@
 import common
 import sparse_img
 from rangelib import RangeSet
+from hashlib import sha256
 
 logger = logging.getLogger(__name__)
 
@@ -42,6 +43,7 @@
 MAX_VBMETA_SIZE = 64 * 1024
 MAX_FOOTER_SIZE = 4096
 
+
 class BuildVerityImageError(Exception):
   """An Exception raised during verity image building."""
 
@@ -64,6 +66,11 @@
   # partition_size could be None at this point, if using dynamic partitions.
   if partition_size:
     partition_size = int(partition_size)
+  # Set up the salt (based on fingerprint) that will be used when adding AVB
+  # hash / hashtree footers.
+  salt = prop_dict.get("avb_salt")
+  if salt is None:
+    salt = sha256(prop_dict.get("fingerprint", "").encode()).hexdigest()
 
   # Verified Boot 2.0
   if (prop_dict.get("avb_hash_enable") == "true" or
@@ -81,7 +88,7 @@
           prop_dict["avb_avbtool"],
           key_path,
           algorithm,
-          prop_dict.get("avb_salt"),
+          salt,
           prop_dict["avb_add_hash_footer_args"])
 
     # Image uses hashtree footer.
@@ -92,7 +99,7 @@
         prop_dict["avb_avbtool"],
         key_path,
         algorithm,
-        prop_dict.get("avb_salt"),
+        salt,
         prop_dict["avb_add_hashtree_footer_args"])
 
   return None
@@ -279,7 +286,7 @@
 
 
 def CreateCustomImageBuilder(info_dict, partition_name, partition_size,
-                            key_path, algorithm, signing_args):
+                             key_path, algorithm, signing_args):
   builder = None
   if info_dict.get("avb_enable") == "true":
     builder = VerifiedBootVersion2VerityImageBuilder(