Add a relayout.py script to relayout an existing APK using a profile
Change-Id: Idd2518909b129d4d1af3b750873441422d897f69
diff --git a/tools/startup/generate_startup_descriptors.py b/tools/startup/generate_startup_descriptors.py
index ee3f27a..d0af556 100755
--- a/tools/startup/generate_startup_descriptors.py
+++ b/tools/startup/generate_startup_descriptors.py
@@ -30,7 +30,7 @@
profile_classes_and_methods, iteration, options)
current_startup_descriptors = \
profile_utils.transform_art_profile_to_r8_startup_list(
- profile_classes_and_methods)
+ profile_classes_and_methods, options.generalize_synthetics)
write_tmp_startup_descriptors(current_startup_descriptors, iteration, options)
new_startup_descriptors = add_r8_startup_descriptors(
startup_descriptors, current_startup_descriptors)
@@ -307,6 +307,11 @@
result.add_argument('--device-pin',
help='Device pin code (e.g., 1234)',
action='append')
+ result.add_argument('--generalize-synthetics',
+ help='Whether synthetics should be abstracted into their '
+ 'synthetic contexts',
+ action='store_true',
+ default=False)
result.add_argument('--logcat',
action='store_true',
default=False)
diff --git a/tools/startup/profile_utils.py b/tools/startup/profile_utils.py
index 0e69397..923326f 100755
--- a/tools/startup/profile_utils.py
+++ b/tools/startup/profile_utils.py
@@ -41,11 +41,12 @@
art_profile[descriptor] = flags
return art_profile
-def transform_art_profile_to_r8_startup_list(art_profile):
+def transform_art_profile_to_r8_startup_list(
+ art_profile, generalize_synthetics=False):
r8_startup_list = {}
for startup_descriptor, flags in art_profile.items():
transformed_startup_descriptor = transform_synthetic_descriptor(
- startup_descriptor)
+ startup_descriptor) if generalize_synthetics else startup_descriptor
r8_startup_list[transformed_startup_descriptor] = {
'conditional_startup': False,
'post_startup': flags['post_startup'],
diff --git a/tools/startup/relayout.py b/tools/startup/relayout.py
new file mode 100755
index 0000000..6220336
--- /dev/null
+++ b/tools/startup/relayout.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import argparse
+import os
+import subprocess
+import sys
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+import apk_masseur
+import toolhelper
+import utils
+
+def parse_options(argv):
+ result = argparse.ArgumentParser(
+ description='Relayout a given APK using a startup profile.')
+ result.add_argument('--apk',
+ help='Path to the .apk',
+ required=True)
+ result.add_argument('--out',
+ help='Destination of resulting apk',
+ required=True)
+ result.add_argument('--profile',
+ help='Path to the startup profile',
+ required=True)
+ options, args = result.parse_known_args(argv)
+ return options, args
+
+def get_min_api(apk):
+ aapt = os.path.join(utils.getAndroidBuildTools(), 'aapt')
+ cmd = [aapt, 'dump', 'badging', apk]
+ stdout = subprocess.check_output(cmd).decode('utf-8').strip()
+ for line in stdout.splitlines():
+ if line.startswith('sdkVersion:\''):
+ return int(line[len('sdkVersion:\''): -1])
+ raise ValueError('Unexpected stdout: %s' % stdout)
+
+def main(argv):
+ (options, args) = parse_options(argv)
+ with utils.TempDir() as temp:
+ dex = os.path.join(temp, 'dex.zip')
+ d8_args = [
+ '--min-api', str(get_min_api(options.apk)),
+ '--output', dex,
+ '--no-desugaring',
+ '--release',
+ options.apk]
+ extra_args = ['-Dcom.android.tools.r8.startup.profile=%s' % options.profile]
+ toolhelper.run(
+ 'd8',
+ d8_args,
+ extra_args=extra_args,
+ main='com.android.tools.r8.D8')
+ apk_masseur.masseur(options.apk, dex=dex, out=options.out)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))