#!/usr/bin/env python3
#
# Copyright 2012 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Compile Android resources into an intermediate APK.

This can also generate an R.txt, and an .srcjar file containing the proper
final R.java class for all resource packages the APK depends on.

This will crunch images with aapt2.
"""

import argparse
import collections
import contextlib
import filecmp
import hashlib
import logging
import os
import pathlib
import re
import shutil
import subprocess
import sys
import textwrap
from xml.etree import ElementTree

from util import build_utils
from util import diff_utils
from util import manifest_utils
from util import parallel
from util import protoresources
from util import resource_utils
import action_helpers  # build_utils adds //build to sys.path.
import zip_helpers


# Pngs that we shouldn't convert to webp. Please add rationale when updating.
_PNG_WEBP_EXCLUSION_PATTERN = re.compile('|'.join([
    # Crashes on Galaxy S5 running L (https://crbug.com/807059).
    r'.*star_gray\.png',
    # Android requires pngs for 9-patch images.
    r'.*\.9\.png',
    # Daydream requires pngs for icon files.
    r'.*daydream_icon_.*\.png'
]))


def _ParseArgs(args):
  """Parses command line options.

  Returns:
    An options object as from argparse.ArgumentParser.parse_args()
  """
  parser = argparse.ArgumentParser(description=__doc__)

  input_opts = parser.add_argument_group('Input options')
  output_opts = parser.add_argument_group('Output options')

  input_opts.add_argument('--include-resources',
                          action='append',
                          required=True,
                          help='Paths to arsc resource files used to link '
                          'against. Can be specified multiple times.')
  input_opts.add_argument(
      '--dependencies-res-zips',
      default=[],
      help='Resources zip archives from dependents. Required to '
      'resolve @type/foo references into dependent libraries.')
  input_opts.add_argument(
      '--extra-res-packages',
      help='Additional package names to generate R.java files for.')
  input_opts.add_argument(
      '--aapt2-path', required=True, help='Path to the Android aapt2 tool.')
  input_opts.add_argument(
      '--android-manifest', required=True, help='AndroidManifest.xml path.')
  input_opts.add_argument(
      '--r-java-root-package-name',
      default='base',
      help='Short package name for this target\'s root R java file (ex. '
      'input of "base" would become gen.base_module). Defaults to "base".')
  group = input_opts.add_mutually_exclusive_group()
  group.add_argument(
      '--shared-resources',
      action='store_true',
      help='Make all resources in R.java non-final and allow the resource IDs '
      'to be reset to a different package index when the apk is loaded by '
      'another application at runtime.')
  group.add_argument(
      '--app-as-shared-lib',
      action='store_true',
      help='Same as --shared-resources, but also ensures all resource IDs are '
      'directly usable from the APK loaded as an application.')
  input_opts.add_argument(
      '--package-id',
      type=int,
      help='Decimal integer representing custom package ID for resources '
      '(instead of 127==0x7f). Cannot be used with --shared-resources.')
  input_opts.add_argument(
      '--package-name',
      help='Package name that will be used to create R class.')
  input_opts.add_argument(
      '--rename-manifest-package', help='Package name to force AAPT to use.')
  input_opts.add_argument(
      '--arsc-package-name',
      help='Package name to set in manifest of resources.arsc file. This is '
      'only used for apks under test.')
  input_opts.add_argument(
      '--shared-resources-allowlist',
      help='An R.txt file acting as a allowlist for resources that should be '
      'non-final and have their package ID changed at runtime in R.java. '
      'Implies and overrides --shared-resources.')
  input_opts.add_argument(
      '--shared-resources-allowlist-locales',
      default='[]',
      help='Optional GN-list of locales. If provided, all strings corresponding'
      ' to this locale list will be kept in the final output for the '
      'resources identified through --shared-resources-allowlist, even '
      'if --locale-allowlist is being used.')
  input_opts.add_argument(
      '--use-resource-ids-path',
      help='Use resource IDs generated by aapt --emit-ids.')
  input_opts.add_argument(
      '--debuggable',
      action='store_true',
      help='Whether to add android:debuggable="true".')
  input_opts.add_argument('--version-code', help='Version code for apk.')
  input_opts.add_argument('--version-name', help='Version name for apk.')
  input_opts.add_argument(
      '--min-sdk-version', required=True, help='android:minSdkVersion for APK.')
  input_opts.add_argument(
      '--target-sdk-version',
      required=True,
      help="android:targetSdkVersion for APK.")
  input_opts.add_argument(
      '--max-sdk-version',
      help="android:maxSdkVersion expected in AndroidManifest.xml.")
  input_opts.add_argument(
      '--manifest-package', help='Package name of the AndroidManifest.xml.')
  input_opts.add_argument(
      '--locale-allowlist',
      default='[]',
      help='GN list of languages to include. All other language configs will '
      'be stripped out. List may include a combination of Android locales '
      'or Chrome locales.')
  input_opts.add_argument(
      '--resource-exclusion-regex',
      default='',
      help='File-based filter for resources (applied before compiling)')
  input_opts.add_argument(
      '--resource-exclusion-exceptions',
      default='[]',
      help='GN list of globs that say which files to include even '
      'when --resource-exclusion-regex is set.')
  input_opts.add_argument(
      '--dependencies-res-zip-overlays',
      help='GN list with subset of --dependencies-res-zips to use overlay '
      'semantics for.')
  input_opts.add_argument(
      '--values-filter-rules',
      help='GN list of source_glob:regex for filtering resources after they '
      'are compiled. Use this to filter out entries within values/ files.')
  input_opts.add_argument('--png-to-webp', action='store_true',
                          help='Convert png files to webp format.')

  input_opts.add_argument('--webp-binary', default='',
                          help='Path to the cwebp binary.')
  input_opts.add_argument(
      '--webp-cache-dir', help='The directory to store webp image cache.')
  input_opts.add_argument(
      '--is-bundle-module',
      action='store_true',
      help='Whether resources are being generated for a bundle module.')
  input_opts.add_argument(
      '--uses-split',
      help='Value to set uses-split to in the AndroidManifest.xml.')
  input_opts.add_argument(
      '--verification-version-code-offset',
      help='Subtract this from versionCode for expectation files')
  input_opts.add_argument(
      '--verification-library-version-offset',
      help='Subtract this from static-library version for expectation files')

  action_helpers.add_depfile_arg(output_opts)
  output_opts.add_argument('--arsc-path', help='Apk output for arsc format.')
  output_opts.add_argument('--proto-path', help='Apk output for proto format.')
  output_opts.add_argument(
      '--info-path', help='Path to output info file for the partial apk.')
  output_opts.add_argument(
      '--srcjar-out',
      help='Path to srcjar to contain generated R.java.')
  output_opts.add_argument('--r-text-out',
                           help='Path to store the generated R.txt file.')
  output_opts.add_argument(
      '--proguard-file', help='Path to proguard.txt generated file.')
  output_opts.add_argument(
      '--proguard-file-main-dex',
      help='Path to proguard.txt generated file for main dex.')
  output_opts.add_argument(
      '--emit-ids-out', help='Path to file produced by aapt2 --emit-ids.')

  diff_utils.AddCommandLineFlags(parser)
  options = parser.parse_args(args)

  options.include_resources = action_helpers.parse_gn_list(
      options.include_resources)
  options.dependencies_res_zips = action_helpers.parse_gn_list(
      options.dependencies_res_zips)
  options.extra_res_packages = action_helpers.parse_gn_list(
      options.extra_res_packages)
  options.locale_allowlist = action_helpers.parse_gn_list(
      options.locale_allowlist)
  options.shared_resources_allowlist_locales = action_helpers.parse_gn_list(
      options.shared_resources_allowlist_locales)
  options.resource_exclusion_exceptions = action_helpers.parse_gn_list(
      options.resource_exclusion_exceptions)
  options.dependencies_res_zip_overlays = action_helpers.parse_gn_list(
      options.dependencies_res_zip_overlays)
  options.values_filter_rules = action_helpers.parse_gn_list(
      options.values_filter_rules)

  if not options.arsc_path and not options.proto_path:
    parser.error('One of --arsc-path or --proto-path is required.')

  if options.package_id and options.shared_resources:
    parser.error('--package-id and --shared-resources are mutually exclusive')

  return options


def _IterFiles(root_dir):
  for root, _, files in os.walk(root_dir):
    for f in files:
      yield os.path.join(root, f)


def _RenameLocaleResourceDirs(resource_dirs, path_info):
  """Rename locale resource directories into standard names when necessary.

  This is necessary to deal with the fact that older Android releases only
  support ISO 639-1 two-letter codes, and sometimes even obsolete versions
  of them.

  In practice it means:
    * 3-letter ISO 639-2 qualifiers are renamed under a corresponding
      2-letter one. E.g. for Filipino, strings under values-fil/ will be moved
      to a new corresponding values-tl/ sub-directory.

    * Modern ISO 639-1 codes will be renamed to their obsolete variant
      for Indonesian, Hebrew and Yiddish (e.g. 'values-in/ -> values-id/).

    * Norwegian macrolanguage strings will be renamed to Bokmal (main
      Norway language). See http://crbug.com/920960. In practice this
      means that 'values-no/ -> values-nb/' unless 'values-nb/' already
      exists.

    * BCP 47 langauge tags will be renamed to an equivalent ISO 639-1
      locale qualifier if possible (e.g. 'values-b+en+US/ -> values-en-rUS').

  Args:
    resource_dirs: list of top-level resource directories.
  """
  for resource_dir in resource_dirs:
    ignore_dirs = {}
    for path in _IterFiles(resource_dir):
      locale = resource_utils.FindLocaleInStringResourceFilePath(path)
      if not locale:
        continue
      cr_locale = resource_utils.ToChromiumLocaleName(locale)
      if not cr_locale:
        continue  # Unsupported Android locale qualifier!?
      locale2 = resource_utils.ToAndroidLocaleName(cr_locale)
      if locale != locale2:
        path2 = path.replace('/values-%s/' % locale, '/values-%s/' % locale2)
        if path == path2:
          raise Exception('Could not substitute locale %s for %s in %s' %
                          (locale, locale2, path))

        # Ignore rather than rename when the destination resources config
        # already exists.
        # e.g. some libraries provide both values-nb/ and values-no/.
        # e.g. material design provides:
        # * res/values-rUS/values-rUS.xml
        # * res/values-b+es+419/values-b+es+419.xml
        config_dir = os.path.dirname(path2)
        already_has_renamed_config = ignore_dirs.get(config_dir)
        if already_has_renamed_config is None:
          # Cache the result of the first time the directory is encountered
          # since subsequent encounters will find the directory already exists
          # (due to the rename).
          already_has_renamed_config = os.path.exists(config_dir)
          ignore_dirs[config_dir] = already_has_renamed_config
        if already_has_renamed_config:
          continue

        build_utils.MakeDirectory(os.path.dirname(path2))
        shutil.move(path, path2)
        path_info.RegisterRename(
            os.path.relpath(path, resource_dir),
            os.path.relpath(path2, resource_dir))


def _ToAndroidLocales(locale_allowlist):
  """Converts the list of Chrome locales to Android config locale qualifiers.

  Args:
    locale_allowlist: A list of Chromium locale names.
  Returns:
    A set of matching Android config locale qualifier names.
  """
  ret = set()
  for locale in locale_allowlist:
    locale = resource_utils.ToAndroidLocaleName(locale)
    if locale is None or ('-' in locale and '-r' not in locale):
      raise Exception('Unsupported Chromium locale name: %s' % locale)
    ret.add(locale)
    # Always keep non-regional fall-backs.
    language = locale.split('-')[0]
    ret.add(language)

  return ret


def _MoveImagesToNonMdpiFolders(res_root, path_info):
  """Move images from drawable-*-mdpi-* folders to drawable-* folders.

  Why? http://crbug.com/289843
  """
  for src_dir_name in os.listdir(res_root):
    src_components = src_dir_name.split('-')
    if src_components[0] != 'drawable' or 'mdpi' not in src_components:
      continue
    src_dir = os.path.join(res_root, src_dir_name)
    if not os.path.isdir(src_dir):
      continue
    dst_components = [c for c in src_components if c != 'mdpi']
    assert dst_components != src_components
    dst_dir_name = '-'.join(dst_components)
    dst_dir = os.path.join(res_root, dst_dir_name)
    build_utils.MakeDirectory(dst_dir)
    for src_file_name in os.listdir(src_dir):
      if not os.path.splitext(src_file_name)[1] in ('.png', '.webp', ''):
        continue
      src_file = os.path.join(src_dir, src_file_name)
      dst_file = os.path.join(dst_dir, src_file_name)
      assert not os.path.lexists(dst_file)
      shutil.move(src_file, dst_file)
      path_info.RegisterRename(
          os.path.relpath(src_file, res_root),
          os.path.relpath(dst_file, res_root))


def _DeterminePlatformVersion(aapt2_path, jar_candidates):
  def maybe_extract_version(j):
    try:
      return resource_utils.ExtractBinaryManifestValues(aapt2_path, j)
    except build_utils.CalledProcessError:
      return None

  def is_sdk_jar(jar_name):
    if jar_name in ('android.jar', 'android_system.jar'):
      return True
    # Robolectric jar looks a bit different.
    return 'android-all' in jar_name and 'robolectric' in jar_name

  android_sdk_jars = [
      j for j in jar_candidates if is_sdk_jar(os.path.basename(j))
  ]
  extract_all = [maybe_extract_version(j) for j in android_sdk_jars]
  extract_all = [x for x in extract_all if x]
  if len(extract_all) == 0:
    raise Exception(
        'Unable to find android SDK jar among candidates: %s'
            % ', '.join(android_sdk_jars))
  if len(extract_all) > 1:
    raise Exception(
        'Found multiple android SDK jars among candidates: %s'
            % ', '.join(android_sdk_jars))
  platform_version_code, platform_version_name = extract_all.pop()[:2]
  return platform_version_code, platform_version_name


def _FixManifest(options, temp_dir):
  """Fix the APK's AndroidManifest.xml.

  This adds any missing namespaces for 'android' and 'tools', and
  sets certains elements like 'platformBuildVersionCode' or
  'android:debuggable' depending on the content of |options|.

  Args:
    options: The command-line arguments tuple.
    temp_dir: A temporary directory where the fixed manifest will be written to.
  Returns:
    Tuple of:
     * Manifest path within |temp_dir|.
     * Original package_name.
     * Manifest package name.
  """
  doc, manifest_node, app_node = manifest_utils.ParseManifest(
      options.android_manifest)

  # merge_manifest.py also sets package & <uses-sdk>. We may want to ensure
  # manifest merger is always enabled and remove these command-line arguments.
  manifest_utils.SetUsesSdk(manifest_node, options.target_sdk_version,
                            options.min_sdk_version, options.max_sdk_version)
  orig_package = manifest_node.get('package') or options.manifest_package
  fixed_package = (options.arsc_package_name or options.manifest_package
                   or orig_package)
  manifest_node.set('package', fixed_package)

  platform_version_code, platform_version_name = _DeterminePlatformVersion(
      options.aapt2_path, options.include_resources)
  manifest_node.set('platformBuildVersionCode', platform_version_code)
  manifest_node.set('platformBuildVersionName', platform_version_name)
  if options.version_code:
    manifest_utils.NamespacedSet(manifest_node, 'versionCode',
                                 options.version_code)
  if options.version_name:
    manifest_utils.NamespacedSet(manifest_node, 'versionName',
                                 options.version_name)
  if options.debuggable:
    manifest_utils.NamespacedSet(app_node, 'debuggable', 'true')

  if options.uses_split:
    uses_split = ElementTree.SubElement(manifest_node, 'uses-split')
    manifest_utils.NamespacedSet(uses_split, 'name', options.uses_split)

  # Make sure the min-sdk condition is not less than the min-sdk of the bundle.
  for min_sdk_node in manifest_node.iter('{%s}min-sdk' %
                                         manifest_utils.DIST_NAMESPACE):
    dist_value = '{%s}value' % manifest_utils.DIST_NAMESPACE
    if int(min_sdk_node.get(dist_value)) < int(options.min_sdk_version):
      min_sdk_node.set(dist_value, options.min_sdk_version)

  debug_manifest_path = os.path.join(temp_dir, 'AndroidManifest.xml')
  manifest_utils.SaveManifest(doc, debug_manifest_path)
  return debug_manifest_path, orig_package, fixed_package


def _CreateKeepPredicate(resource_exclusion_regex,
                         resource_exclusion_exceptions):
  """Return a predicate lambda to determine which resource files to keep.

  Args:
    resource_exclusion_regex: A regular expression describing all resources
      to exclude, except if they are mip-maps, or if they are listed
      in |resource_exclusion_exceptions|.
    resource_exclusion_exceptions: A list of glob patterns corresponding
      to exceptions to the |resource_exclusion_regex|.
  Returns:
    A lambda that takes a path, and returns true if the corresponding file
    must be kept.
  """
  predicate = lambda path: os.path.basename(path)[0] != '.'
  if resource_exclusion_regex == '':
    # Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways.
    return predicate

  # A simple predicate that only removes (returns False for) paths covered by
  # the exclusion regex or listed as exceptions.
  return lambda path: (
      not re.search(resource_exclusion_regex, path) or
      build_utils.MatchesGlob(path, resource_exclusion_exceptions))


def _ComputeSha1(path):
  with open(path, 'rb') as f:
    data = f.read()
  return hashlib.sha1(data).hexdigest()


def _ConvertToWebPSingle(png_path, cwebp_binary, cwebp_version, webp_cache_dir):
  sha1_hash = _ComputeSha1(png_path)

  # The set of arguments that will appear in the cache key.
  quality_args = ['-m', '6', '-q', '100', '-lossless']

  webp_cache_path = os.path.join(
      webp_cache_dir, '{}-{}-{}'.format(sha1_hash, cwebp_version,
                                        ''.join(quality_args)))
  # No need to add .webp. Android can load images fine without them.
  webp_path = os.path.splitext(png_path)[0]

  cache_hit = os.path.exists(webp_cache_path)
  if cache_hit:
    os.link(webp_cache_path, webp_path)
  else:
    # We place the generated webp image to webp_path, instead of in the
    # webp_cache_dir to avoid concurrency issues.
    args = [cwebp_binary, png_path, '-o', webp_path, '-quiet'] + quality_args
    subprocess.check_call(args)

    try:
      os.link(webp_path, webp_cache_path)
    except OSError:
      # Because of concurrent run, a webp image may already exists in
      # webp_cache_path.
      pass

  os.remove(png_path)
  original_dir = os.path.dirname(os.path.dirname(png_path))
  rename_tuple = (os.path.relpath(png_path, original_dir),
                  os.path.relpath(webp_path, original_dir))
  return rename_tuple, cache_hit


def _ConvertToWebP(cwebp_binary, png_paths, path_info, webp_cache_dir):
  cwebp_version = subprocess.check_output([cwebp_binary, '-version']).rstrip()
  shard_args = [(f, ) for f in png_paths
                if not _PNG_WEBP_EXCLUSION_PATTERN.match(f)]

  build_utils.MakeDirectory(webp_cache_dir)
  results = parallel.BulkForkAndCall(_ConvertToWebPSingle,
                                     shard_args,
                                     cwebp_binary=cwebp_binary,
                                     cwebp_version=cwebp_version,
                                     webp_cache_dir=webp_cache_dir)
  total_cache_hits = 0
  for rename_tuple, cache_hit in results:
    path_info.RegisterRename(*rename_tuple)
    total_cache_hits += int(cache_hit)

  logging.debug('png->webp cache: %d/%d', total_cache_hits, len(shard_args))


def _RemoveImageExtensions(directory, path_info):
  """Remove extensions from image files in the passed directory.

  This reduces binary size but does not affect android's ability to load the
  images.
  """
  for f in _IterFiles(directory):
    if (f.endswith('.png') or f.endswith('.webp')) and not f.endswith('.9.png'):
      path_with_extension = f
      path_no_extension = os.path.splitext(path_with_extension)[0]
      if path_no_extension != path_with_extension:
        shutil.move(path_with_extension, path_no_extension)
        path_info.RegisterRename(
            os.path.relpath(path_with_extension, directory),
            os.path.relpath(path_no_extension, directory))


def _CompileSingleDep(index, dep_subdir, keep_predicate, aapt2_path,
                      partials_dir):
  unique_name = '{}_{}'.format(index, os.path.basename(dep_subdir))
  partial_path = os.path.join(partials_dir, '{}.zip'.format(unique_name))

  compile_command = [
      aapt2_path,
      'compile',
      # TODO(wnwen): Turn this on once aapt2 forces 9-patch to be crunched.
      # '--no-crunch',
      '--dir',
      dep_subdir,
      '-o',
      partial_path
  ]

  # There are resources targeting API-versions lower than our minapi. For
  # various reasons it's easier to let aapt2 ignore these than for us to
  # remove them from our build (e.g. it's from a 3rd party library).
  build_utils.CheckOutput(
      compile_command,
      stderr_filter=lambda output: build_utils.FilterLines(
          output, r'ignoring configuration .* for (styleable|attribute)'))

  # Filtering these files is expensive, so only apply filters to the partials
  # that have been explicitly targeted.
  if keep_predicate:
    logging.debug('Applying .arsc filtering to %s', dep_subdir)
    protoresources.StripUnwantedResources(partial_path, keep_predicate)
  return partial_path


def _CreateValuesKeepPredicate(exclusion_rules, dep_subdir):
  patterns = [
      x[1] for x in exclusion_rules
      if build_utils.MatchesGlob(dep_subdir, [x[0]])
  ]
  if not patterns:
    return None

  regexes = [re.compile(p) for p in patterns]
  return lambda x: not any(r.search(x) for r in regexes)


def _CompileDeps(aapt2_path, dep_subdirs, dep_subdir_overlay_set, temp_dir,
                 exclusion_rules):
  partials_dir = os.path.join(temp_dir, 'partials')
  build_utils.MakeDirectory(partials_dir)

  job_params = [(i, dep_subdir,
                 _CreateValuesKeepPredicate(exclusion_rules, dep_subdir))
                for i, dep_subdir in enumerate(dep_subdirs)]

  # Filtering is slow, so ensure jobs with keep_predicate are started first.
  job_params.sort(key=lambda x: not x[2])
  partials = list(
      parallel.BulkForkAndCall(_CompileSingleDep,
                               job_params,
                               aapt2_path=aapt2_path,
                               partials_dir=partials_dir))

  partials_cmd = list()
  for i, partial in enumerate(partials):
    dep_subdir = job_params[i][1]
    if dep_subdir in dep_subdir_overlay_set:
      partials_cmd += ['-R']
    partials_cmd += [partial]
  return partials_cmd


def _CreateResourceInfoFile(path_info, info_path, dependencies_res_zips):
  for zip_file in dependencies_res_zips:
    zip_info_file_path = zip_file + '.info'
    if os.path.exists(zip_info_file_path):
      path_info.MergeInfoFile(zip_info_file_path)
  path_info.Write(info_path)


def _RemoveUnwantedLocalizedStrings(dep_subdirs, options):
  """Remove localized strings that should not go into the final output.

  Args:
    dep_subdirs: List of resource dependency directories.
    options: Command-line options namespace.
  """
  # Collect locale and file paths from the existing subdirs.
  # The following variable maps Android locale names to
  # sets of corresponding xml file paths.
  locale_to_files_map = collections.defaultdict(set)
  for directory in dep_subdirs:
    for f in _IterFiles(directory):
      locale = resource_utils.FindLocaleInStringResourceFilePath(f)
      if locale:
        locale_to_files_map[locale].add(f)

  all_locales = set(locale_to_files_map)

  # Set A: wanted locales, either all of them or the
  # list provided by --locale-allowlist.
  wanted_locales = all_locales
  if options.locale_allowlist:
    wanted_locales = _ToAndroidLocales(options.locale_allowlist)

  # Set B: shared resources locales, which is either set A
  # or the list provided by --shared-resources-allowlist-locales
  shared_resources_locales = wanted_locales
  shared_names_allowlist = set()
  if options.shared_resources_allowlist_locales:
    shared_names_allowlist = set(
        resource_utils.GetRTxtStringResourceNames(
            options.shared_resources_allowlist))

    shared_resources_locales = _ToAndroidLocales(
        options.shared_resources_allowlist_locales)

  # Remove any file that belongs to a locale not covered by
  # either A or B.
  removable_locales = (all_locales - wanted_locales - shared_resources_locales)
  for locale in removable_locales:
    for path in locale_to_files_map[locale]:
      os.remove(path)

  # For any locale in B but not in A, only keep the shared
  # resource strings in each file.
  for locale in shared_resources_locales - wanted_locales:
    for path in locale_to_files_map[locale]:
      resource_utils.FilterAndroidResourceStringsXml(
          path, lambda x: x in shared_names_allowlist)

  # For any locale in A but not in B, only keep the strings
  # that are _not_ from shared resources in the file.
  for locale in wanted_locales - shared_resources_locales:
    for path in locale_to_files_map[locale]:
      resource_utils.FilterAndroidResourceStringsXml(
          path, lambda x: x not in shared_names_allowlist)


def _FilterResourceFiles(dep_subdirs, keep_predicate):
  # Create a function that selects which resource files should be packaged
  # into the final output. Any file that does not pass the predicate will
  # be removed below.
  png_paths = []
  for directory in dep_subdirs:
    for f in _IterFiles(directory):
      if not keep_predicate(f):
        os.remove(f)
      elif f.endswith('.png'):
        png_paths.append(f)

  return png_paths


def _PackageApk(options, build):
  """Compile and link resources with aapt2.

  Args:
    options: The command-line options.
    build: BuildContext object.
  Returns:
    The manifest package name for the APK.
  """
  logging.debug('Extracting resource .zips')
  dep_subdirs = []
  dep_subdir_overlay_set = set()
  for dependency_res_zip in options.dependencies_res_zips:
    extracted_dep_subdirs = resource_utils.ExtractDeps([dependency_res_zip],
                                                       build.deps_dir)
    dep_subdirs += extracted_dep_subdirs
    if dependency_res_zip in options.dependencies_res_zip_overlays:
      dep_subdir_overlay_set.update(extracted_dep_subdirs)

  logging.debug('Applying locale transformations')
  path_info = resource_utils.ResourceInfoFile()
  _RenameLocaleResourceDirs(dep_subdirs, path_info)

  logging.debug('Applying file-based exclusions')
  keep_predicate = _CreateKeepPredicate(options.resource_exclusion_regex,
                                        options.resource_exclusion_exceptions)
  png_paths = _FilterResourceFiles(dep_subdirs, keep_predicate)

  if options.locale_allowlist or options.shared_resources_allowlist_locales:
    logging.debug('Applying locale-based string exclusions')
    _RemoveUnwantedLocalizedStrings(dep_subdirs, options)

  if png_paths and options.png_to_webp:
    logging.debug('Converting png->webp')
    _ConvertToWebP(options.webp_binary, png_paths, path_info,
                   options.webp_cache_dir)
  logging.debug('Applying drawable transformations')
  for directory in dep_subdirs:
    _MoveImagesToNonMdpiFolders(directory, path_info)
    _RemoveImageExtensions(directory, path_info)

  logging.debug('Running aapt2 compile')
  exclusion_rules = [x.split(':', 1) for x in options.values_filter_rules]
  partials = _CompileDeps(options.aapt2_path, dep_subdirs,
                          dep_subdir_overlay_set, build.temp_dir,
                          exclusion_rules)

  link_command = [
      options.aapt2_path,
      'link',
      '--auto-add-overlay',
      '--no-version-vectors',
      '--output-text-symbols',
      build.r_txt_path,
  ]

  for j in options.include_resources:
    link_command += ['-I', j]
  if options.proguard_file:
    link_command += ['--proguard', build.proguard_path]
    link_command += ['--proguard-minimal-keep-rules']
  if options.proguard_file_main_dex:
    link_command += ['--proguard-main-dex', build.proguard_main_dex_path]
  if options.emit_ids_out:
    link_command += ['--emit-ids', build.emit_ids_path]

  # Note: only one of --proto-format, --shared-lib or --app-as-shared-lib
  #       can be used with recent versions of aapt2.
  if options.shared_resources:
    link_command.append('--shared-lib')

  if int(options.min_sdk_version) > 21:
    link_command.append('--no-xml-namespaces')

  if options.package_id:
    link_command += [
        '--package-id',
        '0x%02x' % options.package_id,
        '--allow-reserved-package-id',
    ]

  fixed_manifest, desired_manifest_package_name, fixed_manifest_package = (
      _FixManifest(options, build.temp_dir))
  if options.rename_manifest_package:
    desired_manifest_package_name = options.rename_manifest_package

  link_command += [
      '--manifest', fixed_manifest, '--rename-manifest-package',
      desired_manifest_package_name
  ]

  if options.package_id is not None:
    package_id = options.package_id
  elif options.shared_resources:
    package_id = 0
  else:
    package_id = 0x7f
  _CreateStableIdsFile(options.use_resource_ids_path, build.stable_ids_path,
                       fixed_manifest_package, package_id)
  link_command += ['--stable-ids', build.stable_ids_path]

  link_command += partials

  # We always create a binary arsc file first, then convert to proto, so flags
  # such as --shared-lib can be supported.
  link_command += ['-o', build.arsc_path]

  logging.debug('Starting: aapt2 link')
  link_proc = subprocess.Popen(link_command)

  # Create .res.info file in parallel.
  if options.info_path:
    logging.debug('Creating .res.info file')
    _CreateResourceInfoFile(path_info, build.info_path,
                            options.dependencies_res_zips)

  exit_code = link_proc.wait()
  assert exit_code == 0, f'aapt2 link cmd failed with {exit_code=}'
  logging.debug('Finished: aapt2 link')

  if options.shared_resources:
    logging.debug('Resolving styleables in R.txt')
    # Need to resolve references because unused resource removal tool does not
    # support references in R.txt files.
    resource_utils.ResolveStyleableReferences(build.r_txt_path)

  if exit_code:
    raise subprocess.CalledProcessError(exit_code, link_command)

  if options.proguard_file and (options.shared_resources
                                or options.app_as_shared_lib):
    # Make sure the R class associated with the manifest package does not have
    # its onResourcesLoaded method obfuscated or removed, so that the framework
    # can call it in the case where the APK is being loaded as a library.
    with open(build.proguard_path, 'a') as proguard_file:
      keep_rule = '''
                  -keep,allowoptimization class {package}.R {{
                    public static void onResourcesLoaded(int);
                  }}
                  '''.format(package=desired_manifest_package_name)
      proguard_file.write(textwrap.dedent(keep_rule))

  logging.debug('Running aapt2 convert')
  build_utils.CheckOutput([
      options.aapt2_path, 'convert', '--output-format', 'proto', '-o',
      build.proto_path, build.arsc_path
  ])

  # Workaround for b/147674078. This is only needed for WebLayer and does not
  # affect WebView usage, since WebView does not used dynamic attributes.
  if options.shared_resources:
    logging.debug('Hardcoding dynamic attributes')
    protoresources.HardcodeSharedLibraryDynamicAttributes(
        build.proto_path, options.is_bundle_module,
        options.shared_resources_allowlist)

    build_utils.CheckOutput([
        options.aapt2_path, 'convert', '--output-format', 'binary', '-o',
        build.arsc_path, build.proto_path
    ])

  # Sanity check that the created resources have the expected package ID.
  logging.debug('Performing sanity check')
  _, actual_package_id = resource_utils.ExtractArscPackage(
      options.aapt2_path,
      build.arsc_path if options.arsc_path else build.proto_path)
  # When there are no resources, ExtractArscPackage returns (None, None), in
  # this case there is no need to check for matching package ID.
  if actual_package_id is not None and actual_package_id != package_id:
    raise Exception('Invalid package ID 0x%x (expected 0x%x)' %
                    (actual_package_id, package_id))

  return desired_manifest_package_name


def _CreateStableIdsFile(in_path, out_path, package_name, package_id):
  """Transforms a file generated by --emit-ids from another package.

  --stable-ids is generally meant to be used by different versions of the same
  package. To make it work for other packages, we need to transform the package
  name references to match the package that resources are being generated for.
  """
  if in_path:
    data = pathlib.Path(in_path).read_text()
  else:
    # Force IDs to use 0x01 for the type byte in order to ensure they are
    # different from IDs generated by other apps. https://crbug.com/1293336
    data = 'pkg:id/fake_resource_id = 0x7f010000\n'
  # Replace "pkg:" with correct package name.
  data = re.sub(r'^.*?:', package_name + ':', data, flags=re.MULTILINE)
  # Replace "0x7f" with correct package id.
  data = re.sub(r'0x..', '0x%02x' % package_id, data)
  pathlib.Path(out_path).write_text(data)


def _WriteOutputs(options, build):
  possible_outputs = [
      (options.srcjar_out, build.srcjar_path),
      (options.r_text_out, build.r_txt_path),
      (options.arsc_path, build.arsc_path),
      (options.proto_path, build.proto_path),
      (options.proguard_file, build.proguard_path),
      (options.proguard_file_main_dex, build.proguard_main_dex_path),
      (options.emit_ids_out, build.emit_ids_path),
      (options.info_path, build.info_path),
  ]

  for final, temp in possible_outputs:
    # Write file only if it's changed.
    if final and not (os.path.exists(final) and filecmp.cmp(final, temp)):
      shutil.move(temp, final)


def _CreateNormalizedManifestForVerification(options):
  with build_utils.TempDir() as tempdir:
    fixed_manifest, _, _ = _FixManifest(options, tempdir)
    with open(fixed_manifest) as f:
      return manifest_utils.NormalizeManifest(
          f.read(), options.verification_version_code_offset,
          options.verification_library_version_offset)


def main(args):
  build_utils.InitLogging('RESOURCE_DEBUG')
  args = build_utils.ExpandFileArgs(args)
  options = _ParseArgs(args)

  if options.expected_file:
    actual_data = _CreateNormalizedManifestForVerification(options)
    diff_utils.CheckExpectations(actual_data, options)
    if options.only_verify_expectations:
      return

  path = options.arsc_path or options.proto_path
  debug_temp_resources_dir = os.environ.get('TEMP_RESOURCES_DIR')
  if debug_temp_resources_dir:
    path = os.path.join(debug_temp_resources_dir, os.path.basename(path))
  else:
    # Use a deterministic temp directory since .pb files embed the absolute
    # path of resources: crbug.com/939984
    path = path + '.tmpdir'
  build_utils.DeleteDirectory(path)

  with resource_utils.BuildContext(
      temp_dir=path, keep_files=bool(debug_temp_resources_dir)) as build:

    manifest_package_name = _PackageApk(options, build)

    # If --shared-resources-allowlist is used, all the resources listed in the
    # corresponding R.txt file will be non-final, and an onResourcesLoaded()
    # will be generated to adjust them at runtime.
    #
    # Otherwise, if --shared-resources is used, the all resources will be
    # non-final, and an onResourcesLoaded() method will be generated too.
    #
    # Otherwise, all resources will be final, and no method will be generated.
    #
    rjava_build_options = resource_utils.RJavaBuildOptions()
    if options.shared_resources_allowlist:
      rjava_build_options.ExportSomeResources(
          options.shared_resources_allowlist)
      rjava_build_options.GenerateOnResourcesLoaded()
      if options.shared_resources:
        # The final resources will only be used in WebLayer, so hardcode the
        # package ID to be what WebLayer expects.
        rjava_build_options.SetFinalPackageId(
            protoresources.SHARED_LIBRARY_HARDCODED_ID)
    elif options.shared_resources or options.app_as_shared_lib:
      rjava_build_options.ExportAllResources()
      rjava_build_options.GenerateOnResourcesLoaded()

    custom_root_package_name = options.r_java_root_package_name
    grandparent_custom_package_name = None

    # Always generate an R.java file for the package listed in
    # AndroidManifest.xml because this is where Android framework looks to find
    # onResourcesLoaded() for shared library apks. While not actually necessary
    # for application apks, it also doesn't hurt.
    apk_package_name = manifest_package_name

    if options.package_name and not options.arsc_package_name:
      # Feature modules have their own custom root package name and should
      # inherit from the appropriate base module package. This behaviour should
      # not be present for test apks with an apk under test. Thus,
      # arsc_package_name is used as it is only defined for test apks with an
      # apk under test.
      custom_root_package_name = options.package_name
      grandparent_custom_package_name = options.r_java_root_package_name
      # Feature modules have the same manifest package as the base module but
      # they should not create an R.java for said manifest package because it
      # will be created in the base module.
      apk_package_name = None

    if options.srcjar_out:
      logging.debug('Creating R.srcjar')
      resource_utils.CreateRJavaFiles(build.srcjar_dir, apk_package_name,
                                      build.r_txt_path,
                                      options.extra_res_packages,
                                      rjava_build_options, options.srcjar_out,
                                      custom_root_package_name,
                                      grandparent_custom_package_name)
      with action_helpers.atomic_output(build.srcjar_path) as f:
        zip_helpers.zip_directory(f, build.srcjar_dir)

    logging.debug('Copying outputs')
    _WriteOutputs(options, build)

  if options.depfile:
    assert options.srcjar_out, 'Update first output below and remove assert.'
    depfile_deps = (options.dependencies_res_zips +
                    options.dependencies_res_zip_overlays +
                    options.include_resources)
    action_helpers.write_depfile(options.depfile, options.srcjar_out,
                                 depfile_deps)


if __name__ == '__main__':
  main(sys.argv[1:])
