Commit ca62ba02 authored by Andrew Grieve's avatar Andrew Grieve Committed by Commit Bot

Android: Use apksigner instead of jarsigner.

Brings the finalize_apk step 19 seconds -> 4 seconds on
my machine (for ChromePublic.apk).

Also enables v2 signing of apks, which makes them install
faster on N+ devices.

Bug: 810890
Change-Id: I9fd52ed26c56472bd2894ace6f0516fc386143d6
Reviewed-on: https://chromium-review.googlesource.com/920651Reviewed-by: default avatarJohn Budorick <jbudorick@chromium.org>
Commit-Queue: agrieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537908}
parent aec7a56f
......@@ -3,121 +3,51 @@
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Signs and zipaligns APK.
"""Signs and aligns an APK."""
"""
import optparse
import os
import argparse
import shutil
import sys
import subprocess
import tempfile
import zipfile
# resource_sizes modifies zipfile for zip64 compatibility. See
# https://bugs.python.org/issue14315.
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
import resource_sizes # pylint: disable=unused-import
from util import build_utils
def JarSigner(key_path, key_name, key_passwd, unsigned_path, signed_path):
shutil.copy(unsigned_path, signed_path)
sign_cmd = [
'jarsigner',
'-sigalg', 'MD5withRSA',
'-digestalg', 'SHA1',
'-keystore', key_path,
'-storepass', key_passwd,
signed_path,
key_name,
]
build_utils.CheckOutput(sign_cmd)
def AlignApk(zipalign_path, unaligned_path, final_path):
# Note -p will page align native libraries (files ending with .so), but
# only those that are stored uncompressed.
align_cmd = [
zipalign_path,
'-p',
'-f',
]
align_cmd += [
'4', # 4 bytes
unaligned_path,
final_path,
]
build_utils.CheckOutput(align_cmd)
def main(args):
args = build_utils.ExpandFileArgs(args)
parser = optparse.OptionParser()
build_utils.AddDepfileOption(parser)
parser.add_option('--zipalign-path', help='Path to the zipalign tool.')
parser.add_option('--unsigned-apk-path', help='Path to input unsigned APK.')
parser.add_option('--final-apk-path',
help='Path to output signed and aligned APK.')
parser.add_option('--key-path', help='Path to keystore for signing.')
parser.add_option('--key-passwd', help='Keystore password')
parser.add_option('--key-name', help='Keystore name')
options, _ = parser.parse_args()
input_paths = [
options.unsigned_apk_path,
options.key_path,
]
input_strings = [
options.key_name,
options.key_passwd,
]
build_utils.CallAndWriteDepfileIfStale(
lambda: FinalizeApk(options),
options,
record_path=options.unsigned_apk_path + '.finalize.md5.stamp',
input_paths=input_paths,
input_strings=input_strings,
output_paths=[options.final_apk_path])
def _NormalizeZip(path):
with tempfile.NamedTemporaryFile(suffix='.zip') as hermetic_signed_apk:
with zipfile.ZipFile(path, 'r') as zi:
with zipfile.ZipFile(hermetic_signed_apk, 'w') as zo:
for info in zi.infolist():
# Ignore 'extended local file headers'. Python doesn't write them
# properly (see https://bugs.python.org/issue1742205) which causes
# zipalign to miscalculate alignment. Since we don't use them except
# for alignment anyway, we write a stripped file here and let
# zipalign add them properly later. eLFHs are controlled by 'general
# purpose bit flag 03' (0x08) so we mask that out.
info.flag_bits = info.flag_bits & 0xF7
info.date_time = build_utils.HERMETIC_TIMESTAMP
zo.writestr(info, zi.read(info.filename))
shutil.copy(hermetic_signed_apk.name, path)
def FinalizeApk(options):
with tempfile.NamedTemporaryFile() as signed_apk_path_tmp:
signed_apk_path = signed_apk_path_tmp.name
JarSigner(options.key_path, options.key_name, options.key_passwd,
options.unsigned_apk_path, signed_apk_path)
# Make the newly added signing files hermetic.
_NormalizeZip(signed_apk_path)
AlignApk(options.zipalign_path, signed_apk_path, options.final_apk_path)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--apksigner-path', required=True,
help='Path to the apksigner executable.')
parser.add_argument('--zipalign-path', required=True,
help='Path to the zipalign executable.')
parser.add_argument('--unsigned-apk-path', required=True,
help='Path to input unsigned APK.')
parser.add_argument('--final-apk-path', required=True,
help='Path to output signed and aligned APK.')
parser.add_argument('--key-path', required=True,
help='Path to keystore for signing.')
parser.add_argument('--key-passwd', required=True,
help='Keystore password')
parser.add_argument('--key-name', required=True,
help='Keystore name')
options = parser.parse_args()
# Use a tempfile so that Ctrl-C does not leave the file with a fresh mtime
# and a corrupted state.
with tempfile.NamedTemporaryFile() as staging_file:
# v2 signing requires that zipalign happen first.
subprocess.check_output([
options.zipalign_path, '-p', '-f', '4',
options.unsigned_apk_path, staging_file.name])
subprocess.check_output([
options.apksigner_path, 'sign',
'--in', staging_file.name,
'--out', staging_file.name,
'--ks', options.key_path,
'--ks-key-alias', options.key_name,
'--ks-pass', 'pass:' + options.key_passwd,
])
shutil.move(staging_file.name, options.final_apk_path)
staging_file.delete = False
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
main()
......@@ -263,8 +263,6 @@ if (is_android) {
# Path to the SDK's android.jar
android_sdk_jar = "$android_sdk/android.jar"
zipalign_path = "$android_sdk_build_tools/zipalign"
# Subdirectories inside android_ndk_root that contain the sysroot for the
# associated platform.
x86_android_sysroot_subdir =
......
......@@ -1860,9 +1860,6 @@ if (enable_java_templates) {
# keystore_password: Keystore password.
template("finalize_apk") {
action(target_name) {
deps = []
script = "//build/android/gyp/finalize_apk.py"
depfile = "$target_gen_dir/$target_name.d"
forward_variables_from(invoker,
[
"deps",
......@@ -1871,10 +1868,13 @@ if (enable_java_templates) {
"testonly",
])
sources = [
invoker.input_apk_path,
]
script = "//build/android/gyp/finalize_apk.py"
_apksigner = "$android_sdk_build_tools/apksigner"
_zipalign = "$android_sdk_build_tools/zipalign"
inputs = [
_apksigner,
_zipalign,
invoker.input_apk_path,
invoker.keystore_path,
]
outputs = [
......@@ -1885,14 +1885,14 @@ if (enable_java_templates) {
]
args = [
"--depfile",
rebase_path(depfile, root_build_dir),
"--zipalign-path",
rebase_path(zipalign_path, root_build_dir),
"--unsigned-apk-path",
rebase_path(invoker.input_apk_path, root_build_dir),
"--final-apk-path",
rebase_path(invoker.output_apk_path, root_build_dir),
"--apksigner-path",
rebase_path(_apksigner, root_build_dir),
"--zipalign-path",
rebase_path(_zipalign, root_build_dir),
"--key-path",
rebase_path(invoker.keystore_path, root_build_dir),
"--key-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