Support /product partition

This CL adds the following build flags to support building product partition
from Android build system.
- BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS
- BOARD_AVB_PRODUCT_KEY_PATH
- BOARD_AVB_PRODUCT_ALGORITHM
- BOARD_AVB_PRODUCT_ROLLBACK_INDEX_LOCATION
- BOARD_PREBUILT_PRODUCTIMAGE
- BOARD_PRODUCTIMAGE_EXTFS_INODE_COUNT
- BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
- BOARD_PRODUCTIMAGE_PARTITION_SIZE
- BOARD_PRODUCTIMAGE_SQUASHFS_BLOCK_SIZE
- BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR
- BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR_OPT
- BOARD_PRODUCTIMAGE_SQUASHFS_DISABLE_4K_ALIGN
- BOARD_USES_PRODUCTIMAGE
- LOCAL_PRODUCT_MODULE
- PRODUCT_FOOTER_ARGS
- PRODUCT_PRODUCT_BASE_FS_PATH
- PRODUCT_PRODUCT_VERITY_PARTITION
- TARGET_COPY_OUT_PRODUCT
- TARGET_OUT_PRODUCT*

And PRODUCT_PRODUCT_PROPERTIES is added to save product-specific
properties in /product/build.prop.

Bug: 64195575
Test: succeeded building product.img with BOARD_PRODUCTIMAGE_PARTITION_SIZE,
BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE and PRODUCT_PRODUCT_VERITY_PARTITION.

Change-Id: I774e6a38003734421591e51bed103802ff84f432
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index a9863bc..240e5c9 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -75,7 +75,7 @@
 
 
 # Partitions that should have their care_map added to META/care_map.txt.
-PARTITIONS_WITH_CARE_MAP = ('system', 'vendor')
+PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product')
 
 
 class OutputFile(object):
@@ -172,6 +172,20 @@
   return img.name
 
 
+def AddProduct(output_zip, prefix="IMAGES/"):
+  """Turn the contents of PRODUCT into a product image and store it in output_zip."""
+
+  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "product.img")
+  if os.path.exists(img.input_name):
+    print("product.img already exists in %s, no need to rebuild..." % (prefix,))
+    return img.input_name
+
+  block_list = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "product.map")
+  CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "product", img,
+              block_list=block_list)
+  return img.name
+
+
 def AddDtbo(output_zip, prefix="IMAGES/"):
   """Adds the DTBO image.
 
@@ -621,13 +635,16 @@
       print("target_files appears to already contain images.")
       sys.exit(1)
 
-  # vendor.img is unlike system.img or system_other.img. Because it could be
-  # built from source, or dropped into target_files.zip as a prebuilt blob. We
-  # consider either of them as vendor.img being available, which could be used
-  # when generating vbmeta.img for AVB.
+  # {vendor,product}.img is unlike system.img or system_other.img. Because it could
+  # be built from source, or dropped into target_files.zip as a prebuilt blob.
+  # We consider either of them as {vendor,product}.img being available, which could
+  # be used when generating vbmeta.img for AVB.
   has_vendor = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "VENDOR")) or
                 os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES",
                                             "vendor.img")))
+  has_product = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "PRODUCT")) or
+                 os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES",
+                                             "product.img")))
   has_system_other = os.path.isdir(os.path.join(OPTIONS.input_tmp,
                                                 "SYSTEM_OTHER"))
 
@@ -715,6 +732,10 @@
     banner("vendor")
     partitions['vendor'] = AddVendor(output_zip)
 
+  if has_product:
+    banner("product")
+    partitions['product'] = AddProduct(output_zip)
+
   if has_system_other:
     banner("system_other")
     AddSystemOther(output_zip)
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index f07e4b1..123ec7c 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -778,6 +778,22 @@
     copy_prop("vendor_squashfs_disable_4k_align", "squashfs_disable_4k_align")
     copy_prop("vendor_base_fs_file", "base_fs_file")
     copy_prop("vendor_extfs_inode_count", "extfs_inode_count")
+  elif mount_point == "product":
+    copy_prop("avb_product_hashtree_enable", "avb_hashtree_enable")
+    copy_prop("avb_product_add_hashtree_footer_args",
+              "avb_add_hashtree_footer_args")
+    copy_prop("avb_product_key_path", "avb_key_path")
+    copy_prop("avb_product_algorithm", "avb_algorithm")
+    copy_prop("product_fs_type", "fs_type")
+    copy_prop("product_size", "partition_size")
+    copy_prop("product_journal_size", "journal_size")
+    copy_prop("product_verity_block_device", "verity_block_device")
+    copy_prop("product_squashfs_compressor", "squashfs_compressor")
+    copy_prop("product_squashfs_compressor_opt", "squashfs_compressor_opt")
+    copy_prop("product_squashfs_block_size", "squashfs_block_size")
+    copy_prop("product_squashfs_disable_4k_align", "squashfs_disable_4k_align")
+    copy_prop("product_base_fs_file", "base_fs_file")
+    copy_prop("product_extfs_inode_count", "extfs_inode_count")
   elif mount_point == "oem":
     copy_prop("fs_type", "fs_type")
     copy_prop("oem_size", "partition_size")
@@ -831,6 +847,8 @@
       mount_point = "vendor"
     elif image_filename == "oem.img":
       mount_point = "oem"
+    elif image_filename == "product.img":
+      mount_point = "product"
     else:
       print("error: unknown image file name ", image_filename, file=sys.stderr)
       sys.exit(1)
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index faadae9..632cc11 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -78,7 +78,7 @@
 
 
 # The partitions allowed to be signed by AVB (Android verified boot 2.0).
-AVB_PARTITIONS = ('boot', 'recovery', 'system', 'vendor', 'dtbo')
+AVB_PARTITIONS = ('boot', 'recovery', 'system', 'vendor', 'product', 'dtbo')
 
 
 class ErrorCode(object):