Commit 7d191755 authored by Andrew Grieve's avatar Andrew Grieve Committed by Commit Bot

Android: Speed up apkbuilder.py's signing step

* Disable v1 signatures for Monochrome
* Disable v3 signatures always
* Adds timestamps for profiling (behind APKBUILDER_DEBUG)

Signing debug Monochrome.apk goes from 10 seconds to 3 seconds.

Here's an after breakdown from my machine:
I 59413      9 Started (apkbuilder.py)
D 59413     29 Adding AndroidManifest.xml
D 59413     33 Adding assets/
D 59413    360 Adding classes.dex
D 59413   1713 Adding lib/
D 59413   2107 Adding res/
D 59413   2286 Adding Java resources
D 59413   2294 Running zipalign
D 59413   2614 Signing apk
I 59413   7513 Job's done (apkbuilder.py)

Bug: 1036740
Change-Id: Ic12f52e5e3bd79ca057513cc2ae3d1c344d9858a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1980310Reviewed-by: default avatarPeter Wen <wnwen@chromium.org>
Commit-Queue: Peter Wen <wnwen@chromium.org>
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#728514}
parent 094446a3
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
"""Adds the code parts to a resource APK.""" """Adds the code parts to a resource APK."""
import argparse import argparse
import logging
import os import os
import shutil import shutil
import sys import sys
...@@ -99,6 +100,8 @@ def _ParseArgs(args): ...@@ -99,6 +100,8 @@ def _ParseArgs(args):
help='Keystore password') help='Keystore password')
parser.add_argument('--key-name', parser.add_argument('--key-name',
help='Keystore name') help='Keystore name')
parser.add_argument(
'--min-sdk-version', required=True, help='Value of APK\'s minSdkVersion')
options = parser.parse_args(args) options = parser.parse_args(args)
options.assets = build_utils.ParseGnList(options.assets) options.assets = build_utils.ParseGnList(options.assets)
options.uncompressed_assets = build_utils.ParseGnList( options.uncompressed_assets = build_utils.ParseGnList(
...@@ -228,6 +231,7 @@ def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress): ...@@ -228,6 +231,7 @@ def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
def main(args): def main(args):
build_utils.InitLogging('APKBUILDER_DEBUG')
args = build_utils.ExpandFileArgs(args) args = build_utils.ExpandFileArgs(args)
options = _ParseArgs(args) options = _ParseArgs(args)
...@@ -297,14 +301,17 @@ def main(args): ...@@ -297,14 +301,17 @@ def main(args):
resource_infos = resource_apk.infolist() resource_infos = resource_apk.infolist()
# 1. AndroidManifest.xml # 1. AndroidManifest.xml
logging.debug('Adding AndroidManifest.xml')
copy_resource( copy_resource(
resource_apk.getinfo('AndroidManifest.xml'), out_dir=apk_manifest_dir) resource_apk.getinfo('AndroidManifest.xml'), out_dir=apk_manifest_dir)
# 2. Assets # 2. Assets
logging.debug('Adding assets/')
_AddAssets(out_apk, assets, disable_compression=False) _AddAssets(out_apk, assets, disable_compression=False)
_AddAssets(out_apk, uncompressed_assets, disable_compression=True) _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
# 3. Dex files # 3. Dex files
logging.debug('Adding classes.dex')
if options.dex_file and options.dex_file.endswith('.zip'): if options.dex_file and options.dex_file.endswith('.zip'):
with zipfile.ZipFile(options.dex_file, 'r') as dex_zip: with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
...@@ -321,6 +328,7 @@ def main(args): ...@@ -321,6 +328,7 @@ def main(args):
compress=not options.uncompress_dex) compress=not options.uncompress_dex)
# 4. Native libraries. # 4. Native libraries.
logging.debug('Adding lib/')
_AddNativeLibraries(out_apk, native_libs, options.android_abi, _AddNativeLibraries(out_apk, native_libs, options.android_abi,
options.uncompress_shared_libraries) options.uncompress_shared_libraries)
...@@ -359,6 +367,7 @@ def main(args): ...@@ -359,6 +367,7 @@ def main(args):
build_utils.AddToZipHermetic(out_apk, apk_path, data='') build_utils.AddToZipHermetic(out_apk, apk_path, data='')
# 5. Resources # 5. Resources
logging.debug('Adding res/')
for info in sorted(resource_infos, key=lambda i: i.filename): for info in sorted(resource_infos, key=lambda i: i.filename):
if info.filename != 'AndroidManifest.xml': if info.filename != 'AndroidManifest.xml':
copy_resource(info) copy_resource(info)
...@@ -366,6 +375,7 @@ def main(args): ...@@ -366,6 +375,7 @@ def main(args):
# 6. Java resources that should be accessible via # 6. Java resources that should be accessible via
# Class.getResourceAsStream(), in particular parts of Emma jar. # Class.getResourceAsStream(), in particular parts of Emma jar.
# Prebuilt jars may contain class files which we shouldn't include. # Prebuilt jars may contain class files which we shouldn't include.
logging.debug('Adding Java resources')
for java_resource in options.java_resources: for java_resource in options.java_resources:
with zipfile.ZipFile(java_resource, 'r') as java_resource_jar: with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
for apk_path in sorted(java_resource_jar.namelist()): for apk_path in sorted(java_resource_jar.namelist()):
...@@ -386,7 +396,8 @@ def main(args): ...@@ -386,7 +396,8 @@ def main(args):
if options.format == 'apk': if options.format == 'apk':
finalize_apk.FinalizeApk(options.apksigner_jar, options.zipalign_path, finalize_apk.FinalizeApk(options.apksigner_jar, options.zipalign_path,
f.name, f.name, options.key_path, f.name, f.name, options.key_path,
options.key_passwd, options.key_name) options.key_passwd, options.key_name,
int(options.min_sdk_version))
if options.depfile: if options.depfile:
build_utils.WriteDepfile( build_utils.WriteDepfile(
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
"""Signs and aligns an APK.""" """Signs and aligns an APK."""
import argparse import argparse
import logging
import shutil import shutil
import subprocess import subprocess
import tempfile import tempfile
...@@ -12,15 +13,17 @@ from util import build_utils ...@@ -12,15 +13,17 @@ from util import build_utils
def FinalizeApk(apksigner_path, zipalign_path, unsigned_apk_path, def FinalizeApk(apksigner_path, zipalign_path, unsigned_apk_path,
final_apk_path, key_path, key_passwd, key_name): final_apk_path, key_path, key_passwd, key_name,
min_sdk_version):
# Use a tempfile so that Ctrl-C does not leave the file with a fresh mtime # Use a tempfile so that Ctrl-C does not leave the file with a fresh mtime
# and a corrupted state. # and a corrupted state.
with tempfile.NamedTemporaryFile() as staging_file: with tempfile.NamedTemporaryFile() as staging_file:
# v2 signing requires that zipalign happen first. # v2 signing requires that zipalign happen first.
logging.debug('Running zipalign')
subprocess.check_output([ subprocess.check_output([
zipalign_path, '-p', '-f', '4', zipalign_path, '-p', '-f', '4',
unsigned_apk_path, staging_file.name]) unsigned_apk_path, staging_file.name])
subprocess.check_output([ sign_cmd = [
build_utils.JAVA_PATH, build_utils.JAVA_PATH,
'-jar', '-jar',
apksigner_path, apksigner_path,
...@@ -35,9 +38,21 @@ def FinalizeApk(apksigner_path, zipalign_path, unsigned_apk_path, ...@@ -35,9 +38,21 @@ def FinalizeApk(apksigner_path, zipalign_path, unsigned_apk_path,
key_name, key_name,
'--ks-pass', '--ks-pass',
'pass:' + key_passwd, 'pass:' + key_passwd,
# Force SHA-1 (makes signing faster; insecure is fine for local builds). ]
'--min-sdk-version', # V3 signing adds security niceties, which are irrelevant for local builds.
'1', sign_cmd += ['--v3-signing-enabled', 'false']
])
if min_sdk_version >= 24:
# Disable v1 signatures when v2 signing can be used (it's much faster).
# By default, both v1 and v2 signing happen.
sign_cmd += ['--v1-signing-enabled', 'false']
else:
# Force SHA-1 (makes signing faster; insecure is fine for local builds).
# Leave v2 signing enabled since it verifies faster on device when
# supported.
sign_cmd += ['--min-sdk-version', '1']
logging.debug('Signing apk')
subprocess.check_call(sign_cmd)
shutil.move(staging_file.name, final_apk_path) shutil.move(staging_file.name, final_apk_path)
staging_file.delete = False staging_file.delete = False
...@@ -2542,6 +2542,7 @@ if (enable_java_templates) { ...@@ -2542,6 +2542,7 @@ if (enable_java_templates) {
# dex_path: Path to classes.dex file to include (optional). # dex_path: Path to classes.dex file to include (optional).
# packaged_resources_path: Path to .ap_ to use. # packaged_resources_path: Path to .ap_ to use.
# output_apk_path: Output path for the generated .apk. # output_apk_path: Output path for the generated .apk.
# min_sdk_version: The minimum Android SDK version this target supports.
# native_lib_placeholders: List of placeholder filenames to add to the apk # native_lib_placeholders: List of placeholder filenames to add to the apk
# (optional). # (optional).
# secondary_native_lib_placeholders: List of placeholder filenames to add to # secondary_native_lib_placeholders: List of placeholder filenames to add to
...@@ -2616,6 +2617,7 @@ if (enable_java_templates) { ...@@ -2616,6 +2617,7 @@ if (enable_java_templates) {
invoker.keystore_name, invoker.keystore_name,
"--key-passwd", "--key-passwd",
invoker.keystore_password, invoker.keystore_password,
"--min-sdk-version=${invoker.min_sdk_version}",
] ]
if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) { if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) {
args += [ "--uncompress-dex" ] args += [ "--uncompress-dex" ]
...@@ -3667,6 +3669,7 @@ template("create_android_app_bundle_module") { ...@@ -3667,6 +3669,7 @@ template("create_android_app_bundle_module") {
"--secondary-native-lib-placeholders=@FileArg($_rebased_build_config" + "--secondary-native-lib-placeholders=@FileArg($_rebased_build_config" +
":native:secondary_native_library_placeholders)", ":native:secondary_native_library_placeholders)",
"--android-abi=$android_app_abi", "--android-abi=$android_app_abi",
"--min-sdk-version=${invoker.min_sdk_version}",
"--uncompress-shared-libraries=@FileArg(" + "--uncompress-shared-libraries=@FileArg(" +
"$_rebased_build_config:native:uncompress_shared_libraries)", "$_rebased_build_config:native:uncompress_shared_libraries)",
] ]
......
...@@ -2993,9 +2993,9 @@ if (enable_java_templates) { ...@@ -2993,9 +2993,9 @@ if (enable_java_templates) {
[ [
"disable_checkdiscard", "disable_checkdiscard",
"disable_r8_outlining", "disable_r8_outlining",
"min_sdk_version",
"dexlayout_profile", "dexlayout_profile",
]) ])
min_sdk_version = _min_sdk_version
proguard_enabled = _proguard_enabled proguard_enabled = _proguard_enabled
build_config = _build_config build_config = _build_config
deps = [ deps = [
...@@ -3256,6 +3256,7 @@ if (enable_java_templates) { ...@@ -3256,6 +3256,7 @@ if (enable_java_templates) {
keystore_name = _keystore_name keystore_name = _keystore_name
keystore_path = _keystore_path keystore_path = _keystore_path
keystore_password = _keystore_password keystore_password = _keystore_password
min_sdk_version = _min_sdk_version
uncompress_shared_libraries = _uncompress_shared_libraries uncompress_shared_libraries = _uncompress_shared_libraries
deps = _deps + [ ":$_build_config_target" ] deps = _deps + [ ":$_build_config_target" ]
...@@ -4785,6 +4786,7 @@ if (enable_java_templates) { ...@@ -4785,6 +4786,7 @@ if (enable_java_templates) {
forward_variables_from(invoker, forward_variables_from(invoker,
[ [
"is_multi_abi", "is_multi_abi",
"min_sdk_version",
"uncompress_dex", "uncompress_dex",
]) ])
module_name = _module.name module_name = _module.name
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment