Make apex util detect if hashtree is present

Test: sign_target_fiels_apks oriole_target_files.zip
Bug: 195194430

Change-Id: I919d169ce4d66e6a1cdbfd15babde25005971a30
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index bd86acf..51ec434 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -340,6 +340,8 @@
     zip_items = apex_fd.namelist()
 
   payload_info = ParseApexPayloadInfo(avbtool, payload_file)
+  if no_hashtree is None:
+    no_hashtree = payload_info.get("Tree Size", 0) == 0
   SignApexPayload(
       avbtool,
       payload_file,
@@ -381,8 +383,8 @@
 
 
 def SignCompressedApex(avbtool, apex_file, payload_key, container_key,
-                         container_pw, apk_keys, codename_to_api_level_map,
-                         no_hashtree, signing_args=None):
+                       container_pw, apk_keys, codename_to_api_level_map,
+                       no_hashtree, signing_args=None):
   """Signs the current compressed APEX with the given payload/container keys.
 
   Args:
@@ -503,6 +505,7 @@
     raise ApexInfoError(
         'Failed to get type for {}:\n{}'.format(apex_file, e))
 
+
 def GetApexInfoFromTargetFiles(input_file, partition, compressed_only=True):
   """
   Get information about system APEX stored in the input_file zip
@@ -545,7 +548,7 @@
   for apex_filename in os.listdir(target_dir):
     apex_filepath = os.path.join(target_dir, apex_filename)
     if not os.path.isfile(apex_filepath) or \
-        not zipfile.is_zipfile(apex_filepath):
+            not zipfile.is_zipfile(apex_filepath):
       logger.info("Skipping %s because it's not a zipfile", apex_filepath)
       continue
     apex_info = ota_metadata_pb2.ApexInfo()
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 2859948..0842af9 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -428,7 +428,7 @@
   if is_compressed:
     uncompressed = tempfile.NamedTemporaryFile()
     with gzip.open(unsigned.name, "rb") as in_file, \
-         open(uncompressed.name, "wb") as out_file:
+            open(uncompressed.name, "wb") as out_file:
       shutil.copyfileobj(in_file, out_file)
 
     # Finally, close the "unsigned" file (which is gzip compressed), and then
@@ -468,7 +468,7 @@
     # Recompress the file after it has been signed.
     compressed = tempfile.NamedTemporaryFile()
     with open(signed.name, "rb") as in_file, \
-         gzip.open(compressed.name, "wb") as out_file:
+            gzip.open(compressed.name, "wb") as out_file:
       shutil.copyfileobj(in_file, out_file)
 
     data = compressed.read()
@@ -484,21 +484,21 @@
 
 def IsBuildPropFile(filename):
   return filename in (
-        "SYSTEM/etc/prop.default",
-        "BOOT/RAMDISK/prop.default",
-        "RECOVERY/RAMDISK/prop.default",
+      "SYSTEM/etc/prop.default",
+      "BOOT/RAMDISK/prop.default",
+      "RECOVERY/RAMDISK/prop.default",
 
-        "VENDOR_BOOT/RAMDISK/default.prop",
-        "VENDOR_BOOT/RAMDISK/prop.default",
+      "VENDOR_BOOT/RAMDISK/default.prop",
+      "VENDOR_BOOT/RAMDISK/prop.default",
 
-        # ROOT/default.prop is a legacy path, but may still exist for upgrading
-        # devices that don't support `property_overrides_split_enabled`.
-        "ROOT/default.prop",
+      # ROOT/default.prop is a legacy path, but may still exist for upgrading
+      # devices that don't support `property_overrides_split_enabled`.
+      "ROOT/default.prop",
 
-        # RECOVERY/RAMDISK/default.prop is a legacy path, but will always exist
-        # as a symlink in the current code. So it's a no-op here. Keeping the
-        # path here for clarity.
-        "RECOVERY/RAMDISK/default.prop") or filename.endswith("build.prop")
+      # RECOVERY/RAMDISK/default.prop is a legacy path, but will always exist
+      # as a symlink in the current code. So it's a no-op here. Keeping the
+      # path here for clarity.
+      "RECOVERY/RAMDISK/default.prop") or filename.endswith("build.prop")
 
 
 def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
@@ -561,7 +561,7 @@
 
       # We've asserted not having a case with only one of them PRESIGNED.
       if (payload_key not in common.SPECIAL_CERT_STRINGS and
-          container_key not in common.SPECIAL_CERT_STRINGS):
+              container_key not in common.SPECIAL_CERT_STRINGS):
         print("    signing: %-*s container (%s)" % (
             maxsize, name, container_key))
         print("           : %-*s payload   (%s)" % (
@@ -575,7 +575,7 @@
             key_passwords,
             apk_keys,
             codename_to_api_level_map,
-            no_hashtree=True,
+            no_hashtree=None,  # Let apex_util determine if hash tree is needed
             signing_args=OPTIONS.avb_extra_args.get('apex'))
         common.ZipWrite(output_tf_zip, signed_apex, filename)
 
@@ -658,7 +658,7 @@
     # Updates system_other.avbpubkey in /product/etc/.
     elif filename in (
         "PRODUCT/etc/security/avb/system_other.avbpubkey",
-        "SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
+            "SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
       # Only update system_other's public key, if the corresponding signing
       # key is specified via --avb_system_other_key.
       signing_key = OPTIONS.avb_keys.get("system_other")
@@ -671,7 +671,7 @@
     # Should NOT sign boot-debug.img.
     elif filename in (
         "BOOT/RAMDISK/force_debuggable",
-        "BOOT/RAMDISK/first_stage_ramdisk/force_debuggable"):
+            "BOOT/RAMDISK/first_stage_ramdisk/force_debuggable"):
       raise common.ExternalError("debuggable boot.img cannot be signed")
 
     # A non-APK file; copy it verbatim.
@@ -762,7 +762,8 @@
   # it's only checking entries with global seinfo at the moment (i.e. ignoring
   # the ones with inner packages). (Bug: 69479366)
   root = ElementTree.fromstring(data)
-  signatures = [signer.attrib['signature'] for signer in root.findall('signer')]
+  signatures = [signer.attrib['signature']
+                for signer in root.findall('signer')]
   assert len(signatures) == len(set(signatures)), \
       "Found duplicate entries after cert replacement: {}".format(data)
 
@@ -807,7 +808,7 @@
     if line and line[0] != '#' and "=" in line:
       key, value = line.split("=", 1)
       if (key.startswith("ro.") and
-          key.endswith((".build.fingerprint", ".build.thumbprint"))):
+              key.endswith((".build.fingerprint", ".build.thumbprint"))):
         pieces = value.split("/")
         pieces[-1] = EditTags(pieces[-1])
         value = "/".join(pieces)
@@ -1000,7 +1001,7 @@
     ReplaceAvbPartitionSigningKey(partition)
 
   for custom_partition in misc_info.get(
-      "avb_custom_images_partition_list", "").strip().split():
+          "avb_custom_images_partition_list", "").strip().split():
     ReplaceAvbPartitionSigningKey(custom_partition)
 
 
@@ -1065,7 +1066,7 @@
           devkeydir + "/shared":   d + "/shared",
           devkeydir + "/platform": d + "/platform",
           devkeydir + "/networkstack": d + "/networkstack",
-          })
+      })
     else:
       OPTIONS.key_map[s] = d
 
@@ -1168,8 +1169,8 @@
     if container_cert == 'PRESIGNED' and container_private_key == 'PRESIGNED':
       container_key = 'PRESIGNED'
     elif CompareKeys(
-        container_cert, OPTIONS.public_key_suffix,
-        container_private_key, OPTIONS.private_key_suffix):
+            container_cert, OPTIONS.public_key_suffix,
+            container_private_key, OPTIONS.private_key_suffix):
       container_key = container_cert[:-len(OPTIONS.public_key_suffix)]
     else:
       raise ValueError("Failed to parse container keys: \n{}".format(line))