Merge "Check for duplicate entries in build.prop in validation script"
diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index 6504515..ca70ca8 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -25,10 +25,9 @@
 import test_utils
 from rangelib import RangeSet
 from validate_target_files import (ValidateVerifiedBootImages,
-                                   ValidateFileConsistency)
+                                   ValidateFileConsistency, CheckBuildPropDuplicity)
 from verity_utils import CreateVerityImageBuilder
 
-
 class ValidateTargetFilesTest(test_utils.ReleaseToolsTestCase):
 
   def setUp(self):
@@ -329,3 +328,38 @@
     with zipfile.ZipFile(input_file) as input_zip:
       info_dict = {'extfs_sparse_flag': '-s'}
       ValidateFileConsistency(input_zip, input_tmp, info_dict)
+
+  @staticmethod
+  def make_build_prop(build_prop):
+    input_tmp = common.MakeTempDir()
+    system_dir = os.path.join(input_tmp, 'SYSTEM')
+    os.makedirs(system_dir)
+    prop_file = os.path.join(system_dir, 'build.prop')
+    with open(prop_file, 'w') as output_file:
+      output_file.write("\n".join(build_prop))
+    return input_tmp
+
+  def test_checkDuplicateProps_noDuplicate(self):
+    build_prop = [
+        'ro.odm.build.date.utc=1578430045',
+        'ro.odm.build.fingerprint='
+        'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+        'ro.product.odm.device=coral',
+    ]
+    input_tmp = ValidateTargetFilesTest.make_build_prop(build_prop)
+    CheckBuildPropDuplicity(input_tmp)
+
+  def test_checkDuplicateProps_withDuplicate(self):
+    build_prop = [
+        'ro.odm.build.date.utc=1578430045',
+        'ro.odm.build.date.utc=1578430049',
+        'ro.odm.build.fingerprint='
+        'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+        'ro.product.odm.device=coral',
+    ]
+    input_tmp = ValidateTargetFilesTest.make_build_prop({
+        'ODM/etc/build.prop': '\n'.join(build_prop),
+    })
+
+    self.assertRaises(ValueError, CheckBuildPropDuplicity,
+                        input_tmp)
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index ac469eb..8763825 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -408,6 +408,34 @@
           'Verified %s with avbtool (key: %s):\n%s', image, key,
           stdoutdata.rstrip())
 
+def CheckDataDuplicity(lines):
+    build_prop = {}
+    for line in lines:
+      if line.startswith("import") or line.startswith("#"):
+        continue
+      key, value = line.split("=", 1)
+      if key in build_prop:
+        return key
+      build_prop[key] = value
+
+def CheckBuildPropDuplicity(input_tmp):
+  """Check all buld.prop files inside directory input_tmp, raise error
+  if they contain duplicates"""
+
+  if not os.path.isdir(input_tmp):
+    raise ValueError("Expect {} to be a directory".format(input_tmp))
+  for name in os.listdir(input_tmp):
+    if not name.isupper():
+      continue
+    for prop_file in ['build.prop', 'etc/build.prop']:
+      path = os.path.join(input_tmp, name, prop_file)
+      if not os.path.exists(path):
+        continue
+      logging.info("Checking {}".format(path))
+      with open(path, 'r') as fp:
+        dupKey = CheckDataDuplicity(fp.readlines())
+        if dupKey:
+          raise ValueError("{} contains duplicate keys for {}", path, dupKey)
 
 def main():
   parser = argparse.ArgumentParser(
@@ -447,6 +475,8 @@
   with zipfile.ZipFile(args.target_files, 'r') as input_zip:
     ValidateFileConsistency(input_zip, input_tmp, info_dict)
 
+  CheckBuildPropDuplicity(input_tmp)
+
   ValidateInstallRecoveryScript(input_tmp, info_dict)
 
   ValidateVerifiedBootImages(input_tmp, info_dict, options)