Refactor apex signing logic in preparation for compressed apexes

Logic for signing compressed apex will be added in the follow-up cl.

Test: python -m unittest test_sign_apex
Bug: 172912232
Change-Id: I8dc1d334c17e11f9eed8fe0a575b6dfcf337ab5d
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index 6808f15..c8a0dcc 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -300,13 +300,13 @@
   return payload_info
 
 
-def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
-             apk_keys, codename_to_api_level_map,
-             no_hashtree, signing_args=None):
-  """Signs the current APEX with the given payload/container keys.
+def SignUncompressedApex(avbtool, apex_data, payload_key, container_key,
+                         container_pw, apk_keys, codename_to_api_level_map,
+                         no_hashtree, signing_args=None):
+  """Signs the current uncompressed APEX with the given payload/container keys.
 
   Args:
-    apex_data: Raw APEX data.
+    apex_data: Raw uncompressed APEX data.
     payload_key: The path to payload signing key (w/ extension).
     container_key: The path to container signing key (w/o extension).
     container_pw: The matching password of the container_key, or None.
@@ -380,3 +380,51 @@
       extra_signapk_args=extra_signapk_args)
 
   return signed_apex
+
+
+def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
+             apk_keys, codename_to_api_level_map,
+             no_hashtree, signing_args=None):
+  """Signs the current APEX with the given payload/container keys.
+
+  Args:
+    apex_file: Path to apex file path.
+    payload_key: The path to payload signing key (w/ extension).
+    container_key: The path to container signing key (w/o extension).
+    container_pw: The matching password of the container_key, or None.
+    apk_keys: A dict that holds the signing keys for apk files.
+    codename_to_api_level_map: A dict that maps from codename to API level.
+    no_hashtree: Don't include hashtree in the signed APEX.
+    signing_args: Additional args to be passed to the payload signer.
+
+  Returns:
+    The path to the signed APEX file.
+  """
+  apex_file = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
+  with open(apex_file, 'wb') as output_fp:
+    output_fp.write(apex_data)
+
+  debugfs_path = os.path.join(OPTIONS.search_path, "bin", "debugfs_static")
+  cmd = ['deapexer', '--debugfs_path', debugfs_path,
+         'info', '--print-type', apex_file]
+
+  try:
+    apex_type = common.RunAndCheckOutput(cmd).strip()
+    if apex_type == 'UNCOMPRESSED':
+      return SignUncompressedApex(
+          avbtool,
+          apex_data,
+          payload_key=payload_key,
+          container_key=container_key,
+          container_pw=None,
+          codename_to_api_level_map=codename_to_api_level_map,
+          no_hashtree=no_hashtree,
+          apk_keys=apk_keys,
+          signing_args=signing_args)
+    else:
+      # TODO(b/172912232): support signing compressed apex
+      raise ApexInfoError('Unsupported apex type {}'.format(apex_type))
+
+  except common.ExternalError as e:
+    raise ApexInfoError(
+        'Failed to get type for {}:\n{}'.format(apex_file))