Merge "Remove TARGET_TRANSLATE_2ND_ARCH"
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 6270387..b40616d 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -700,6 +700,18 @@
   endif
 endif
 
+
+ifeq ($(use_testcase_folder),true)
+ifneq ($(my_test_data_file_pairs),)
+$(foreach pair, $(my_test_data_file_pairs), \
+  $(eval parts := $(subst :,$(space),$(pair))) \
+  $(eval src_path := $(word 1,$(parts))) \
+  $(eval file := $(word 2,$(parts))) \
+  $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+    $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
+      $(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data))))))
+endif
+else
 ifneq ($(my_test_data_file_pairs),)
 $(foreach pair, $(my_test_data_file_pairs), \
   $(eval parts := $(subst :,$(space),$(pair))) \
@@ -709,6 +721,7 @@
     $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
       $(src_path):$(call append-path,$(dir),$(file))))))
 endif
+endif
 
 
 
diff --git a/core/definitions.mk b/core/definitions.mk
index 381a2a7..a442bc0 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2419,6 +2419,16 @@
 $(if $(filter-out $(2), $(LOCAL_INSTALLED_MODULE)), $(1):$(2))
 endef
 
+# Create copy pair for $(1) $(2)
+# If $(2) is substring of $(3) do nothing.
+# $(1): source path
+# $(2): destination path
+# $(3): filter-out target
+# The format of copy pair is src:dst
+define filter-copy-pair
+$(if $(findstring $(2), $(3)),,$(1):$(2))
+endef
+
 # Copies many files.
 # $(1): The files to copy.  Each entry is a ':' separated src:dst pair
 # $(2): An optional directory to prepend to the destination
diff --git a/core/main.mk b/core/main.mk
index b682a58..1b2b3e6 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -44,11 +44,7 @@
 .KATI_READONLY := BUILD_NUMBER_FILE
 $(KATI_obsolete_var BUILD_NUMBER,See https://android.googlesource.com/platform/build/+/master/Changes.md#BUILD_NUMBER)
 
-ifeq ($(HOST_OS),darwin)
-DATE_FROM_FILE := date -r $(BUILD_DATETIME_FROM_FILE)
-else
 DATE_FROM_FILE := date -d @$(BUILD_DATETIME_FROM_FILE)
-endif
 .KATI_READONLY := DATE_FROM_FILE
 
 # Pick a reasonable string to use to identify files.
@@ -1488,7 +1484,7 @@
 # -------------------------------------------------------------------
 
 .PHONY: checkbuild
-checkbuild: $(modules_to_check) droid_targets
+checkbuild: $(modules_to_check) droid_targets check-elf-files
 
 ifeq (true,$(ANDROID_BUILD_EVERYTHING_BY_DEFAULT))
 droid: checkbuild
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 00c5ed0..30890c0 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -256,11 +256,7 @@
 
 ifndef PLATFORM_SECURITY_PATCH_TIMESTAMP
   # Used to indicate the matching timestamp for the security patch string in PLATFORM_SECURITY_PATCH.
-  ifneq (,$(findstring Darwin,$(UNAME)))
-    PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -jf '%Y-%m-%d %T %Z' '$(PLATFORM_SECURITY_PATCH) 00:00:00 GMT' +%s)
-  else
-    PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -d 'TZ="GMT" $(PLATFORM_SECURITY_PATCH)' +%s)
-  endif
+  PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -d 'TZ="GMT" $(PLATFORM_SECURITY_PATCH)' +%s)
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH_TIMESTAMP
 
@@ -289,11 +285,7 @@
   BUILD_DATETIME := $(shell date +%s)
 endif
 
-ifneq (,$(findstring Darwin,$(UNAME)))
-DATE := date -r $(BUILD_DATETIME)
-else
 DATE := date -d @$(BUILD_DATETIME)
-endif
 .KATI_READONLY := DATE
 
 # Everything should be using BUILD_DATETIME_FROM_FILE instead.
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index f941918..d11f9d2 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -7,6 +7,9 @@
 BOARD_USES_GENERIC_AUDIO := true
 TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
 
+# No Kernel
+TARGET_NO_KERNEL := true
+
 # no hardware camera
 USE_CAMERA_STUB := true
 
@@ -48,6 +51,8 @@
     TARGET_COPY_OUT_SYSTEM_EXT := system_ext
     BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4
   else
+    TARGET_COPY_OUT_PRODUCT := system/product
+    TARGET_COPY_OUT_SYSTEM_EXT := system/system_ext
     BOARD_EMULATOR_DYNAMIC_PARTITIONS_PARTITION_LIST := \
         system \
         vendor
@@ -69,6 +74,12 @@
   BOARD_VENDORIMAGE_PARTITION_SIZE := 146800640
 endif
 
+# Enable chain partition for system.
+BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
+BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
+BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
+BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
+
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
 BOARD_FLASH_BLOCK_SIZE := 512
 DEVICE_MATRIX_FILE   := device/generic/goldfish/compatibility_matrix.xml
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 4c783c0..61aa67c 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -33,12 +33,6 @@
 #   updating the last seen rollback index in the tamper-evident storage.
 BOARD_AVB_ROLLBACK_INDEX := 0
 
-# Enable chain partition for system.
-BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
-BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
-BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
-BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
-
 # GSI specific System Properties
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 TARGET_SYSTEM_EXT_PROP := build/make/target/board/gsi_system_ext.prop
diff --git a/target/board/generic_x86_arm/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
index e879001..3fbf79b 100644
--- a/target/board/generic_x86_arm/BoardConfig.mk
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -25,10 +25,18 @@
 
 BUILD_BROKEN_DUP_RULES := true
 
-
-include build/make/target/board/BoardConfigGsiCommon.mk
+#
+# The inclusion order below is important.
+# The settings in latter makefiles overwrite those in the former.
+#
+include build/make/target/board/BoardConfigMainlineCommon.mk
 include build/make/target/board/BoardConfigEmuCommon.mk
 
+# the settings differ from BoardConfigMainlineCommon.mk
+BOARD_USES_SYSTEM_OTHER_ODEX :=
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
 # Resize to 4G to accomodate ASAN and CTS
 BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
 
diff --git a/target/board/generic_x86_arm/device.mk b/target/board/generic_x86_arm/device.mk
index 0a32415..fa1eb67 100644
--- a/target/board/generic_x86_arm/device.mk
+++ b/target/board/generic_x86_arm/device.mk
@@ -13,12 +13,3 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-# NFC:
-#   Provide default libnfc-nci.conf file for devices that does not have one in
-#   vendor/etc because aosp system image (of aosp_$arch products) is going to
-#   be used as GSI.
-#   May need to remove the following for newly launched devices in P since this
-#   NFC configuration file should be in vendor/etc, instead of system/etc
-PRODUCT_COPY_FILES += \
-    device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf
diff --git a/target/product/aosp_x86_arm.mk b/target/product/aosp_x86_arm.mk
index 70aa64e..c0f8f8a 100644
--- a/target/product/aosp_x86_arm.mk
+++ b/target/product/aosp_x86_arm.mk
@@ -16,27 +16,35 @@
 
 PRODUCT_USE_DYNAMIC_PARTITIONS := true
 
-# aosp_x86 with arm libraries needed by binary translation.
+#
+# All components inherited here go to system image
+#
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
 
-# The system image of aosp_x86-userdebug is a GSI for the devices with:
-# - x86 32 bits user space
-# - 64 bits binder interface
-# - system-as-root
-# - VNDK enforcement
-# - compatible property override enabled
+# Enable mainline checking
+ifeq (aosp_x86_arm,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
--include device/generic/goldfish/x86-vendor.mk
+# TODO (b/138382074): remove following setting after enable product/system_ext
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    system/product/% \
+    system/system_ext/%
 
-include $(SRC_TARGET_DIR)/product/full_x86.mk
+#
+# All components inherited here go to product image
+#
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
 
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
+#
+# All components inherited here go to vendor image
+#
+$(call inherit-product-if-exists, device/generic/goldfish/x86-vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_arm/device.mk)
 
-# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
-
-# Support addtional P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
 
 PRODUCT_NAME := aosp_x86_arm
 PRODUCT_DEVICE := generic_x86_arm
+PRODUCT_BRAND := Android
+PRODUCT_MODEL := AOSP on IA Emulator
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 44fc7e4..dab8487 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -362,6 +362,7 @@
     adb_keys \
     arping \
     gdbserver \
+    idlcli \
     init-debug.rc \
     iotop \
     iperf3 \
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index 7b9c783..d4655f1 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -39,6 +39,7 @@
 
 # Do not spin up a separate process for the network stack on go devices, use an in-process APK.
 PRODUCT_PACKAGES += InProcessNetworkStack
+PRODUCT_PACKAGES += CellBroadcastAppPlatform
 
 # Strip the local variable table and the local variable type table to reduce
 # the size of the system image. This has no bearing on stack traces, but will
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/security/Android.mk b/target/product/security/Android.mk
index a0b2d6d..3631cfd 100644
--- a/target/product/security/Android.mk
+++ b/target/product/security/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 
 #######################################
-# verity_key
+# verity_key (installed to /, i.e. part of system.img)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := verity_key
@@ -9,9 +9,29 @@
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
 
+# For devices using a separate ramdisk, we need a copy there to establish the chain of trust.
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+LOCAL_REQUIRED_MODULES := verity_key_ramdisk
+endif
+
 include $(BUILD_PREBUILT)
 
 #######################################
+# verity_key (installed to ramdisk)
+#
+# Enabling the target when using system-as-root would cause build failure, as TARGET_RAMDISK_OUT
+# points to the same location as TARGET_ROOT_OUT.
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+  include $(CLEAR_VARS)
+  LOCAL_MODULE := verity_key_ramdisk
+  LOCAL_MODULE_CLASS := ETC
+  LOCAL_SRC_FILES := verity_key
+  LOCAL_MODULE_STEM := verity_key
+  LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)
+  include $(BUILD_PREBUILT)
+endif
+
+#######################################
 # adb key, if configured via PRODUCT_ADB_KEYS
 ifdef PRODUCT_ADB_KEYS
   ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
diff --git a/target/product/telephony_system.mk b/target/product/telephony_system.mk
index 584cf1e..4da9bdf 100644
--- a/target/product/telephony_system.mk
+++ b/target/product/telephony_system.mk
@@ -21,6 +21,6 @@
     ONS \
     CarrierDefaultApp \
     CallLogBackup \
-    CellBroadcastReceiver \
+    CellBroadcastAppPlatform \
 
 PRODUCT_COPY_FILES := \
diff --git a/tools/extract_kernel.py b/tools/extract_kernel.py
index 42561cf..8ca11d1 100755
--- a/tools/extract_kernel.py
+++ b/tools/extract_kernel.py
@@ -100,19 +100,25 @@
   return o
 
 
-def try_decompress(cmd, search_bytes, input_bytes):
-  idx = input_bytes.find(search_bytes)
-  if idx < 0:
-    return None
-
-  idx = 0
+def try_decompress_bytes(cmd, input_bytes):
   sp = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
-  o, _ = sp.communicate(input=input_bytes[idx:])
+  o, _ = sp.communicate(input=input_bytes)
   # ignore errors
   return o
 
 
+def try_decompress(cmd, search_bytes, input_bytes):
+  idx = 0
+  while True:
+    idx = input_bytes.find(search_bytes, idx)
+    if idx < 0:
+      raise StopIteration()
+
+    yield try_decompress_bytes(cmd, input_bytes[idx:])
+    idx += 1
+
+
 def decompress_dump(func, input_bytes):
   """
   Run func(input_bytes) first; and if that fails (returns value evaluates to
@@ -122,15 +128,15 @@
   if o:
     return o
   for cmd, search_bytes in COMPRESSION_ALGO:
-    decompressed = try_decompress(cmd, search_bytes, input_bytes)
-    if decompressed:
-      o = func(decompressed)
-      if o:
-        return o
+    for decompressed in try_decompress(cmd, search_bytes, input_bytes):
+      if decompressed:
+        o = decompress_dump(func, decompressed)
+        if o:
+          return o
     # Force decompress the whole file even if header doesn't match
-    decompressed = try_decompress(cmd, b"", input_bytes)
+    decompressed = try_decompress_bytes(cmd, input_bytes)
     if decompressed:
-      o = func(decompressed)
+      o = decompress_dump(func, decompressed)
       if o:
         return o
 
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 67cec1c..de947f3 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -251,6 +251,12 @@
                                 'PRODUCT/*', 'SYSTEM_EXT/*', 'ODM/*']
 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.
@@ -298,6 +304,9 @@
           that it always uses the first dict to calculate the fingerprint or the
           device name. The rest would be used for asserting OEM properties only
           (e.g. one package can be installed on one of these devices).
+
+    Raises:
+      ValueError: On invalid inputs.
     """
     self.info_dict = info_dict
     self.oem_dicts = oem_dicts
@@ -312,6 +321,13 @@
     self._device = self.GetOemProperty("ro.product.device")
     self._fingerprint = self.CalculateFingerprint()
 
+    # Sanity check the build fingerprint.
+    if (' ' in self._fingerprint or
+        any(ord(ch) > 127 for ch in self._fingerprint)):
+      raise ValueError(
+          'Invalid build fingerprint: "{}". See the requirement in Android CDD '
+          '3.2.2. Build Parameters.'.format(self._fingerprint))
+
   @property
   def is_ab(self):
     return self._is_ab
@@ -1792,6 +1808,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)
 
@@ -1809,12 +1862,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 3119afa..1f41431 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -602,11 +602,16 @@
     ReplaceVerityPrivateKey(misc_info, OPTIONS.replace_verity_private_key[1])
 
   if OPTIONS.replace_verity_public_key:
-    dest = "ROOT/verity_key" if system_root_image else "BOOT/RAMDISK/verity_key"
-    # We are replacing the one in boot image only, since the one under
-    # recovery won't ever be needed.
+    # Replace the one in root dir in system.img.
     ReplaceVerityPublicKey(
-        output_tf_zip, dest, OPTIONS.replace_verity_public_key[1])
+        output_tf_zip, 'ROOT/verity_key', OPTIONS.replace_verity_public_key[1])
+
+    if not system_root_image:
+      # Additionally replace the copy in ramdisk if not using system-as-root.
+      ReplaceVerityPublicKey(
+          output_tf_zip,
+          'BOOT/RAMDISK/verity_key',
+          OPTIONS.replace_verity_public_key[1])
 
   # Replace the keyid string in BOOT/cmdline.
   if OPTIONS.replace_verity_keyid:
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index ee831e3..9825a5e 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -174,6 +174,14 @@
     self.assertRaises(AssertionError, BuildInfo,
                       self.TEST_INFO_DICT_USES_OEM_PROPS, None)
 
+  def test_init_badFingerprint(self):
+    info_dict = copy.deepcopy(self.TEST_INFO_DICT)
+    info_dict['build.prop']['ro.build.fingerprint'] = 'bad fingerprint'
+    self.assertRaises(ValueError, BuildInfo, info_dict, None)
+
+    info_dict['build.prop']['ro.build.fingerprint'] = 'bad\x80fingerprint'
+    self.assertRaises(ValueError, BuildInfo, info_dict, None)
+
   def test___getitem__(self):
     target_info = BuildInfo(self.TEST_INFO_DICT, None)
     self.assertEqual('value1', target_info['property1'])
@@ -588,17 +596,20 @@
 
     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):
@@ -610,14 +621,13 @@
       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()
@@ -631,17 +641,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/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index 0f0d773..9c816eb 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -143,21 +143,52 @@
     verity_image_builder.Build(output_file)
 
   @test_utils.SkipIfExternalToolsUnavailable()
-  def test_ValidateVerifiedBootImages_systemImage(self):
+  def test_ValidateVerifiedBootImages_systemRootImage(self):
     input_tmp = common.MakeTempDir()
     os.mkdir(os.path.join(input_tmp, 'IMAGES'))
     system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
     self._generate_system_image(system_image)
 
     # Pack the verity key.
-    verity_key_mincrypt = os.path.join(
-        input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
     os.makedirs(os.path.dirname(verity_key_mincrypt))
     shutil.copyfile(
         os.path.join(self.testdata_dir, 'testkey_mincrypt'),
         verity_key_mincrypt)
 
     info_dict = {
+        'system_root_image' : 'true',
+        'verity' : 'true',
+    }
+    options = {
+        'verity_key' : os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+        'verity_key_mincrypt' : verity_key_mincrypt,
+    }
+    ValidateVerifiedBootImages(input_tmp, info_dict, options)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_ValidateVerifiedBootImages_nonSystemRootImage(self):
+    input_tmp = common.MakeTempDir()
+    os.mkdir(os.path.join(input_tmp, 'IMAGES'))
+    system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
+    self._generate_system_image(system_image)
+
+    # Pack the verity key into the root dir in system.img.
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_mincrypt))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'testkey_mincrypt'),
+        verity_key_mincrypt)
+
+    # And a copy in ramdisk.
+    verity_key_ramdisk = os.path.join(
+        input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_ramdisk))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'testkey_mincrypt'),
+        verity_key_ramdisk)
+
+    info_dict = {
         'verity' : 'true',
     }
     options = {
@@ -167,6 +198,39 @@
     ValidateVerifiedBootImages(input_tmp, info_dict, options)
 
   @test_utils.SkipIfExternalToolsUnavailable()
+  def test_ValidateVerifiedBootImages_nonSystemRootImage_mismatchingKeys(self):
+    input_tmp = common.MakeTempDir()
+    os.mkdir(os.path.join(input_tmp, 'IMAGES'))
+    system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
+    self._generate_system_image(system_image)
+
+    # Pack the verity key into the root dir in system.img.
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_mincrypt))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'testkey_mincrypt'),
+        verity_key_mincrypt)
+
+    # And an invalid copy in ramdisk.
+    verity_key_ramdisk = os.path.join(
+        input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_ramdisk))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'verity_mincrypt'),
+        verity_key_ramdisk)
+
+    info_dict = {
+        'verity' : 'true',
+    }
+    options = {
+        'verity_key' : os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+        'verity_key_mincrypt' : verity_key_mincrypt,
+    }
+    self.assertRaises(
+        AssertionError, ValidateVerifiedBootImages, input_tmp, info_dict,
+        options)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_ValidateFileConsistency_incompleteRange(self):
     input_tmp = common.MakeTempDir()
     os.mkdir(os.path.join(input_tmp, 'IMAGES'))
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index d189499..c299a48 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -276,15 +276,12 @@
   # Verify verity signed system images in Verified Boot 1.0. Note that not using
   # 'elif' here, since 'boot_signer' and 'verity' are not bundled in VB 1.0.
   if info_dict.get('verity') == 'true':
-    # First verify that the verity key that's built into the root image (as
-    # /verity_key) matches the one given via command line, if any.
-    if info_dict.get("system_root_image") == "true":
-      verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
-    else:
-      verity_key_mincrypt = os.path.join(
-          input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    # First verify that the verity key is built into the root image (regardless
+    # of system-as-root).
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
     assert os.path.exists(verity_key_mincrypt), 'Missing verity_key'
 
+    # Verify /verity_key matches the one given via command line, if any.
     if options['verity_key_mincrypt'] is None:
       logging.warn(
           'Skipped checking the content of /verity_key, as the key file not '
@@ -295,6 +292,18 @@
           "Mismatching mincrypt verity key files"
       logging.info('Verified the content of /verity_key')
 
+    # For devices with a separate ramdisk (i.e. non-system-as-root), there must
+    # be a copy in ramdisk.
+    if info_dict.get("system_root_image") != "true":
+      verity_key_ramdisk = os.path.join(
+          input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+      assert os.path.exists(verity_key_ramdisk), 'Missing verity_key in ramdisk'
+
+      assert filecmp.cmp(
+          verity_key_mincrypt, verity_key_ramdisk, shallow=False), \
+              'Mismatching verity_key files in root and ramdisk'
+      logging.info('Verified the content of /verity_key in ramdisk')
+
     # Then verify the verity signed system/vendor/product images, against the
     # verity pubkey in mincrypt format.
     for image in ('system.img', 'vendor.img', 'product.img'):