blob: 906284e0985c2fd49ca05a50d57467a97123ad75 [file] [log] [blame]
Rico Wind744ba752021-01-22 06:24:49 +01001#!/usr/bin/env python3
Rico Wind0ed24cc2018-03-23 07:16:35 +01002# Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
Rico Wind744ba752021-01-22 06:24:49 +01006import optparse
Søren Gjessecdae8792018-12-12 09:02:43 +01007import os
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +02008import shutil
Rico Wind0ed24cc2018-03-23 07:16:35 +01009import subprocess
Rico Wind744ba752021-01-22 06:24:49 +010010import sys
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +020011import time
12
Rico Wind0ed24cc2018-03-23 07:16:35 +010013import utils
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +020014import zip_utils
Rico Wind0ed24cc2018-03-23 07:16:35 +010015
Rico Wind744ba752021-01-22 06:24:49 +010016USAGE = 'usage: %prog [options] <apk>'
17
18def parse_options():
19 parser = optparse.OptionParser(usage=USAGE)
20 parser.add_option('--keystore',
21 help='keystore file (default ~/.android/app.keystore)',
22 default='~/.android/app.keystore')
23 parser.add_option('--sign',
24 help='Sign the passed in apk.',
25 default=False,
26 action='store_true')
27 parser.add_option('--use_apksigner',
28 help='Use apksigner to sign.',
29 default=False,
30 action='store_true')
31 parser.add_option('--output',
32 help='Where to put the signed apk.)',
33 default=None)
34
35 (options, args) = parser.parse_args()
36 if len(args) != 1:
37 parser.error('Expected <apk> argument, got: ' + ' '.join(args))
38 apk = args[0]
39 return (options, apk)
40
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +020041def add_baseline_profile_to_apk(apk, baseline_profile, tmp_dir):
42 if baseline_profile is None:
43 return apk
44 ts = time.time_ns()
45 dest_apk = os.path.join(tmp_dir, 'app-%s.apk' % ts)
46 dest_apk_aligned = os.path.join(tmp_dir, 'app-aligned-%s.apk' % ts)
47 dest_apk_signed = os.path.join(tmp_dir, 'app-signed-%s.apk' % ts)
48 shutil.copy2(apk, dest_apk)
49 zip_utils.add_file_to_zip(
50 baseline_profile, 'assets/dexopt/baseline.prof', dest_apk)
51 align(dest_apk, dest_apk_aligned)
52 sign_with_apksigner(dest_apk_aligned, dest_apk_signed)
53 return dest_apk_signed
54
55def align(apk, aligned_apk):
56 zipalign_path = (
57 'zipalign' if 'build_tools' in os.environ.get('PATH')
58 else os.path.join(utils.getAndroidBuildTools(), 'zipalign'))
59 cmd = [zipalign_path, '-f', '4', apk, aligned_apk]
60 utils.RunCmd(cmd, quiet=True, logging=False)
61 return aligned_apk
62
63def default_keystore():
64 return os.path.join(os.getenv('HOME'), '.android', 'app.keystore')
Rico Wind744ba752021-01-22 06:24:49 +010065
Christoffer Quist Adamsen41cbdca2019-04-12 08:52:03 +020066def sign(unsigned_apk, signed_apk, keystore, quiet=False, logging=True):
Christoffer Quist Adamsen1de3dde2019-01-24 13:17:46 +010067 utils.Print('Signing (ignore the warnings)', quiet=quiet)
Rico Wind0ed24cc2018-03-23 07:16:35 +010068 cmd = ['zip', '-d', unsigned_apk, 'META-INF/*']
Rico Windfecaf022020-01-28 12:28:31 +010069 utils.RunCmd(cmd, quiet=quiet, logging=logging, fail=False)
Rico Wind0ed24cc2018-03-23 07:16:35 +010070 cmd = [
71 'jarsigner',
72 '-sigalg', 'SHA1withRSA',
73 '-digestalg', 'SHA1',
74 '-keystore', keystore,
75 '-storepass', 'android',
76 '-signedjar', signed_apk,
77 unsigned_apk,
78 'androiddebugkey'
79 ]
Christoffer Quist Adamsen1de3dde2019-01-24 13:17:46 +010080 utils.RunCmd(cmd, quiet=quiet)
Søren Gjessecdae8792018-12-12 09:02:43 +010081
Christoffer Quist Adamsen3b6f1062019-02-07 09:49:43 +010082def sign_with_apksigner(
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +020083 unsigned_apk, signed_apk, keystore=None, password='android', quiet=False,
Christoffer Quist Adamsen41cbdca2019-04-12 08:52:03 +020084 logging=True):
Søren Gjessecdae8792018-12-12 09:02:43 +010085 cmd = [
Morten Krogh-Jespersen220e5702019-02-27 12:57:01 +010086 os.path.join(utils.getAndroidBuildTools(), 'apksigner'),
Søren Gjessecdae8792018-12-12 09:02:43 +010087 'sign',
88 '-v',
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +020089 '--ks', keystore or default_keystore(),
Søren Gjessecdae8792018-12-12 09:02:43 +010090 '--ks-pass', 'pass:' + password,
91 '--min-sdk-version', '19',
92 '--out', signed_apk,
Christoffer Quist Adamsen8c803b42022-05-31 10:36:17 +020093 '--v2-signing-enabled',
Søren Gjessecdae8792018-12-12 09:02:43 +010094 unsigned_apk
95 ]
Christoffer Quist Adamsen41cbdca2019-04-12 08:52:03 +020096 utils.RunCmd(cmd, quiet=quiet, logging=logging)
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +020097 return signed_apk
Rico Wind744ba752021-01-22 06:24:49 +010098
99def main():
100 (options, apk) = parse_options()
101 if options.sign:
102 if not options.output:
103 print('When signing you must specify an output apk')
104 return 1
105 if not options.keystore:
106 print('When signing you must specify a keystore')
107 return 1
108 if options.use_apksigner:
109 sign_with_apksigner(apk, options.output, options.keystore)
110 else:
111 sign(apk, options.output, options.keystore)
112 return 0
113
114if __name__ == '__main__':
115 sys.exit(main())