Reland: Android: Use apksigner instead of jarsigner.
Reverted in: f4424029c0d3f43b64dcf5a04488e224229c5ec0. Reason for reland: * Fixed apkmerger.py 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, 814350 Change-Id: I8bb010c2da59ace1450da79985e5f2a1111a9330 Reviewed-on: https://chromium-review.googlesource.com/929101 Reviewed-by: Tao Bai <michaelbai@chromium.org> Reviewed-by: John Budorick <jbudorick@chromium.org> Reviewed-by: agrieve <agrieve@chromium.org> Commit-Queue: agrieve <agrieve@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#538433} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: bef0ce0b1f29658f9c86d89e6a1fbb33069d5754
This commit is contained in:
Родитель
5e17532005
Коммит
3a79eed50c
|
@ -242,9 +242,6 @@ def main(args):
|
|||
def on_stale_md5():
|
||||
tmp_apk = options.output_apk + '.tmp'
|
||||
try:
|
||||
# TODO(agrieve): It would be more efficient to combine this step
|
||||
# with finalize_apk(), which sometimes aligns and uncompresses the
|
||||
# native libraries.
|
||||
with zipfile.ZipFile(options.resource_apk) as resource_apk, \
|
||||
zipfile.ZipFile(tmp_apk, 'w', zipfile.ZIP_DEFLATED) as out_apk:
|
||||
def copy_resource(zipinfo):
|
||||
|
|
|
@ -3,121 +3,59 @@
|
|||
# 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 FinalizeApk(apksigner_path, zipalign_path, unsigned_apk_path,
|
||||
final_apk_path, key_path, key_passwd, key_name):
|
||||
# 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([
|
||||
zipalign_path, '-p', '-f', '4',
|
||||
unsigned_apk_path, staging_file.name])
|
||||
subprocess.check_output([
|
||||
apksigner_path, 'sign',
|
||||
'--in', staging_file.name,
|
||||
'--out', staging_file.name,
|
||||
'--ks', key_path,
|
||||
'--ks-key-alias', key_name,
|
||||
'--ks-pass', 'pass:' + key_passwd,
|
||||
# Force SHA-1 (makes signing faster; insecure is fine for local builds).
|
||||
'--min-sdk-version', '1',
|
||||
])
|
||||
shutil.move(staging_file.name, final_apk_path)
|
||||
staging_file.delete = False
|
||||
|
||||
|
||||
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',
|
||||
]
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
|
||||
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)
|
||||
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()
|
||||
FinalizeApk(options.apksigner_path, options.zipalign_path,
|
||||
options.unsigned_apk_path, options.final_apk_path,
|
||||
options.key_path, options.key_passwd, options.key_name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
main()
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2015 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 split APKs.
|
||||
|
||||
This script is require only by GYP (not GN).
|
||||
"""
|
||||
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
import finalize_apk
|
||||
from util import build_utils
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('--zipalign-path', help='Path to the zipalign tool.')
|
||||
parser.add_option('--resource-packaged-apk-path',
|
||||
help='Base path to input .ap_s.')
|
||||
parser.add_option('--base-output-path',
|
||||
help='Path to output .apk, minus extension.')
|
||||
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')
|
||||
parser.add_option('--densities',
|
||||
help='Comma separated list of densities finalize.')
|
||||
parser.add_option('--languages',
|
||||
help='GYP list of language splits to finalize.')
|
||||
|
||||
options, _ = parser.parse_args()
|
||||
options.load_library_from_zip = 0
|
||||
|
||||
if options.densities:
|
||||
for density in options.densities.split(','):
|
||||
options.unsigned_apk_path = ("%s_%s" %
|
||||
(options.resource_packaged_apk_path, density))
|
||||
options.final_apk_path = ("%s-density-%s.apk" %
|
||||
(options.base_output_path, density))
|
||||
finalize_apk.FinalizeApk(options)
|
||||
|
||||
if options.languages:
|
||||
for lang in build_utils.ParseGnList(options.languages):
|
||||
options.unsigned_apk_path = ("%s_%s" %
|
||||
(options.resource_packaged_apk_path, lang))
|
||||
options.final_apk_path = ("%s-lang-%s.apk" %
|
||||
(options.base_output_path, lang))
|
||||
finalize_apk.FinalizeApk(options)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(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 =
|
||||
|
|
|
@ -1866,9 +1866,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",
|
||||
|
@ -1877,10 +1874,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 = [
|
||||
|
@ -1891,14 +1891,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",
|
||||
|
|
Загрузка…
Ссылка в новой задаче