Generate care_map.pb when merging target files packages.

Test: build a merged target using Forrest,
      Observe META/care_map.pb
Bug: 182296208
Change-Id: Ic269fa99ec8ed2bd474a2f69b1be1f545c567112
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 16cab4f..17d3030 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -96,12 +96,17 @@
 from xml.etree import ElementTree
 
 import add_img_to_target_files
+import build_image
 import build_super_image
 import check_target_files_vintf
 import common
 import img_from_target_files
 import find_shareduid_violation
 import ota_from_target_files
+import sparse_img
+import verity_utils
+
+from common import AddCareMapForAbOta, ExternalError, PARTITIONS_WITH_CARE_MAP
 
 logger = logging.getLogger(__name__)
 
@@ -355,8 +360,9 @@
           ' includes %s.', partition, partition)
       has_error = True
 
-  if ('dynamic_partition_list' in framework_misc_info_keys) or (
-      'super_partition_groups' in framework_misc_info_keys):
+  if ('dynamic_partition_list'
+      in framework_misc_info_keys) or ('super_partition_groups'
+                                       in framework_misc_info_keys):
     logger.error('Dynamic partition misc info keys should come from '
                  'the vendor instance of META/misc_info.txt.')
     has_error = True
@@ -447,8 +453,8 @@
     merged_dict[key] = framework_dict[key]
 
   # Merge misc info keys used for Dynamic Partitions.
-  if (merged_dict.get('use_dynamic_partitions') == 'true') and (
-      framework_dict.get('use_dynamic_partitions') == 'true'):
+  if (merged_dict.get('use_dynamic_partitions')
+      == 'true') and (framework_dict.get('use_dynamic_partitions') == 'true'):
     merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
         framework_dict=framework_dict, vendor_dict=merged_dict)
     merged_dict.update(merged_dynamic_partitions_dict)
@@ -733,6 +739,42 @@
   return cmd
 
 
+def generate_care_map(partitions, output_target_files_dir):
+  """Generates a merged META/care_map.pb file in the output target files dir.
+
+  Depends on the info dict from META/misc_info.txt, as well as built images
+  within IMAGES/.
+
+  Args:
+    partitions: A list of partitions to potentially include in the care map.
+    output_target_files_dir: The name of a directory that will be used to create
+      the output target files package after all the special cases are processed.
+  """
+  OPTIONS.info_dict = common.LoadInfoDict(output_target_files_dir)
+  partition_image_map = {}
+  for partition in partitions:
+    image_path = os.path.join(output_target_files_dir, 'IMAGES',
+                              '{}.img'.format(partition))
+    if os.path.exists(image_path):
+      partition_image_map[partition] = image_path
+      # Regenerated images should have their image_size property already set.
+      image_size_prop = '{}_image_size'.format(partition)
+      if image_size_prop not in OPTIONS.info_dict:
+        # Images copied directly from input target files packages will need
+        # their image sizes calculated.
+        partition_size = sparse_img.GetImagePartitionSize(image_path)
+        image_props = build_image.ImagePropFromGlobalDict(
+            OPTIONS.info_dict, partition)
+        verity_image_builder = verity_utils.CreateVerityImageBuilder(
+            image_props)
+        image_size = verity_image_builder.CalculateMaxImageSize(partition_size)
+        OPTIONS.info_dict[image_size_prop] = image_size
+
+  AddCareMapForAbOta(
+      os.path.join(output_target_files_dir, 'META', 'care_map.pb'),
+      PARTITIONS_WITH_CARE_MAP, partition_image_map)
+
+
 def process_special_cases(framework_target_files_temp_dir,
                           vendor_target_files_temp_dir,
                           output_target_files_temp_dir,
@@ -1087,12 +1129,14 @@
   if not output_target_files:
     return
 
+  # Create the merged META/care_map.bp
+  generate_care_map(partition_map.keys(), output_target_files_temp_dir)
+
   output_zip = create_target_files_archive(output_target_files,
                                            output_target_files_temp_dir,
                                            temp_dir)
 
   # Create the IMG package from the merged target files package.
-
   if output_img:
     img_from_target_files.main([output_zip, output_img])