Adds new merge builds script for use in merging two non-dist builds.

Bug: 137853921
Test: python -m unittest test_common
Test: python -m unittest test_merge_target_files
Test: Built two partial builds without dist. Ran out/host/linux-x86/bin/merge_builds.
Flashed using `fastboot flashall`. Device boots.
Change-Id: Iffd0a447cdf19a7775a813b4b896178aa6f861f3
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 913601f..1175688 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -554,6 +554,64 @@
     logger.info("%-25s = (%s) %s", k, type(v).__name__, v)
 
 
+def MergeDynamicPartitionInfoDicts(framework_dict,
+                                   vendor_dict,
+                                   include_dynamic_partition_list=True,
+                                   size_prefix="",
+                                   size_suffix="",
+                                   list_prefix="",
+                                   list_suffix=""):
+  """Merges dynamic partition info variables.
+
+  Args:
+    framework_dict: The dictionary of dynamic partition info variables from the
+      partial framework target files.
+    vendor_dict: The dictionary of dynamic partition info variables from the
+      partial vendor target files.
+    include_dynamic_partition_list: If true, merges the dynamic_partition_list
+      variable. Not all use cases need this variable merged.
+    size_prefix: The prefix in partition group size variables that precedes the
+      name of the partition group. For example, partition group 'group_a' with
+      corresponding size variable 'super_group_a_group_size' would have the
+      size_prefix 'super_'.
+    size_suffix: Similar to size_prefix but for the variable's suffix. For
+      example, 'super_group_a_group_size' would have size_suffix '_group_size'.
+    list_prefix: Similar to size_prefix but for the partition group's
+      partition_list variable.
+    list_suffix: Similar to size_suffix but for the partition group's
+      partition_list variable.
+
+  Returns:
+    The merged dynamic partition info dictionary.
+  """
+  merged_dict = {}
+  # Partition groups and group sizes are defined by the vendor dict because
+  # these values may vary for each board that uses a shared system image.
+  merged_dict["super_partition_groups"] = vendor_dict["super_partition_groups"]
+  if include_dynamic_partition_list:
+    framework_dynamic_partition_list = framework_dict.get(
+        "dynamic_partition_list", "")
+    vendor_dynamic_partition_list = vendor_dict.get("dynamic_partition_list",
+                                                    "")
+    merged_dict["dynamic_partition_list"] = (
+        "%s %s" % (framework_dynamic_partition_list,
+                   vendor_dynamic_partition_list)).strip()
+  for partition_group in merged_dict["super_partition_groups"].split(" "):
+    # Set the partition group's size using the value from the vendor dict.
+    key = "%s%s%s" % (size_prefix, partition_group, size_suffix)
+    if key not in vendor_dict:
+      raise ValueError("Vendor dict does not contain required key %s." % key)
+    merged_dict[key] = vendor_dict[key]
+
+    # Set the partition group's partition list using a concatenation of the
+    # framework and vendor partition lists.
+    key = "%s%s%s" % (list_prefix, partition_group, list_suffix)
+    merged_dict[key] = (
+        "%s %s" %
+        (framework_dict.get(key, ""), vendor_dict.get(key, ""))).strip()
+  return merged_dict
+
+
 def AppendAVBSigningArgs(cmd, partition):
   """Append signing arguments for avbtool."""
   # e.g., "--key path/to/signing_key --algorithm SHA256_RSA4096"