| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2014 The Chromium Authors. All rights reserved. | 3 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 # pylint: disable=C0301 | 7 # pylint: disable=C0301 |
| 8 """Package resources into an apk. | 8 """Package resources into an apk. |
| 9 | 9 |
| 10 See https://android.googlesource.com/platform/tools/base/+/master/legacy/ant-tas
ks/src/main/java/com/android/ant/AaptExecTask.java | 10 See https://android.googlesource.com/platform/tools/base/+/master/legacy/ant-tas
ks/src/main/java/com/android/ant/AaptExecTask.java |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 action='store_true', | 128 action='store_true', |
| 129 help='Enables density splits') | 129 help='Enables density splits') |
| 130 parser.add_option('--language-splits', | 130 parser.add_option('--language-splits', |
| 131 default='[]', | 131 default='[]', |
| 132 help='GN list of languages to create splits for') | 132 help='GN list of languages to create splits for') |
| 133 parser.add_option('--locale-whitelist', | 133 parser.add_option('--locale-whitelist', |
| 134 default='[]', | 134 default='[]', |
| 135 help='GN list of languages to include. All other language ' | 135 help='GN list of languages to include. All other language ' |
| 136 'configs will be stripped out. List may include ' | 136 'configs will be stripped out. List may include ' |
| 137 'a combination of Android locales or Chrome locales.') | 137 'a combination of Android locales or Chrome locales.') |
| 138 | |
| 139 parser.add_option('--apk-path', | 138 parser.add_option('--apk-path', |
| 140 help='Path to output (partial) apk.') | 139 help='Path to output (partial) apk.') |
| 140 parser.add_option('--exclude-xxxhdpi', action='store_true', |
| 141 help='Do not include xxxhdpi drawables.') |
| 142 parser.add_option('--xxxhdpi-whitelist', |
| 143 default='[]', |
| 144 help='GN list of globs that say which xxxhdpi images to ' |
| 145 'include even when --exclude-xxxhdpi is set.') |
| 141 | 146 |
| 142 options, positional_args = parser.parse_args(args) | 147 options, positional_args = parser.parse_args(args) |
| 143 | 148 |
| 144 if positional_args: | 149 if positional_args: |
| 145 parser.error('No positional arguments should be given.') | 150 parser.error('No positional arguments should be given.') |
| 146 | 151 |
| 147 # Check that required options have been provided. | 152 # Check that required options have been provided. |
| 148 required_options = ('android_sdk_jar', 'aapt_path', 'configuration_name', | 153 required_options = ('android_sdk_jar', 'aapt_path', 'configuration_name', |
| 149 'android_manifest', 'version_code', 'version_name', | 154 'android_manifest', 'version_code', 'version_name', |
| 150 'apk_path') | 155 'apk_path') |
| 151 | 156 |
| 152 build_utils.CheckOptions(options, parser, required=required_options) | 157 build_utils.CheckOptions(options, parser, required=required_options) |
| 153 | 158 |
| 154 options.resource_zips = build_utils.ParseGnList(options.resource_zips) | 159 options.resource_zips = build_utils.ParseGnList(options.resource_zips) |
| 155 options.language_splits = build_utils.ParseGnList(options.language_splits) | 160 options.language_splits = build_utils.ParseGnList(options.language_splits) |
| 156 options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist) | 161 options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist) |
| 162 options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist) |
| 157 return options | 163 return options |
| 158 | 164 |
| 159 | 165 |
| 160 def _ToAaptLocales(locale_whitelist): | 166 def _ToAaptLocales(locale_whitelist): |
| 161 """Converts the list of Chrome locales to aapt config locales.""" | 167 """Converts the list of Chrome locales to aapt config locales.""" |
| 162 ret = set() | 168 ret = set() |
| 163 for locale in locale_whitelist: | 169 for locale in locale_whitelist: |
| 164 locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale) | 170 locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale) |
| 165 if locale is None or ('-' in locale and '-r' not in locale): | 171 if locale is None or ('-' in locale and '-r' not in locale): |
| 166 raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.' | 172 raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.' |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 | 207 |
| 202 def PackageArgsForExtractedZip(d): | 208 def PackageArgsForExtractedZip(d): |
| 203 """Returns the aapt args for an extracted resources zip. | 209 """Returns the aapt args for an extracted resources zip. |
| 204 | 210 |
| 205 A resources zip either contains the resources for a single target or for | 211 A resources zip either contains the resources for a single target or for |
| 206 multiple targets. If it is multiple targets merged into one, the actual | 212 multiple targets. If it is multiple targets merged into one, the actual |
| 207 resource directories will be contained in the subdirectories 0, 1, 2, ... | 213 resource directories will be contained in the subdirectories 0, 1, 2, ... |
| 208 """ | 214 """ |
| 209 subdirs = [os.path.join(d, s) for s in os.listdir(d)] | 215 subdirs = [os.path.join(d, s) for s in os.listdir(d)] |
| 210 subdirs = [s for s in subdirs if os.path.isdir(s)] | 216 subdirs = [s for s in subdirs if os.path.isdir(s)] |
| 211 is_multi = '0' in [os.path.basename(s) for s in subdirs] | 217 is_multi = any(os.path.basename(s).isdigit() for s in subdirs) |
| 212 if is_multi: | 218 if is_multi: |
| 213 res_dirs = sorted(subdirs, key=lambda p : int(os.path.basename(p))) | 219 res_dirs = sorted(subdirs, key=lambda p : int(os.path.basename(p))) |
| 214 else: | 220 else: |
| 215 res_dirs = [d] | 221 res_dirs = [d] |
| 216 package_command = [] | 222 package_command = [] |
| 217 for d in res_dirs: | 223 for d in res_dirs: |
| 218 MoveImagesToNonMdpiFolders(d) | 224 MoveImagesToNonMdpiFolders(d) |
| 219 package_command += ['-S', d] | 225 package_command += ['-S', d] |
| 220 return package_command | 226 return package_command |
| 221 | 227 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 if 'Debug' in options.configuration_name: | 301 if 'Debug' in options.configuration_name: |
| 296 package_command += ['--debug-mode'] | 302 package_command += ['--debug-mode'] |
| 297 | 303 |
| 298 if options.locale_whitelist: | 304 if options.locale_whitelist: |
| 299 aapt_locales = _ToAaptLocales(options.locale_whitelist) | 305 aapt_locales = _ToAaptLocales(options.locale_whitelist) |
| 300 package_command += ['-c', ','.join(aapt_locales)] | 306 package_command += ['-c', ','.join(aapt_locales)] |
| 301 | 307 |
| 302 return package_command | 308 return package_command |
| 303 | 309 |
| 304 | 310 |
| 311 def _ResourceNameFromPath(path): |
| 312 return os.path.splitext(os.path.basename(path))[0] |
| 313 |
| 314 |
| 315 def _CreateExtractPredicate(dep_zips, exclude_xxxhdpi, xxxhdpi_whitelist): |
| 316 if not exclude_xxxhdpi: |
| 317 # Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways. |
| 318 return lambda path: os.path.basename(path)[0] != '.' |
| 319 |
| 320 # Returns False only for xxxhdpi non-mipmap, non-whitelisted drawables. |
| 321 naive_predicate = lambda path: ( |
| 322 not re.search(r'[/-]xxxhdpi[/-]', path) or |
| 323 re.search(r'[/-]mipmap[/-]', path) or |
| 324 build_utils.MatchesGlob(path, xxxhdpi_whitelist)) |
| 325 |
| 326 # Build a set of all non-xxxhdpi drawables to ensure that we never exclude any |
| 327 # xxxhdpi drawable that does not exist in other densities. |
| 328 non_xxxhdpi_drawables = set() |
| 329 for resource_zip_path in dep_zips: |
| 330 with zipfile.ZipFile(resource_zip_path) as zip_file: |
| 331 for path in zip_file.namelist(): |
| 332 if re.search(r'[/-]drawable[/-]', path) and naive_predicate(path): |
| 333 non_xxxhdpi_drawables.add(_ResourceNameFromPath(path)) |
| 334 |
| 335 return lambda path: (naive_predicate(path) or |
| 336 _ResourceNameFromPath(path) not in non_xxxhdpi_drawables) |
| 337 |
| 338 |
| 305 def _OnStaleMd5(package_command, options): | 339 def _OnStaleMd5(package_command, options): |
| 306 with build_utils.TempDir() as temp_dir: | 340 with build_utils.TempDir() as temp_dir: |
| 307 if options.resource_zips: | 341 if options.resource_zips: |
| 308 dep_zips = options.resource_zips | 342 dep_zips = options.resource_zips |
| 343 extract_predicate = _CreateExtractPredicate( |
| 344 dep_zips, options.exclude_xxxhdpi, options.xxxhdpi_whitelist) |
| 309 for z in dep_zips: | 345 for z in dep_zips: |
| 310 subdir = os.path.join(temp_dir, os.path.basename(z)) | 346 subdir = os.path.join(temp_dir, os.path.basename(z)) |
| 311 if os.path.exists(subdir): | 347 if os.path.exists(subdir): |
| 312 raise Exception('Resource zip name conflict: ' + os.path.basename(z)) | 348 raise Exception('Resource zip name conflict: ' + os.path.basename(z)) |
| 313 build_utils.ExtractAll(z, path=subdir) | 349 if build_utils.ExtractAll(z, path=subdir, predicate=extract_predicate): |
| 314 package_command += PackageArgsForExtractedZip(subdir) | 350 package_command += PackageArgsForExtractedZip(subdir) |
| 315 | 351 |
| 316 build_utils.CheckOutput( | 352 build_utils.CheckOutput( |
| 317 package_command, print_stdout=False, print_stderr=False) | 353 package_command, print_stdout=False, print_stderr=False) |
| 318 | 354 |
| 319 if options.create_density_splits or options.language_splits: | 355 if options.create_density_splits or options.language_splits: |
| 320 CheckForMissedConfigs(options.apk_path, options.create_density_splits, | 356 CheckForMissedConfigs(options.apk_path, options.create_density_splits, |
| 321 options.language_splits) | 357 options.language_splits) |
| 322 | 358 |
| 323 if options.create_density_splits: | 359 if options.create_density_splits: |
| 324 RenameDensitySplits(options.apk_path) | 360 RenameDensitySplits(options.apk_path) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 build_utils.CallAndWriteDepfileIfStale( | 394 build_utils.CallAndWriteDepfileIfStale( |
| 359 lambda: _OnStaleMd5(package_command, options), | 395 lambda: _OnStaleMd5(package_command, options), |
| 360 options, | 396 options, |
| 361 input_paths=input_paths, | 397 input_paths=input_paths, |
| 362 input_strings=input_strings, | 398 input_strings=input_strings, |
| 363 output_paths=output_paths) | 399 output_paths=output_paths) |
| 364 | 400 |
| 365 | 401 |
| 366 if __name__ == '__main__': | 402 if __name__ == '__main__': |
| 367 main(sys.argv[1:]) | 403 main(sys.argv[1:]) |
| OLD | NEW |