Update Security String to 2023-02-01 am: b601ce96db

Original change: https://googleplex-android-review.googlesource.com/c/platform/build/+/20665910

Change-Id: I524f6521a7aa06e1cb27b5217486ab3141d2978b
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 7c9c6da..386e14c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -639,6 +639,10 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/odm/build.prop)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/odm/build.prop)
 
+# Remove libcameraservice and libcamera_client from base_system
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libcameraservice.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libcamera_client.so)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 589f6ac..d7d1965 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -3417,6 +3417,14 @@
 $(if $(filter true,$(AB_OTA_UPDATER)),$(if $(filter true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS)),,_a))
 endef
 
+ifndef BOARD_SUPER_PARTITION_WARN_LIMIT
+BOARD_SUPER_PARTITION_WARN_LIMIT := $$(($(BOARD_SUPER_PARTITION_SIZE) * 95 / 100))
+endif
+
+ifndef BOARD_SUPER_PARTITION_ERROR_LIMIT
+BOARD_SUPER_PARTITION_ERROR_LIMIT := $(BOARD_SUPER_PARTITION_SIZE)
+endif
+
 droid_targets: check-all-partition-sizes
 
 .PHONY: check-all-partition-sizes check-all-partition-sizes-nodeps
@@ -3447,6 +3455,10 @@
 # $(1): human-readable max size string
 # $(2): max size expression
 # $(3): list of partition names
+# $(4): human-readable warn size string
+# $(5): warn size expression
+# $(6): human readable error size string
+# $(7): error size expression
 define check-sum-of-partition-sizes
   partition_size_list="$$(for i in $(call read-size-of-partitions,$(3)); do \
     echo $(call round-partition-size,$${i}); \
@@ -3457,6 +3469,17 @@
     echo $${sum_sizes_expr} '==' $$(( $${sum_sizes_expr} )) '>' "$(2)" '==' $$(( $(2) )); \
     exit 1; \
   else \
+    if [[ ! -z "$(7)" ]] && [ $$(( $${sum_sizes_expr} )) -gt $$(( $(7) )) ]; then \
+        echo "!!!! ERROR !!!! The sum of sizes of [$(strip $(3))] is larger than $(strip $(6)):"; \
+        echo $${sum_sizes_expr} '==' $$(( $${sum_sizes_expr} )) '>' "$(7)" '==' $$(( $(7) )); \
+        echo "Super partition is" $$(( $$(( $$(( $${sum_sizes_expr} )) * 100)) / $$(( $(2) )) )) "percent occupied!"; \
+        exit 1; \
+    fi; \
+    if [[ ! -z "$(5)" ]] && [ $$(( $${sum_sizes_expr} )) -gt $$(( $(5) )) ]; then \
+        echo "!!!! WARNING !!!! The sum of sizes of [$(strip $(3))] is larger than $(strip $(4)):"; \
+        echo $${sum_sizes_expr} '==' $$(( $${sum_sizes_expr} )) '>' "$(5)" '==' $$(( $(5) )); \
+        echo "Super partition is" $$(( $$(( $$(( $${sum_sizes_expr} )) * 100)) / $$(( $(2) )) )) "percent occupied!"; \
+    fi; \
     echo "The sum of sizes of [$(strip $(3))] is within $(strip $(1)):"; \
     echo $${sum_sizes_expr} '==' $$(( $${sum_sizes_expr} )) '<=' "$(2)" '==' $$(( $(2) )); \
   fi;
@@ -3466,7 +3489,12 @@
   # Check sum(all partitions) <= super partition (/ 2 for A/B devices launched with dynamic partitions)
   $(if $(BOARD_SUPER_PARTITION_SIZE),$(if $(BOARD_SUPER_PARTITION_PARTITION_LIST), \
     $(call check-sum-of-partition-sizes,BOARD_SUPER_PARTITION_SIZE$(if $(call super-slot-suffix), / 2), \
-      $(BOARD_SUPER_PARTITION_SIZE)$(if $(call super-slot-suffix), / 2),$(BOARD_SUPER_PARTITION_PARTITION_LIST))))
+      $(BOARD_SUPER_PARTITION_SIZE)$(if $(call super-slot-suffix), / 2),$(BOARD_SUPER_PARTITION_PARTITION_LIST), \
+      BOARD_SUPER_PARTITION_WARN_LIMIT$(if $(call super-slot-suffix), / 2), \
+      $(BOARD_SUPER_PARTITION_WARN_LIMIT)$(if $(call super-slot-suffix), / 2), \
+      BOARD_SUPER_PARTITION_ERROR_LIMIT$(if $(call super-slot-suffix), / 2), \
+      $(BOARD_SUPER_PARTITION_ERROR_LIMIT)$(if $(call super-slot-suffix), / 2)) \
+  ))
 
   # For each group, check sum(partitions in group) <= group size
   $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
@@ -3545,6 +3573,7 @@
 ifeq ($(build_otatools_package),true)
 OTATOOLS :=  $(HOST_OUT_EXECUTABLES)/minigzip \
   $(HOST_OUT_EXECUTABLES)/aapt \
+  $(HOST_OUT_EXECUTABLES)/aapt2 \
   $(HOST_OUT_EXECUTABLES)/checkvintf \
   $(HOST_OUT_EXECUTABLES)/mkbootfs \
   $(HOST_OUT_EXECUTABLES)/mkbootimg \
@@ -4432,6 +4461,19 @@
 
 endif # TARGET_BUILD_APPS
 
+
+ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
+
+# Dump variables used by build_super_image.py (for building super.img and super_empty.img).
+# $(1): output file
+define dump-super-image-info
+  $(call dump-dynamic-partitions-info,$(1))
+  $(if $(filter true,$(AB_OTA_UPDATER)), \
+    echo "ab_update=true" >> $(1))
+endef
+
+endif # PRODUCT_USE_DYNAMIC_PARTITIONS
+
 # -----------------------------------------------------------------
 # super partition image (dist)
 
@@ -4440,13 +4482,6 @@
 # BOARD_SUPER_PARTITION_SIZE must be defined to build super image.
 ifneq ($(BOARD_SUPER_PARTITION_SIZE),)
 
-# Dump variables used by build_super_image.py.
-define dump-super-image-info
-  $(call dump-dynamic-partitions-info,$(1))
-  $(if $(filter true,$(AB_OTA_UPDATER)), \
-    echo "ab_update=true" >> $(1))
-endef
-
 ifneq (true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS))
 
 # For real devices and for dist builds, build super image from target files to an intermediate directory.
@@ -4526,7 +4561,7 @@
 # -----------------------------------------------------------------
 # super empty image
 
-ifeq (true,$(PRODUCT_BUILD_SUPER_PARTITION))
+ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
 ifneq ($(BOARD_SUPER_PARTITION_SIZE),)
 
 INSTALLED_SUPERIMAGE_EMPTY_TARGET := $(PRODUCT_OUT)/super_empty.img
@@ -4542,7 +4577,7 @@
 $(call dist-for-goals,dist_files,$(INSTALLED_SUPERIMAGE_EMPTY_TARGET))
 
 endif # BOARD_SUPER_PARTITION_SIZE != ""
-endif # PRODUCT_BUILD_SUPER_PARTITION == "true"
+endif # PRODUCT_USE_DYNAMIC_PARTITIONS == "true"
 
 
 # -----------------------------------------------------------------
diff --git a/core/board_config.mk b/core/board_config.mk
index ac0f27d..e58b123 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -508,8 +508,16 @@
 # APEXes are by default flattened, i.e. non-updatable.
 # It can be unflattened (and updatable) by inheriting from
 # updatable_apex.mk
-ifeq (,$(TARGET_FLATTEN_APEX))
-TARGET_FLATTEN_APEX := true
+#
+# APEX flattening can also be forcibly enabled (resp. disabled) by
+# setting OVERRIDE_TARGET_FLATTEN_APEX to true (resp. false), e.g. by
+# setting the OVERRIDE_TARGET_FLATTEN_APEX environment variable.
+ifdef OVERRIDE_TARGET_FLATTEN_APEX
+  TARGET_FLATTEN_APEX := $(OVERRIDE_TARGET_FLATTEN_APEX)
+else
+  ifeq (,$(TARGET_FLATTEN_APEX))
+    TARGET_FLATTEN_APEX := true
+  endif
 endif
 
 ifeq (,$(TARGET_BUILD_APPS))
diff --git a/core/config.mk b/core/config.mk
index 8c73281..4386489 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -888,16 +888,12 @@
 #     - BOARD_{GROUP}_PARTITION_PARTITION_LIST: the list of partitions that belongs to this group.
 #       If empty, no partitions belong to this group, and the sum of sizes is effectively 0.
 $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
-    $(eval BOARD_$(group)_PARTITION_LIST ?=) \
-    $(eval .KATI_READONLY := BOARD_$(group)_PARTITION_LIST) \
-)
-ifeq ($(PRODUCT_BUILD_SUPER_PARTITION),true)
-$(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
     $(eval BOARD_$(group)_SIZE := $(strip $(BOARD_$(group)_SIZE))) \
     $(if $(BOARD_$(group)_SIZE),,$(error BOARD_$(group)_SIZE must not be empty)) \
     $(eval .KATI_READONLY := BOARD_$(group)_SIZE) \
+    $(eval BOARD_$(group)_PARTITION_LIST ?=) \
+    $(eval .KATI_READONLY := BOARD_$(group)_PARTITION_LIST) \
 )
-endif # PRODUCT_BUILD_SUPER_PARTITION
 
 # BOARD_*_PARTITION_LIST: a list of the following tokens
 valid_super_partition_list := system vendor product product_services odm
@@ -919,10 +915,6 @@
         $(BOARD_$(group)_PARTITION_LIST))
 .KATI_READONLY := BOARD_SUPER_PARTITION_PARTITION_LIST
 
-endif # PRODUCT_USE_DYNAMIC_PARTITIONS
-
-ifeq ($(PRODUCT_BUILD_SUPER_PARTITION),true)
-
 ifneq ($(BOARD_SUPER_PARTITION_SIZE),)
 ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
 
@@ -982,8 +974,11 @@
 
 endif # PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
 endif # BOARD_SUPER_PARTITION_SIZE
+BOARD_SUPER_PARTITION_BLOCK_DEVICES ?=
 .KATI_READONLY := BOARD_SUPER_PARTITION_BLOCK_DEVICES
+BOARD_SUPER_PARTITION_METADATA_DEVICE ?=
 .KATI_READONLY := BOARD_SUPER_PARTITION_METADATA_DEVICE
+BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE ?=
 .KATI_READONLY := BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE
 
 $(foreach device,$(call to-upper,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES)), \
@@ -992,7 +987,7 @@
         $(error BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE must not be empty)) \
     $(eval .KATI_READONLY := BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE))
 
-endif # PRODUCT_BUILD_SUPER_PARTITION
+endif # PRODUCT_USE_DYNAMIC_PARTITIONS
 
 # ###############################################################
 # Set up final options.
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index ecc217d..2f8a634 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -123,8 +123,6 @@
     libbinder_ndk \
     libc.bootstrap \
     libcamera2ndk \
-    libcamera_client \
-    libcameraservice \
     libc_malloc_debug \
     libc_malloc_hooks \
     libcutils \
diff --git a/target/product/developer_gsi_keys.mk b/target/product/developer_gsi_keys.mk
new file mode 100644
index 0000000..a7e3d62
--- /dev/null
+++ b/target/product/developer_gsi_keys.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2019 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Device makers who are willing to support booting the public Developer-GSI
+# in locked state can add the following line into a device.mk to inherit this
+# makefile. This file will then install the up-to-date GSI public keys into
+# the first-stage ramdisk to pass verified boot.
+#
+# In device/<company>/<board>/device.mk:
+#   $(call inherit-product, $(SRC_TARGET_DIR)/product/developer_gsi_keys.mk)
+#
+# Currently, the developer GSI images can be downloaded from the following URL:
+#   https://developer.android.com/topic/generic-system-image/releases
+#
+PRODUCT_PACKAGES += \
+    q-developer-gsi.avbpubkey \
+    r-developer-gsi.avbpubkey \
+    s-developer-gsi.avbpubkey \
diff --git a/target/product/emulator_system.mk b/target/product/emulator_system.mk
new file mode 100644
index 0000000..4b6987c
--- /dev/null
+++ b/target/product/emulator_system.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# This file lists emulator experimental modules added to PRODUCT_PACKAGES,
+# only included by targets sdk_phone_x86/64 and sdk_gphone_x86/64
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST := \
+    system/lib/libemulator_multidisplay_jni.so \
+    system/lib64/libemulator_multidisplay_jni.so \
+    system/priv-app/MultiDisplayProvider/MultiDisplayProvider.apk \
+
+PRODUCT_PACKAGES += MultiDisplayProvider
diff --git a/target/product/handheld_product.mk b/target/product/handheld_product.mk
index 0d100b2..54dcaf2 100644
--- a/target/product/handheld_product.mk
+++ b/target/product/handheld_product.mk
@@ -27,7 +27,6 @@
     Camera2 \
     Contacts \
     DeskClock \
-    Email \
     Gallery2 \
     LatinIME \
     Launcher3QuickStep \
diff --git a/target/product/updatable_apex.mk b/target/product/updatable_apex.mk
index 038f66e..9b87165 100644
--- a/target/product/updatable_apex.mk
+++ b/target/product/updatable_apex.mk
@@ -16,6 +16,8 @@
 
 # Inherit this when the target needs to support updating APEXes
 
-PRODUCT_PROPERTY_OVERRIDES := ro.apex.updatable=true
-PRODUCT_PACKAGES := com.android.apex.cts.shim.v1_prebuilt
-TARGET_FLATTEN_APEX := false
+ifneq ($(OVERRIDE_TARGET_FLATTEN_APEX),true)
+  PRODUCT_PACKAGES := com.android.apex.cts.shim.v1_prebuilt
+  PRODUCT_PROPERTY_OVERRIDES := ro.apex.updatable=true
+  TARGET_FLATTEN_APEX := false
+endif
diff --git a/tools/extract_kernel.py b/tools/extract_kernel.py
index 16ccb22..42561cf 100755
--- a/tools/extract_kernel.py
+++ b/tools/extract_kernel.py
@@ -47,7 +47,10 @@
   null_idx = input_bytes.find('\x00', start_idx)
   if null_idx < 0:
     return None
-  linux_banner = input_bytes[start_idx:null_idx].decode()
+  try:
+    linux_banner = input_bytes[start_idx:null_idx].decode()
+  except UnicodeDecodeError:
+    return None
   mo = re.match(LINUX_BANNER_REGEX, linux_banner)
   if mo:
     return mo.group(1)
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
index 96db0f3..af0da46 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -99,7 +99,7 @@
 	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
 	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
 	   --partition system \
-	   --all-partitions $(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST)) \
+	   --all-partitions "$(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST))" \
 	   --dirs \
 	   --out_file $@ \
 	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
@@ -124,7 +124,7 @@
 	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
 	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
 	   --partition system \
-	   --all-partitions $(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST)) \
+	   --all-partitions "$(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST))" \
 	   --files \
 	   --out_file $@ \
 	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py
index dccff92..109b29a 100755
--- a/tools/fs_config/fs_config_generator.py
+++ b/tools/fs_config/fs_config_generator.py
@@ -1004,10 +1004,6 @@
 
         self._partition = args['partition']
         self._all_partitions = args['all_partitions']
-        if self._partition == 'system' and self._all_partitions is None:
-            sys.exit(
-                'All other partitions must be provided if generating output'
-                ' for the system partition')
 
         self._out_file = args['out_file']
 
@@ -1137,6 +1133,8 @@
         path = fs_config.path
 
         if self._partition == 'system':
+            if not self._all_partitions:
+                return True
             for skip_partition in self._all_partitions.split(','):
                 if path.startswith(skip_partition) or path.startswith(
                         'system/' + skip_partition):
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 1090d57..f2b9afa 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -870,10 +870,11 @@
     banner("vbmeta")
     AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
 
-  if OPTIONS.info_dict.get("build_super_partition") == "true":
+  if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
     banner("super_empty")
     AddSuperEmpty(output_zip)
 
+  if OPTIONS.info_dict.get("build_super_partition") == "true":
     if OPTIONS.info_dict.get(
         "build_retrofit_dynamic_partitions_ota_package") == "true":
       banner("super split images")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index d743c3e..9a27ad3 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -97,6 +97,9 @@
 AVB_PARTITIONS = ('boot', 'recovery', 'system', 'vendor', 'product',
                   'product_services', 'dtbo', 'odm')
 
+# Chained VBMeta partitions.
+AVB_VBMETA_PARTITIONS = ('vbmeta_system', 'vbmeta_vendor')
+
 # Partitions that should have their care_map added to META/care_map.pb
 PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product', 'product_services',
                             'odm')
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 3b72551..712e3f7 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -395,6 +395,10 @@
       merged_info_dict[key] = '%s %s' % (
         system_info_dict.get(key, ''),
         merged_info_dict.get(key, ''))
+    # Ensure that add_img_to_target_files rebuilds super split images for
+    # devices that retrofit dynamic partitions. This flag may have been set to
+    # false in the partial builds to prevent duplicate building of super.img.
+    merged_dict['build_super_partition'] = 'true'
 
   output_misc_info_txt = os.path.join(
       output_target_files_temp_dir,
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 8b55f03..27854fd 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -243,6 +243,12 @@
 UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'RADIO/*']
 RETROFIT_DAP_UNZIP_PATTERN = ['OTA/super_*.img', AB_PARTITIONS]
 
+# Images to be excluded from secondary payload. We essentially only keep
+# 'system_other' and bootloader partitions.
+SECONDARY_PAYLOAD_SKIPPED_IMAGES = [
+    'boot', 'dtbo', 'modem', 'odm', 'product', 'radio', 'recovery',
+    'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor']
+
 
 class BuildInfo(object):
   """A class that holds the information for a given build.
@@ -1859,6 +1865,43 @@
   Returns:
     The filename of the target-files.zip for generating secondary payload.
   """
+
+  def GetInfoForSecondaryImages(info_file):
+    """Updates info file for secondary payload generation.
+
+    Scan each line in the info file, and remove the unwanted partitions from
+    the dynamic partition list in the related properties. e.g.
+    "super_google_dynamic_partitions_partition_list=system vendor product"
+    will become "super_google_dynamic_partitions_partition_list=system".
+
+    Args:
+      info_file: The input info file. e.g. misc_info.txt.
+
+    Returns:
+      A string of the updated info content.
+    """
+
+    output_list = []
+    with open(info_file) as f:
+      lines = f.read().splitlines()
+
+    # The suffix in partition_list variables that follows the name of the
+    # partition group.
+    LIST_SUFFIX = 'partition_list'
+    for line in lines:
+      if line.startswith('#') or '=' not in line:
+        output_list.append(line)
+        continue
+      key, value = line.strip().split('=', 1)
+      if key == 'dynamic_partition_list' or key.endswith(LIST_SUFFIX):
+        partitions = value.split()
+        partitions = [partition for partition in partitions if partition
+                      not in SECONDARY_PAYLOAD_SKIPPED_IMAGES]
+        output_list.append('{}={}'.format(key, ' '.join(partitions)))
+      else:
+        output_list.append(line)
+    return '\n'.join(output_list)
+
   target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
   target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
 
@@ -1877,12 +1920,33 @@
                            'IMAGES/system.map'):
       pass
 
+    # Copy images that are not in SECONDARY_PAYLOAD_SKIPPED_IMAGES.
+    elif info.filename.startswith(('IMAGES/', 'RADIO/')):
+      image_name = os.path.basename(info.filename)
+      if image_name not in ['{}.img'.format(partition) for partition in
+                            SECONDARY_PAYLOAD_SKIPPED_IMAGES]:
+        common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+
     # Skip copying the postinstall config if requested.
     elif skip_postinstall and info.filename == POSTINSTALL_CONFIG:
       pass
 
-    elif info.filename.startswith(('META/', 'IMAGES/', 'RADIO/')):
-      common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+    elif info.filename.startswith('META/'):
+      # Remove the unnecessary partitions for secondary images from the
+      # ab_partitions file.
+      if info.filename == AB_PARTITIONS:
+        with open(unzipped_file) as f:
+          partition_list = f.read().splitlines()
+        partition_list = [partition for partition in partition_list if partition
+                          and partition not in SECONDARY_PAYLOAD_SKIPPED_IMAGES]
+        common.ZipWriteStr(target_zip, info.filename, '\n'.join(partition_list))
+      # Remove the unnecessary partitions from the dynamic partitions list.
+      elif (info.filename == 'META/misc_info.txt' or
+            info.filename == DYNAMIC_PARTITION_INFO):
+        modified_info = GetInfoForSecondaryImages(unzipped_file)
+        common.ZipWriteStr(target_zip, info.filename, modified_info)
+      else:
+        common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
 
   common.ZipClose(target_zip)
 
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index e8c4163..1b3d6f1 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -972,6 +972,10 @@
     codename = codename.strip()
     if codename:
       result[codename] = api_level
+
+  # Work around APKs that still target 'Q' instead of API 29 (b/132882632).
+  result['Q'] = 29
+
   return result
 
 
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index 466fde1..07dcffb 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -588,18 +588,22 @@
 
     with zipfile.ZipFile(target_file) as verify_zip:
       namelist = verify_zip.namelist()
+      ab_partitions = verify_zip.read('META/ab_partitions.txt')
 
     self.assertIn('META/ab_partitions.txt', namelist)
-    self.assertIn('IMAGES/boot.img', namelist)
     self.assertIn('IMAGES/system.img', namelist)
-    self.assertIn('IMAGES/vendor.img', namelist)
     self.assertIn('RADIO/bootloader.img', namelist)
-    self.assertIn('RADIO/modem.img', namelist)
     self.assertIn(POSTINSTALL_CONFIG, namelist)
 
+    self.assertNotIn('IMAGES/boot.img', namelist)
     self.assertNotIn('IMAGES/system_other.img', namelist)
     self.assertNotIn('IMAGES/system.map', namelist)
+    self.assertNotIn('RADIO/modem.img', namelist)
 
+    expected_ab_partitions = ['system', 'bootloader']
+    self.assertEqual('\n'.join(expected_ab_partitions), ab_partitions)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_GetTargetFilesZipForSecondaryImages_skipPostinstall(self):
     input_file = construct_target_files(secondary=True)
     target_file = GetTargetFilesZipForSecondaryImages(
@@ -609,16 +613,16 @@
       namelist = verify_zip.namelist()
 
     self.assertIn('META/ab_partitions.txt', namelist)
-    self.assertIn('IMAGES/boot.img', namelist)
     self.assertIn('IMAGES/system.img', namelist)
-    self.assertIn('IMAGES/vendor.img', namelist)
     self.assertIn('RADIO/bootloader.img', namelist)
-    self.assertIn('RADIO/modem.img', namelist)
 
+    self.assertNotIn('IMAGES/boot.img', namelist)
     self.assertNotIn('IMAGES/system_other.img', namelist)
     self.assertNotIn('IMAGES/system.map', namelist)
+    self.assertNotIn('RADIO/modem.img', namelist)
     self.assertNotIn(POSTINSTALL_CONFIG, namelist)
 
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_GetTargetFilesZipForSecondaryImages_withoutRadioImages(self):
     input_file = construct_target_files(secondary=True)
     common.ZipDelete(input_file, 'RADIO/bootloader.img')
@@ -629,16 +633,65 @@
       namelist = verify_zip.namelist()
 
     self.assertIn('META/ab_partitions.txt', namelist)
-    self.assertIn('IMAGES/boot.img', namelist)
     self.assertIn('IMAGES/system.img', namelist)
-    self.assertIn('IMAGES/vendor.img', namelist)
     self.assertIn(POSTINSTALL_CONFIG, namelist)
 
+    self.assertNotIn('IMAGES/boot.img', namelist)
     self.assertNotIn('IMAGES/system_other.img', namelist)
     self.assertNotIn('IMAGES/system.map', namelist)
     self.assertNotIn('RADIO/bootloader.img', namelist)
     self.assertNotIn('RADIO/modem.img', namelist)
 
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_GetTargetFilesZipForSecondaryImages_dynamicPartitions(self):
+    input_file = construct_target_files(secondary=True)
+    misc_info = '\n'.join([
+        'use_dynamic_partition_size=true',
+        'use_dynamic_partitions=true',
+        'dynamic_partition_list=system vendor product',
+        'super_partition_groups=google_dynamic_partitions',
+        'super_google_dynamic_partitions_group_size=4873781248',
+        'super_google_dynamic_partitions_partition_list=system vendor product',
+    ])
+    dynamic_partitions_info = '\n'.join([
+        'super_partition_groups=google_dynamic_partitions',
+        'super_google_dynamic_partitions_group_size=4873781248',
+        'super_google_dynamic_partitions_partition_list=system vendor product',
+    ])
+
+    with zipfile.ZipFile(input_file, 'a') as append_zip:
+      common.ZipWriteStr(append_zip, 'META/misc_info.txt', misc_info)
+      common.ZipWriteStr(append_zip, 'META/dynamic_partitions_info.txt',
+                         dynamic_partitions_info)
+
+    target_file = GetTargetFilesZipForSecondaryImages(input_file)
+
+    with zipfile.ZipFile(target_file) as verify_zip:
+      namelist = verify_zip.namelist()
+      updated_misc_info = verify_zip.read('META/misc_info.txt')
+      updated_dynamic_partitions_info = verify_zip.read(
+          'META/dynamic_partitions_info.txt')
+
+    self.assertIn('META/ab_partitions.txt', namelist)
+    self.assertIn('IMAGES/system.img', namelist)
+    self.assertIn(POSTINSTALL_CONFIG, namelist)
+    self.assertIn('META/misc_info.txt', namelist)
+    self.assertIn('META/dynamic_partitions_info.txt', namelist)
+
+    self.assertNotIn('IMAGES/boot.img', namelist)
+    self.assertNotIn('IMAGES/system_other.img', namelist)
+    self.assertNotIn('IMAGES/system.map', namelist)
+
+    # Check the vendor & product are removed from the partitions list.
+    expected_misc_info = misc_info.replace('system vendor product',
+                                           'system')
+    expected_dynamic_partitions_info = dynamic_partitions_info.replace(
+        'system vendor product', 'system')
+    self.assertEqual(expected_misc_info, updated_misc_info)
+    self.assertEqual(expected_dynamic_partitions_info,
+                     updated_dynamic_partitions_info)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_GetTargetFilesZipWithoutPostinstallConfig(self):
     input_file = construct_target_files()
     target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index 1c856a8..37d5d27 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -327,11 +327,14 @@
     cmd = ['avbtool', 'verify_image', '--image', image, '--key', key]
 
     # Append the args for chained partitions if any.
-    for partition in common.AVB_PARTITIONS:
+    for partition in common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS:
       key_name = 'avb_' + partition + '_key_path'
       if info_dict.get(key_name) is not None:
+        # Use the key file from command line if specified; otherwise fall back
+        # to the one in info dict.
+        key_file = options.get(key_name, info_dict[key_name])
         chained_partition_arg = common.GetAvbChainedPartitionArg(
-            partition, info_dict, options[key_name])
+            partition, info_dict, key_file)
         cmd.extend(["--expected_chain_partition", chained_partition_arg])
 
     proc = common.Run(cmd)
@@ -357,7 +360,7 @@
       help='the verity public key to verify the bootable images (Verified '
            'Boot 1.0), or the vbmeta image (Verified Boot 2.0, aka AVB), where '
            'applicable')
-  for partition in common.AVB_PARTITIONS:
+  for partition in common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS:
     parser.add_argument(
         '--avb_' + partition + '_key_path',
         help='the public or private key in PEM format to verify AVB chained '