Make change and version bump to RP1A.190918.001

Change-Id: I48eefe816d44a999d6c37d021a11bae7e1468d6e
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 7147f6d..3c973bb 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -716,6 +716,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))) \
@@ -725,6 +737,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/build_id.mk b/core/build_id.mk
index 8fd0712..729cb6b 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -18,4 +18,4 @@
 # (like "CRB01").  It must be a single word, and is
 # capitalized by convention.
 
-BUILD_ID=RP1A.190917.001
+BUILD_ID=RP1A.190918.001
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 b91770b..ba04ece 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1494,7 +1494,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/target/product/base_vendor.mk b/target/product/base_vendor.mk
index f3705ea..1e1effb 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -75,7 +75,3 @@
 # VINTF data for vendor image
 PRODUCT_PACKAGES += \
     device_compatibility_matrix.xml \
-
-PRODUCT_PACKAGES += \
-    libprotobuf-cpp-lite-vendorcompat \
-    libprotobuf-cpp-full-vendorcompat \
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/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 dc75ce2..82ea539 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -299,6 +299,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
@@ -313,6 +316,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
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 0846d87..9b2fbb6 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'])
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'):