Index: build/android/gyp/package_resources.py |
diff --git a/build/android/gyp/package_resources.py b/build/android/gyp/package_resources.py |
index 2251de00c89178e176478469dee313527e145ff1..f2c2a6ed9ee6329bc3a44a6b487c87aef41dd997 100755 |
--- a/build/android/gyp/package_resources.py |
+++ b/build/android/gyp/package_resources.py |
@@ -16,9 +16,52 @@ https://android.googlesource.com/platform/sdk/+/master/files/ant/build.xml |
import optparse |
import os |
import shutil |
+import zipfile |
from util import build_utils |
+ |
+# List is generated from the chrome_apk.apk_intermediates.ap_ via: |
+# unzip -l $FILE_AP_ | cut -c31- | grep res/draw | cut -d'/' -f 2 | sort \ |
+# | uniq | grep -- -tvdpi- | cut -c10- |
+# and then manually sorted. |
+# Note that we can't just do a cross-product of dimentions because the filenames |
+# become too big and aapt fails to create the files. |
+# This leaves all default drawables (mdpi) in the main apk. Android gets upset |
+# though if any drawables are missing from the default drawables/ directory. |
+DENSITY_SPLITS = { |
+ 'hdpi': ( |
+ 'hdpi-v4', # Order matters for output file names. |
+ 'ldrtl-hdpi-v4', |
+ 'sw600dp-hdpi-v13', |
+ 'ldrtl-hdpi-v17', |
+ 'ldrtl-sw600dp-hdpi-v17', |
+ 'hdpi-v21', |
+ ), |
+ 'xhdpi': ( |
+ 'xhdpi-v4', |
+ 'ldrtl-xhdpi-v4', |
+ 'sw600dp-xhdpi-v13', |
+ 'ldrtl-xhdpi-v17', |
+ 'ldrtl-sw600dp-xhdpi-v17', |
+ 'xhdpi-v21', |
+ ), |
+ 'xxhdpi': ( |
+ 'xxhdpi-v4', |
+ 'ldrtl-xxhdpi-v4', |
+ 'sw600dp-xxhdpi-v13', |
+ 'ldrtl-xxhdpi-v17', |
+ 'ldrtl-sw600dp-xxhdpi-v17', |
+ 'xxhdpi-v21', |
+ ), |
+ 'tvdpi': ( |
+ 'tvdpi-v4', |
+ 'sw600dp-tvdpi-v13', |
+ 'ldrtl-sw600dp-tvdpi-v17', |
+ ), |
+} |
+ |
+ |
def ParseArgs(): |
"""Parses command line options. |
@@ -28,8 +71,8 @@ def ParseArgs(): |
parser = optparse.OptionParser() |
build_utils.AddDepfileOption(parser) |
parser.add_option('--android-sdk', help='path to the Android SDK folder') |
- parser.add_option('--android-sdk-tools', |
- help='path to the Android SDK build tools folder') |
+ parser.add_option('--aapt-path', |
+ help='path to the Android aapt tool') |
parser.add_option('--configuration-name', |
help='Gyp\'s configuration name (Debug or Release).') |
@@ -48,6 +91,10 @@ def ParseArgs(): |
help='directories containing assets to be packaged') |
parser.add_option('--no-compress', help='disables compression for the ' |
'given comma separated list of extensions') |
+ parser.add_option( |
+ '--create-density-splits', |
+ action='store_true', |
+ help='Enables density splits') |
parser.add_option('--apk-path', |
help='Path to output (partial) apk.') |
@@ -58,9 +105,9 @@ def ParseArgs(): |
parser.error('No positional arguments should be given.') |
# Check that required options have been provided. |
- required_options = ('android_sdk', 'android_sdk_tools', 'configuration_name', |
+ required_options = ('android_sdk', 'aapt_path', 'configuration_name', |
'android_manifest', 'version_code', 'version_name', |
- 'resource_zips', 'asset_dir', 'apk_path') |
+ 'apk_path') |
build_utils.CheckOptions(options, parser, required=required_options) |
@@ -114,10 +161,33 @@ def PackageArgsForExtractedZip(d): |
return package_command |
+def RenameDensitySplits(apk_path): |
+ """Renames all density splits to have shorter / predictable names.""" |
+ for density, config in DENSITY_SPLITS.iteritems(): |
+ src_path = '%s_%s' % (apk_path, '_'.join(config)) |
+ dst_path = '%s-%s' % (apk_path, density) |
+ if os.path.exists(dst_path): |
+ os.unlink(dst_path) |
+ os.rename(src_path, dst_path) |
+ |
+ |
+def CheckDensityMissedConfigs(apk_path): |
+ """Raises an exception if apk_path contains any density-specifc files.""" |
+ triggers = ['-%s' % density for density in DENSITY_SPLITS] |
+ with zipfile.ZipFile(apk_path) as main_apk_zip: |
+ for name in main_apk_zip.namelist(): |
+ for trigger in triggers: |
+ if trigger in name and not 'mipmap-' in name: |
+ raise Exception(('Found density in main apk that should have been ' + |
+ 'put into a split: %s\nYou need to update ' + |
+ 'package_resources.py to include this new ' + |
+ 'config.') % name) |
+ |
+ |
def main(): |
options = ParseArgs() |
android_jar = os.path.join(options.android_sdk, 'android.jar') |
- aapt = os.path.join(options.android_sdk_tools, 'aapt') |
+ aapt = options.aapt_path |
with build_utils.TempDir() as temp_dir: |
package_command = [aapt, |
@@ -128,7 +198,6 @@ def main(): |
'--no-crunch', |
'-f', |
'--auto-add-overlay', |
- |
'-I', android_jar, |
'-F', options.apk_path, |
'--ignore-assets', build_utils.AAPT_IGNORE_PATTERN, |
@@ -140,16 +209,21 @@ def main(): |
if options.shared_resources: |
package_command.append('--shared-lib') |
- if os.path.exists(options.asset_dir): |
+ if options.asset_dir and os.path.exists(options.asset_dir): |
package_command += ['-A', options.asset_dir] |
- dep_zips = build_utils.ParseGypList(options.resource_zips) |
- for z in dep_zips: |
- subdir = os.path.join(temp_dir, os.path.basename(z)) |
- if os.path.exists(subdir): |
- raise Exception('Resource zip name conflict: ' + os.path.basename(z)) |
- build_utils.ExtractAll(z, path=subdir) |
- package_command += PackageArgsForExtractedZip(subdir) |
+ if options.resource_zips: |
+ dep_zips = build_utils.ParseGypList(options.resource_zips) |
+ for z in dep_zips: |
+ subdir = os.path.join(temp_dir, os.path.basename(z)) |
+ if os.path.exists(subdir): |
+ raise Exception('Resource zip name conflict: ' + os.path.basename(z)) |
+ build_utils.ExtractAll(z, path=subdir) |
+ package_command += PackageArgsForExtractedZip(subdir) |
+ |
+ if options.create_density_splits: |
+ for config in DENSITY_SPLITS.itervalues(): |
+ package_command.extend(('--split', ','.join(config))) |
if 'Debug' in options.configuration_name: |
package_command += ['--debug-mode'] |
@@ -157,6 +231,10 @@ def main(): |
build_utils.CheckOutput( |
package_command, print_stdout=False, print_stderr=False) |
+ if options.create_density_splits: |
+ CheckDensityMissedConfigs(options.apk_path) |
+ RenameDensitySplits(options.apk_path) |
+ |
if options.depfile: |
build_utils.WriteDepfile( |
options.depfile, |