Add support for /product-services partition

This CL is largely an adaptation of Change-Id
I774e6a38003734421591e51bed103802ff84f432

It adds the following variables:

- BOARD_AVB_PRODUCT_SERVICES_KEY_PATH
- BOARD_AVB_PRODUCT_SERVICES_ALGORITHM
- BOARD_AVB_PRODUCT_SERVICES_ROLLBACK_INDEX_LOCATION
- BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
- BOARD_PRODUCT_SERVICESIMAGE_EXTFS_INODE_COUNT
- BOARD_PRODUCT_SERVICESIMAGE_EXTFS_RSV_PCT
- BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE
- BOARD_PRODUCT_SERVICESIMAGE_JOURNAL_SIZE
- BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_BLOCK_SIZE
- BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_COMPRESSOR
- BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_COMPRESSOR_OPT
- BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_DISABLE_4K_ALIGN
- BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
- BOARD_USES_PRODUCT_SERVICESIMAGE
- LOCAL_PRODUCT_SERVICES_MODULE
- PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH
- PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION
- PRODUCT_PRODUCT_SERVICES_PROPERTIES
- TARGET_COPY_OUT_PRODUCT_SERVICES
- TARGET_OUT_PRODUCT_SERVICES
- TARGET_OUT_PRODUCT_SERVICES_*

Bug: 80741439
Test: Successfully built product-services.img with one module in it, and flashed
on device. Also successfully built image with /system/product-services directory
and no /product-services partition.
Change-Id: I5d229f6ac729ea6df9ff1f14cee2e28972cd9b4d
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 8ac039f..3e5dd52 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -74,7 +74,7 @@
 
 
 # Partitions that should have their care_map added to META/care_map.txt.
-PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product')
+PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product', 'product-services')
 
 
 class OutputFile(object):
@@ -196,6 +196,24 @@
   return img.name
 
 
+def AddProductServices(output_zip):
+  """Turn the contents of PRODUCT_SERVICES into a product-services image and
+  store it in output_zip."""
+
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES",
+                   "product-services.img")
+  if os.path.exists(img.input_name):
+    print("product-services.img already exists; no need to rebuild...")
+    return img.input_name
+
+  block_list = OutputFile(
+      output_zip, OPTIONS.input_tmp, "IMAGES", "product-services.map")
+  CreateImage(
+      OPTIONS.input_tmp, OPTIONS.info_dict, "product-services", img,
+      block_list=block_list)
+  return img.name
+
+
 def AddDtbo(output_zip):
   """Adds the DTBO image.
 
@@ -628,16 +646,22 @@
 
   has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
 
-  # {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.
+  # {vendor,product,product-services}.img are 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,product-services}.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_productservices = (os.path.isdir(os.path.join(OPTIONS.input_tmp,
+                                                    "PRODUCTSERVICES")) or
+                         os.path.exists(os.path.join(OPTIONS.input_tmp,
+                                                     "IMAGES",
+                                                     "product-services.img")))
   has_system_other = os.path.isdir(os.path.join(OPTIONS.input_tmp,
                                                 "SYSTEM_OTHER"))
 
@@ -714,6 +738,10 @@
     banner("product")
     partitions['product'] = AddProduct(output_zip)
 
+  if has_productservices:
+    banner("product-services")
+    partitions['product-services'] = AddProductServices(output_zip)
+
   if has_system_other:
     banner("system_other")
     AddSystemOther(output_zip)