#!/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([
    # 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('--static-library-version',
                          help='Version code for static library.')
  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(
      '--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')

  if options.static_library_version and (options.static_library_version !=
                                         options.version_code):
    assert options.static_library_version == options.version_code, (
        f'static_library_version={options.static_library_version} must equal '
        f'version_code={options.version_code}. Please verify the version code '
        'map for this target is defined correctly.')

  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):
      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',
      '--no-xml-namespaces',
      '--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.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 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.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:])
