Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  rules.gni   Sprache: unbekannt

 
Spracherkennung für: .gni vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Do not add any imports to non-//build directories here.
# Some projects (e.g. V8) do not have non-build directories DEPS'ed in.

import("//chromium/build/config/android/channel.gni")
import("//chromium/build/config/android/config.gni")
import("//chromium/build/config/android/internal_rules.gni")
import("//chromium/build/config/clang/clang.gni")
import("//chromium/build/config/compiler/compiler.gni")
import("//chromium/build/config/coverage/coverage.gni")
import("//chromium/build/config/python.gni")
import("//chromium/build/config/rts.gni")
import("//chromium/build/config/zip.gni")
import("//chromium/build/toolchain/toolchain.gni")

assert(is_android)

declare_args() {
  enable_jni_tracing = false
}

if (target_cpu == "arm") {
  _sanitizer_arch = "arm"
} else if (target_cpu == "arm64") {
  _sanitizer_arch = "aarch64"
} else if (target_cpu == "x86") {
  _sanitizer_arch = "i686"
}

_sanitizer_runtimes = []
if (use_cfi_diag || is_ubsan || is_ubsan_security || is_ubsan_vptr) {
  _sanitizer_runtimes = [ "$clang_base_path/lib/clang/$clang_version/lib/linux/libclang_rt.ubsan_standalone-$_sanitizer_arch-android.so" ]
}

# Creates a dist directory for a native executable.
#
# Running a native executable on a device requires all the shared library
# dependencies of that executable. To make it easier to install and run such an
# executable, this will create a directory containing the native exe and all
# it's library dependencies.
#
# Note: It's usually better to package things as an APK than as a native
# executable.
#
# Variables
#   dist_dir: Directory for the exe and libraries. Everything in this directory
#     will be deleted before copying in the exe and libraries.
#   binary: Path to (stripped) executable.
#   extra_files: List of extra files to copy in (optional).
#
# Example
#   create_native_executable_dist("foo_dist") {
#     dist_dir = "$root_build_dir/foo_dist"
#     binary = "$root_build_dir/foo"
#     deps = [ ":the_thing_that_makes_foo" ]
#   }
template("create_native_executable_dist") {
  forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

  _libraries_list = "${target_gen_dir}/${target_name}_library_dependencies.list"

  _sanitizer_runtimes_target_name = "${target_name}__sanitizer_runtimes"
  group(_sanitizer_runtimes_target_name) {
    metadata = {
      shared_libraries = _sanitizer_runtimes
    }
  }

  generated_file("${target_name}__library_list") {
    forward_variables_from(invoker, [ "deps" ])
    if (!defined(deps)) {
      deps = []
    }
    deps += [ ":${_sanitizer_runtimes_target_name}" ]
    output_conversion = "json"
    outputs = [ _libraries_list ]
    data_keys = [ "shared_libraries" ]
    walk_keys = [ "shared_libraries_barrier" ]
    rebase = root_build_dir
  }

  copy_ex(target_name) {
    inputs = [
      _libraries_list,
      invoker.binary,
    ]

    dest = invoker.dist_dir
    data = [ "${invoker.dist_dir}/" ]

    _rebased_libraries_list = rebase_path(_libraries_list, root_build_dir)
    _rebased_binaries_list = rebase_path([ invoker.binary ], root_build_dir)
    args = [
      "--clear",
      "--files=@FileArg($_rebased_libraries_list)",
      "--files=$_rebased_binaries_list",
    ]
    if (defined(invoker.extra_files)) {
      _rebased_extra_files = rebase_path(invoker.extra_files, root_build_dir)
      args += [ "--files=$_rebased_extra_files" ]
    }

    _depfile = "$target_gen_dir/$target_name.d"
    _stamp_file = "$target_gen_dir/$target_name.stamp"
    outputs = [ _stamp_file ]
    args += [
      "--depfile",
      rebase_path(_depfile, root_build_dir),
      "--stamp",
      rebase_path(_stamp_file, root_build_dir),
    ]

    deps = [ ":${target_name}__library_list" ]
    if (defined(invoker.deps)) {
      deps += invoker.deps
    }
  }
}

if (enable_java_templates) {
  import("//chromium/build/config/sanitizers/sanitizers.gni")

  # JNI target implementation. See generate_jni or generate_jar_jni for usage.
  template("generate_jni_impl") {
    _jni_output_dir = "${target_gen_dir}/${target_name}"
    if (defined(invoker.jni_generator_include)) {
      _jni_generator_include = invoker.jni_generator_include
      _jni_generator_include_deps = []
    } else {
      _jni_generator_include =
          "//base/android/jni_generator/jni_generator_helper.h"
      _jni_generator_include_deps = [
        # Using //base/android/jni_generator/jni_generator_helper.h introduces
        # a dependency on buildflags targets indirectly through
        # base/android/jni_android.h, which is part of the //base target.
        # This can't depend directly on //base without causing a dependency
        # cycle, though.
        "//base:debugging_buildflags",
        "//base:logging_buildflags",
        "//chromium/build:chromeos_buildflags",
      ]
    }

    action_with_pydeps(target_name) {
      # The sources aren't compiled so don't check their dependencies.
      check_includes = false
      script = "//base/android/jni_generator/jni_generator.py"
      forward_variables_from(invoker,
                             TESTONLY_AND_VISIBILITY + [
                                   "deps",
                                   "public_deps",
                                 ])
      if (!defined(public_deps)) {
        public_deps = []
      }
      public_deps += _jni_generator_include_deps
      inputs = []
      args = [
        "--ptr_type=long",
        "--includes",
        rebase_path(_jni_generator_include, _jni_output_dir),
      ]

      if (defined(invoker.classes)) {
        if (defined(invoker.jar_file)) {
          _jar_file = invoker.jar_file
        } else {
          _jar_file = android_sdk_jar
        }
        inputs += [ _jar_file ]
        args += [
          "--jar_file",
          rebase_path(_jar_file, root_build_dir),
        ]
        _input_args = invoker.classes
        _input_names = invoker.classes
        if (defined(invoker.always_mangle) && invoker.always_mangle) {
          args += [ "--always_mangle" ]
        }
      } else {
        assert(defined(invoker.sources))
        inputs += invoker.sources
        _input_args = rebase_path(invoker.sources, root_build_dir)
        _input_names = invoker.sources
        if (use_hashed_jni_names) {
          args += [ "--use_proxy_hash" ]
        }
        if (defined(invoker.namespace)) {
          args += [ "-n ${invoker.namespace}" ]
        }
      }
      if (defined(invoker.split_name)) {
        args += [ "--split_name=${invoker.split_name}" ]
      }

      outputs = []
      foreach(_name, _input_names) {
        _name_part = get_path_info(_name, "name")
        outputs += [ "${_jni_output_dir}/${_name_part}_jni.h" ]
      }

      # Avoid passing GN lists because not all webrtc embedders use //build.
      foreach(_output, outputs) {
        args += [
          "--output_file",
          rebase_path(_output, root_build_dir),
        ]
      }
      foreach(_input, _input_args) {
        args += [ "--input_file=$_input" ]
      }

      if (enable_profiling) {
        args += [ "--enable_profiling" ]
      }
      if (enable_jni_tracing) {
        args += [ "--enable_tracing" ]
      }
    }
  }

  # Declare a jni target
  #
  # This target generates the native jni bindings for a set of .java files.
  #
  # See base/android/jni_generator/jni_generator.py for more info about the
  # format of generating JNI bindings.
  #
  # Variables
  #   sources: list of .java files to generate jni for
  #   namespace: Specify the namespace for the generated header file.
  #   deps, public_deps: As normal
  #
  # Example
  #   # Target located in base/BUILD.gn.
  #   generate_jni("foo_jni") {
  #     # Generates gen/base/foo_jni/Foo_jni.h
  #     # To use: #include "base/foo_jni/Foo_jni.h"
  #     sources = [
  #       "android/java/src/org/chromium/foo/Foo.java",
  #       ...,
  #     ]
  #   }
  template("generate_jni") {
    generate_jni_impl(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    }
  }

  # Declare a jni target for a prebuilt jar
  #
  # This target generates the native jni bindings for a set of classes in a .jar.
  #
  # See base/android/jni_generator/jni_generator.py for more info about the
  # format of generating JNI bindings.
  #
  # Variables
  #   classes: list of .class files in the jar to generate jni for. These should
  #     include the full path to the .class file.
  #   jar_file: the path to the .jar. If not provided, will default to the sdk's
  #     android.jar
  #   always_mangle: Mangle all generated method names. By default, the script
  #     only mangles methods that cause ambiguity due to method overload.
  #   deps, public_deps: As normal
  #
  # Example
  #   # Target located in base/BUILD.gn.
  #   generate_jar_jni("foo_jni") {
  #     # Generates gen/base/foo_jni/Runnable_jni.h
  #     # To use: #include "base/foo_jni/Runnable_jni.h"
  #     classes = [
  #       "android/view/Foo.class",
  #     ]
  #   }
  template("generate_jar_jni") {
    generate_jni_impl(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    }
  }

  # Declare a jni registration target.
  #
  # This target generates a srcjar containing a copy of GEN_JNI.java, which has
  # the native methods of all dependent java files. It can also create a .h file
  # for use with manual JNI registration.
  #
  # The script does not scan any generated sources (those within .srcjars, or
  # within root_build_dir). This could be fixed by adding deps & logic to scan
  # .srcjars, but isn't currently needed.
  #
  # See base/android/jni_generator/jni_registration_generator.py for more info
  # about the format of the header file.
  #
  # Variables
  #   targets: List of .build_config.json supported targets to provide java sources.
  #   header_output: Path to the generated .h file (optional).
  #   sources_exclusions: List of .java files that should be skipped. (optional)
  #   namespace: Registration functions will be wrapped into this. (optional)
  #   require_native_mocks: Enforce that any native calls using
  #     org.chromium.base.annotations.NativeMethods must have a mock set
  #     (optional).
  #   enable_native_mocks: Allow native calls using
  #     org.chromium.base.annotations.NativeMethods to be mocked in tests
  #     (optional).
  #   no_transitive_deps: Generate registration for only the Java source in the
  #     specified target(s). This is useful for generating registration for
  #     feature modules, without including base module dependencies.
  #
  # Example
  #   generate_jni_registration("chrome_jni_registration") {
  #     targets = [ ":chrome_public_apk" ]
  #     header_output = "$target_gen_dir/$target_name.h"
  #     sources_exclusions = [
  #       "//path/to/Exception.java",
  #     ]
  #   }
  template("generate_jni_registration") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

      script = "//base/android/jni_generator/jni_registration_generator.py"
      inputs = []
      deps = []
      _srcjar_output = "$target_gen_dir/$target_name.srcjar"
      outputs = [ _srcjar_output ]
      depfile = "$target_gen_dir/$target_name.d"

      args = [
        "--srcjar-path",
        rebase_path(_srcjar_output, root_build_dir),
        "--depfile",
        rebase_path(depfile, root_build_dir),
      ]
      foreach(_target, invoker.targets) {
        deps += [ "${_target}$build_config_target_suffix($default_toolchain)" ]
        _build_config =
            get_label_info("${_target}($default_toolchain)", "target_gen_dir") +
            "/" + get_label_info("${_target}($default_toolchain)", "name") +
            ".build_config.json"
        _rebased_build_config = rebase_path(_build_config, root_build_dir)
        inputs += [ _build_config ]

        if (defined(invoker.no_transitive_deps) && invoker.no_transitive_deps) {
          args += [ "--sources-files=@FileArg($_rebased_build_config:deps_info:java_sources_file)" ]
        } else {
          args += [
            # This is a list of .sources files.
            "--sources-files=@FileArg($_rebased_build_config:deps_info:jni:all_source)",
          ]
        }
      }

      if (use_hashed_jni_names) {
        args += [ "--use_proxy_hash" ]
      }

      if (defined(invoker.enable_native_mocks) && invoker.enable_native_mocks) {
        args += [ "--enable_proxy_mocks" ]

        if (defined(invoker.require_native_mocks) &&
            invoker.require_native_mocks) {
          args += [ "--require_mocks" ]
        }
      }

      if (defined(invoker.header_output)) {
        outputs += [ invoker.header_output ]
        args += [
          "--header-path",
          rebase_path(invoker.header_output, root_build_dir),
        ]
      }

      if (defined(invoker.sources_exclusions)) {
        _rebase_sources_exclusions =
            rebase_path(invoker.sources_exclusions, root_build_dir)
        args += [ "--sources-exclusions=$_rebase_sources_exclusions" ]
      }

      if (defined(invoker.namespace)) {
        args += [ "--namespace=${invoker.namespace}" ]
      }
    }
  }

  # Declare a target for c-preprocessor-generated java files
  #
  # NOTE: For generating Java conterparts to enums prefer using the java_cpp_enum
  #       rule instead.
  #
  # This target generates java files using the host C pre-processor. Each file in
  # sources will be compiled using the C pre-processor. If include_path is
  # specified, it will be passed (with --I) to the pre-processor.
  #
  # This target will create a single .srcjar. Adding this target to an
  # android_library target's srcjar_deps will make the generated java files be
  # included in that library's final outputs.
  #
  # Variables
  #   sources: list of files to be processed by the C pre-processor. For each
  #     file in sources, there will be one .java file in the final .srcjar. For a
  #     file named FooBar.template, a java file will be created with name
  #     FooBar.java.
  #   inputs: additional compile-time dependencies. Any files
  #     `#include`-ed in the templates should be listed here.
  #   defines: List of -D arguments for the preprocessor.
  #
  # Example
  #   java_cpp_template("foo_generated_enum") {
  #     sources = [
  #       "android/java/templates/Foo.template",
  #     ]
  #     inputs = [
  #       "android/java/templates/native_foo_header.h",
  #     ]
  #   }
  template("java_cpp_template") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker,
                             [
                               "data_deps",
                               "deps",
                               "inputs",
                               "public_deps",
                               "sources",
                               "testonly",
                               "visibility",
                             ])
      script = "//chromium/build/android/gyp/gcc_preprocess.py"
      outputs = [ "$target_gen_dir/$target_name.srcjar" ]

      _include_dirs = [
        "//",
        root_gen_dir,
      ]
      _rebased_include_dirs = rebase_path(_include_dirs, root_build_dir)
      args = [
        "--include-dirs=$_rebased_include_dirs",
        "--output",
        rebase_path(outputs[0], root_build_dir),
      ]
      if (defined(invoker.defines)) {
        foreach(_define, invoker.defines) {
          args += [
            "--define",
            _define,
          ]
        }
      }
      args += rebase_path(sources, root_build_dir)
    }
  }

  # Declare a target for generating Java classes from C++ enums.
  #
  # This target generates Java files from C++ enums using a script.
  #
  # This target will create a single .srcjar. Adding this target to an
  # android_library target's srcjar_deps will make the generated java files be
  # included in that library's final outputs.
  #
  # Variables
  #   sources: list of files to be processed by the script. For each annotated
  #     enum contained in the sources files the script will generate a .java
  #     file with the same name as the name of the enum.
  #
  # Example
  #   java_cpp_enum("foo_generated_enum") {
  #     sources = [
  #       "src/native_foo_header.h",
  #     ]
  #   }
  template("java_cpp_enum") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ])

      # The sources aren't compiled so don't check their dependencies.
      check_includes = false
      script = "//chromium/build/android/gyp/java_cpp_enum.py"

      _srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
      _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir)
      _rebased_sources = rebase_path(invoker.sources, root_build_dir)

      args = [ "--srcjar=$_rebased_srcjar_path" ] + _rebased_sources
      outputs = [ _srcjar_path ]
    }
  }

  # Declare a target for generating Java classes with string constants matching
  # those found in C++ files using a python script.
  #
  # This target will create a single .srcjar. Adding this target to an
  # android_library target's srcjar_deps will make the generated java files be
  # included in that library's final outputs.
  #
  # Variables
  #   sources: list of files to be processed by the script. For each string
  #            constant in the source files, the script will add a corresponding
  #            Java string to the specified template file.
  # Example
  #   java_cpp_strings("foo_switches") {
  #     sources = [
  #       "src/foo_switches.cc",
  #     ]
  #     template = "src/templates/FooSwitches.java.tmpl
  #   }
  #
  # foo_switches.cc:
  #
  # // A switch.
  # const char kASwitch = "a-switch";
  #
  # FooSwitches.java.tmpl
  #
  # // Copyright {YEAR} The Chromium Authors. All rights reserved.
  # // Use of this source code is governed by a BSD-style license that can be
  # // found in the LICENSE file.
  #
  # // This file is autogenerated by
  # //     {SCRIPT_NAME}
  # // From
  # //     {SOURCE_PATH}, and
  # //     {TEMPLATE_PATH}
  #
  # package my.java.package;
  #
  # public abstract class FooSwitches {{
  #     // ...snip...
  # {NATIVE_STRINGS}
  #     // ...snip...
  # }}
  #
  # result:
  #   A FooSwitches.java file, defining a class named FooSwitches in the package
  #   my.java.package.
  template("java_cpp_strings") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ])

      # The sources aren't compiled so don't check their dependencies.
      check_includes = false
      script = "//chromium/build/android/gyp/java_cpp_strings.py"

      _srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
      _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir)
      _rebased_sources = rebase_path(invoker.sources, root_build_dir)
      _rebased_template = rebase_path(invoker.template, root_build_dir)

      args = [
        "--srcjar=$_rebased_srcjar_path",
        "--template=$_rebased_template",
      ]
      args += _rebased_sources
      sources += [ invoker.template ]

      outputs = [ _srcjar_path ]
    }
  }

  # Declare a target for generating Java classes with string constants matching
  # those found in C++ base::Feature declarations, using a python script.
  #
  # This target will create a single .srcjar. Adding this target to an
  # android_library target's srcjar_deps will make the generated java files be
  # included in that library's final outputs.
  #
  # Variables
  #   sources: list of files to be processed by the script. For each
  #            base::Feature in the source files, the script will add a
  #            corresponding Java string for that feature's name to the
  #            specified template file.
  # Example
  #   java_cpp_features("foo_features") {
  #     sources = [
  #       "src/foo_features.cc",
  #     ]
  #     template = "src/templates/FooFeatures.java.tmpl
  #   }
  #
  # foo_features.cc:
  #
  # // A feature.
  # const base::Feature kSomeFeature{"SomeFeature",
  #                                  base::FEATURE_DISABLED_BY_DEFAULT};
  #
  # FooFeatures.java.tmpl
  #
  # // Copyright $YEAR The Chromium Authors. All rights reserved.
  # // Use of this source code is governed by a BSD-style license that can be
  # // found in the LICENSE file.
  #
  # package my.java.package;
  #
  # public final class FooFeatures {{
  #     // ...snip...
  # {NATIVE_STRINGS}
  #     // ...snip...
  #     // Do not instantiate this class.
  #     private FooFeatures() {{}}
  # }}
  #
  # result:
  #   A FooFeatures.java file, defining a class named FooFeatures in the package
  #   my.java.package.
  template("java_cpp_features") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ])

      # The sources aren't compiled so don't check their dependencies.
      check_includes = false
      script = "//chromium/build/android/gyp/java_cpp_features.py"

      _srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
      _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir)
      _rebased_sources = rebase_path(invoker.sources, root_build_dir)
      _rebased_template = rebase_path(invoker.template, root_build_dir)

      args = [
        "--srcjar=$_rebased_srcjar_path",
        "--template=$_rebased_template",
      ]
      args += _rebased_sources
      sources += [ invoker.template ]

      outputs = [ _srcjar_path ]
    }
  }

  # Declare a target for processing a Jinja template.
  #
  # Variables
  #   input: The template file to be processed.
  #   includes: List of files {% include %}'ed by input.
  #   output: Where to save the result.
  #   variables: (Optional) A list of variables to make available to the template
  #     processing environment, e.g. ["name=foo", "color=red"].
  #
  # Example
  #   jinja_template("chrome_public_manifest") {
  #     input = "java/AndroidManifest.xml"
  #     output = "$target_gen_dir/AndroidManifest.xml"
  #   }
  template("jinja_template") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ])
      inputs = [ invoker.input ]
      if (defined(invoker.includes)) {
        inputs += invoker.includes
      }
      script = "//chromium/build/android/gyp/jinja_template.py"

      outputs = [ invoker.output ]

      args = [
        "--loader-base-dir",
        rebase_path("//", root_build_dir),
        "--inputs",
        rebase_path(invoker.input, root_build_dir),
        "--output",
        rebase_path(invoker.output, root_build_dir),
        "--check-includes",
      ]
      if (defined(invoker.includes)) {
        _rebased_includes = rebase_path(invoker.includes, root_build_dir)
        args += [ "--includes=$_rebased_includes" ]
      }
      if (defined(invoker.variables)) {
        args += [ "--variables=${invoker.variables}" ]
      }
    }
  }

  # Writes native libraries to a NativeLibaries.java file.
  #
  # This target will create a single .srcjar. Adding this target to an
  # android_library target's srcjar_deps will make the generated java files be
  # included in that library's final outputs.
  #
  # Variables:
  #   native_libraries_list_file: (Optional) Path to file listing all native
  #     libraries to write.
  #   version_number: (Optional) String of expected version of 'main' native
  #     library.
  #   enable_chromium_linker: (Optional) Whether to use the Chromium linker.
  #   load_library_from_apk: (Optional) Whether libraries should be loaded from
  #     the APK without uncompressing.
  #   use_final_fields: True to use final fields. When false, all other
  #       variables must not be set.
  template("write_native_libraries_java") {
    _native_libraries_file = "$target_gen_dir/$target_name.srcjar"
    if (target_cpu == "arm" || target_cpu == "arm64") {
      _cpu_family = "CPU_FAMILY_ARM"
    } else if (target_cpu == "x86" || target_cpu == "x64") {
      _cpu_family = "CPU_FAMILY_X86"
    } else if (target_cpu == "mipsel" || target_cpu == "mips64el") {
      _cpu_family = "CPU_FAMILY_MIPS"
    } else {
      assert(false, "Unsupported CPU family")
    }

    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ])
      script = "//chromium/build/android/gyp/write_native_libraries_java.py"
      outputs = [ _native_libraries_file ]
      args = [
        "--output",
        rebase_path(_native_libraries_file, root_build_dir),
        "--cpu-family",
        _cpu_family,
      ]
      if (invoker.use_final_fields) {
        # Write native_libraries_list_file via depfile rather than specifyin it
        # as a dep in order allow R8 to run in parallel with native compilation.
        depfile = "$target_gen_dir/$target_name.d"
        args += [
          "--final",
          "--depfile",
          rebase_path(depfile, root_build_dir),
          "--native-libraries-list",
          rebase_path(invoker.native_libraries_list_file, root_build_dir),
        ]
        if (defined(invoker.main_component_library)) {
          args += [
            "--main-component-library",
            invoker.main_component_library,
          ]
        }
        if (defined(invoker.enable_chromium_linker) &&
            invoker.enable_chromium_linker) {
          args += [ "--enable-chromium-linker" ]
        }
        if (defined(invoker.load_library_from_apk) &&
            invoker.load_library_from_apk) {
          args += [ "--load-library-from-apk" ]
        }
        if (defined(invoker.use_modern_linker) && invoker.use_modern_linker) {
          args += [ "--use-modern-linker" ]
        }
      }
    }
  }

  # Declare a target for a set of Android resources generated at build
  # time and stored in a single zip archive. The content of the archive
  # should match the layout of a regular Android res/ folder (but the
  # archive should not include a top-level res/ directory).
  #
  # Note that there is no associated .srcjar, R.txt or package name
  # associated with this target.
  #
  # Variables:
  #   generated_resources_zip: Generated zip archive path.
  #   generating_target: Name of the target generating
  #     generated_resources_zip. This rule will check that it is part
  #     of its outputs.
  #   deps: Specifies the dependencies of this target. Any Android resources
  #     listed here will be also be included *after* this one when compiling
  #     all resources for a final apk or junit binary. This is useful to
  #     ensure that the resources of the current target override those of the
  #     dependency as well (and would not work if you have these deps to the
  #     generating target's dependencies).
  #
  # Example
  #   _zip_archive = "$target_gen_dir/${target_name}.resources_zip"
  #
  #   action("my_resources__create_zip") {
  #     _depfile = "$target_gen_dir/${target_name}.d"
  #     script = "//chromium/build/path/to/create_my_resources_zip.py"
  #     args = [
  #       "--depfile", rebase_path(_depfile, root_build_dir),
  #       "--output-zip", rebase_path(_zip_archive, root_build_dir),
  #     ]
  #     inputs = []
  #     outputs = _zip_archive
  #     depfile = _depfile
  #   }
  #
  #   android_generated_resources("my_resources") {
  #      generated_resources_zip = _zip_archive
  #      generating_target = ":my_resources__create_zip"
  #   }
  #
  template("android_generated_resources") {
    forward_variables_from(invoker, [ "testonly" ])
    _build_config = "$target_gen_dir/${target_name}.build_config.json"
    _rtxt_out_path = "$target_gen_dir/${target_name}.R.txt"
    write_build_config("$target_name$build_config_target_suffix") {
      forward_variables_from(invoker, [ "resource_overlay" ])

      build_config = _build_config
      resources_zip = invoker.generated_resources_zip
      type = "android_resources"
      if (defined(invoker.deps)) {
        possible_config_deps = invoker.deps
      }
      r_text = _rtxt_out_path
    }
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, [ "visibility" ])
      public_deps = [
        ":$target_name$build_config_target_suffix",
        invoker.generating_target,
      ]
      inputs = [ invoker.generated_resources_zip ]
      outputs = [ _rtxt_out_path ]
      script = "//chromium/build/android/gyp/create_r_txt.py"
      args = [
        "--resources-zip-path",
        rebase_path(invoker.generated_resources_zip, root_build_dir),
        "--rtxt-path",
        rebase_path(_rtxt_out_path, root_build_dir),
      ]
    }
  }

  # Declare a target for processing Android resources as Jinja templates.
  #
  # This takes an Android resource directory where each resource is a Jinja
  # template, processes each template, then packages the results in a zip file
  # which can be consumed by an android resources, library, or apk target.
  #
  # If this target is included in the deps of an android resources/library/apk,
  # the resources will be included with that target.
  #
  # Variables
  #   resources: The list of resources files to process.
  #   res_dir: The resource directory containing the resources.
  #   variables: (Optional) A list of variables to make available to the template
  #     processing environment, e.g. ["name=foo", "color=red"].
  #
  # Example
  #   jinja_template_resources("chrome_public_template_resources") {
  #     res_dir = "res_template"
  #     resources = ["res_template/xml/syncable.xml"]
  #     variables = ["color=red"]
  #   }
  template("jinja_template_resources") {
    _resources_zip = "$target_out_dir/${target_name}.resources.zip"
    _generating_target_name = "${target_name}__template"

    action_with_pydeps(_generating_target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ])
      inputs = invoker.resources
      script = "//chromium/build/android/gyp/jinja_template.py"

      outputs = [ _resources_zip ]

      _rebased_resources = rebase_path(invoker.resources, root_build_dir)
      args = [
        "--inputs=${_rebased_resources}",
        "--inputs-base-dir",
        rebase_path(invoker.res_dir, root_build_dir),
        "--outputs-zip",
        rebase_path(_resources_zip, root_build_dir),
        "--check-includes",
      ]
      if (defined(invoker.variables)) {
        variables = invoker.variables
        args += [ "--variables=${variables}" ]
      }
    }

    android_generated_resources(target_name) {
      forward_variables_from(invoker,
                             TESTONLY_AND_VISIBILITY + [
                                   "deps",
                                   "resource_overlay",
                                 ])
      generating_target = ":$_generating_target_name"
      generated_resources_zip = _resources_zip
    }
  }

  # Declare a prebuilt android native library.
  #
  # This takes a base directory and library name and then looks for the library
  # in <base dir>/$android_app_abi/<library name>.
  #
  # If you depend on this target, the library is stripped and output to the
  # same locations non-prebuilt libraries are output.
  #
  # Variables
  #   base_dir: Directory where all ABIs of the library live.
  #   library_name: Name of the library .so file.
  #
  # Example
  #   android_native_prebuilt("elements_native") {
  #     base_dir = "//third_party/elements"
  #     lib_name = "elements.so"
  #   }
  template("android_native_prebuilt") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker,
                             [
                               "deps",
                               "testonly",
                             ])
      script = "//chromium/build/android/gyp/process_native_prebuilt.py"
      _lib_path = "${invoker.base_dir}/$android_app_abi/${invoker.lib_name}"
      _stripped_output_path = "$root_out_dir/${invoker.lib_name}"
      _unstripped_output_path =
          "$root_out_dir/lib.unstripped/${invoker.lib_name}"
      inputs = [ _lib_path ]
      outputs = [
        _stripped_output_path,
        _unstripped_output_path,
      ]

      # Add unstripped output to runtime deps for use by bots during stacktrace
      # symbolization.
      data = [ _unstripped_output_path ]

      _rebased_lib_path = rebase_path(_lib_path, root_build_dir)
      _rebased_stripped_ouput_path =
          rebase_path(_stripped_output_path, root_build_dir)
      _rebased_unstripped_ouput_path =
          rebase_path(_unstripped_output_path, root_build_dir)
      _strip_tool_path =
          rebase_path("//buildtools/third_party/eu-strip/bin/eu-strip",
                      root_build_dir)

      args = [
        "--strip-path=$_strip_tool_path",
        "--input-path=$_rebased_lib_path",
        "--stripped-output-path=$_rebased_stripped_ouput_path",
        "--unstripped-output-path=$_rebased_unstripped_ouput_path",
      ]
    }
  }

  # Declare an Android resources target
  #
  # This creates a resources zip file that will be used when building an Android
  # library or apk and included into a final apk.
  #
  # To include these resources in a library/apk, this target should be listed in
  # the library's deps. A library/apk will also include any resources used by its
  # own dependencies.
  #
  # Variables
  #   sources: List of resource files for this target.
  #   deps: Specifies the dependencies of this target. Any Android resources
  #     listed in deps will be included by libraries/apks that depend on this
  #     target.
  #   alternative_android_sdk_dep: Optional. Alternative Android system
  #     android java target to use.
  #   android_manifest: AndroidManifest.xml for this target (optional). Will be
  #     merged into apks that directly or indirectly depend on this target.
  #   android_manifest_dep: Target that generates AndroidManifest (if applicable)
  #   custom_package: java package for generated .java files.
  #   allow_missing_resources: Do not fail if a resource exists in a directory
  #      but is not listed in sources.
  #   shared_resources: If true make a resource package that can be loaded by a
  #     different application at runtime to access the package's resources.
  #   resource_overlay: Whether the resources in 'sources' should override
  #     resources with the same name. Does not affect the behaviour of any
  #     android_resources() deps of this target. If a target with
  #     resource_overlay=true depends on another target with
  #     resource_overlay=true the target with the dependency overrides the
  #     other.
  #   r_text_file: (optional) path to pre-generated R.txt to be used when
  #     generating R.java instead of resource-based aapt-generated one.
  #   recursive_resource_deps: (optional) whether deps should be walked
  #     recursively to find resource deps.
  #
  # Example:
  #   android_resources("foo_resources") {
  #     deps = [":foo_strings_grd"]
  #     sources = [
  #       "res/drawable/foo1.xml",
  #       "res/drawable/foo2.xml",
  #     ]
  #     custom_package = "org.chromium.foo"
  #   }
  #
  #   android_resources("foo_resources_overrides") {
  #     deps = [":foo_resources"]
  #     sources = [
  #       "res_overrides/drawable/foo1.xml",
  #       "res_overrides/drawable/foo2.xml",
  #     ]
  #   }
  template("android_resources") {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

    _base_path = "$target_gen_dir/$target_name"
    if (defined(invoker.v14_skip)) {
      not_needed(invoker, [ "v14_skip" ])
    }

    _res_sources_path = "$target_gen_dir/${invoker.target_name}.res.sources"

    _resources_zip = "$target_out_dir/$target_name.resources.zip"
    _r_text_out_path = _base_path + "_R.txt"
    _build_config = _base_path + ".build_config.json"
    _build_config_target_name = "$target_name$build_config_target_suffix"

    _deps = []
    if (defined(invoker.deps)) {
      _deps += invoker.deps
    }

    if (defined(invoker.alternative_android_sdk_dep)) {
      _deps += [ invoker.alternative_android_sdk_dep ]
    } else {
      _deps += [ "//third_party/android_sdk:android_sdk_java" ]
    }

    _resource_files = []
    if (defined(invoker.sources)) {
      _resource_files += invoker.sources
    }

    _rebased_resource_files = rebase_path(_resource_files, root_build_dir)
    write_file(_res_sources_path, _rebased_resource_files)

    # This is necessary so we only lint chromium resources.
    if (defined(invoker.chromium_code)) {
      _chromium_code = invoker.chromium_code
    } else {
      # Default based on whether target is in third_party.
      _chromium_code =
          filter_exclude([ get_label_info(":$target_name", "dir") ],
                         [ "*\bthird_party\b*" ]) != []
    }

    write_build_config(_build_config_target_name) {
      type = "android_resources"
      build_config = _build_config
      resources_zip = _resources_zip
      res_sources_path = _res_sources_path
      chromium_code = _chromium_code

      forward_variables_from(invoker,
                             [
                               "android_manifest",
                               "android_manifest_dep",
                               "custom_package",
                               "mergeable_android_manifests",
                               "resource_overlay",
                               "recursive_resource_deps",
                             ])

      r_text = _r_text_out_path
      possible_config_deps = _deps

      # Always merge manifests from resources.
      # * Might want to change this at some point for consistency and clarity,
      #   but keeping for backwards-compatibility.
      if (!defined(mergeable_android_manifests) && defined(android_manifest)) {
        mergeable_android_manifests = [ android_manifest ]
      }
    }

    prepare_resources(target_name) {
      forward_variables_from(invoker,
                             [
                               "strip_drawables",
                               "allow_missing_resources",
                               "visibility",
                             ])
      deps = _deps

      res_sources_path = _res_sources_path
      sources = _resource_files

      resources_zip = _resources_zip
      r_text_out_path = _r_text_out_path

      if (defined(invoker.r_text_file)) {
        r_text_in_path = invoker.r_text_file
      }
    }
  }

  # Declare an Android assets target.
  #
  # Defines a set of files to include as assets in a dependent apk.
  #
  # To include these assets in an apk, this target should be listed in
  # the apk's deps, or in the deps of a library target used by an apk.
  #
  # Variables
  #   deps: Specifies the dependencies of this target. Any Android assets
  #     listed in deps will be included by libraries/apks that depend on this
  #     target.
  #   sources: List of files to include as assets.
  #   renaming_sources: List of files to include as assets and be renamed.
  #   renaming_destinations: List of asset paths for files in renaming_sources.
  #   disable_compression: Whether to disable compression for files that are
  #     known to be compressable (default: false).
  #   treat_as_locale_paks: Causes base's BuildConfig.java to consider these
  #     assets to be locale paks.
  #
  # Example:
  # android_assets("content_shell_assets") {
  #   deps = [
  #     ":generates_foo",
  #     ":other_assets",
  #     ]
  #   sources = [
  #     "//path/asset1.png",
  #     "//path/asset2.png",
  #     "$target_gen_dir/foo.dat",
  #   ]
  # }
  #
  # android_assets("overriding_content_shell_assets") {
  #   deps = [ ":content_shell_assets" ]
  #   # Override foo.dat from content_shell_assets.
  #   sources = [ "//custom/foo.dat" ]
  #   renaming_sources = [ "//path/asset2.png" ]
  #   renaming_destinations = [ "renamed/asset2.png" ]
  # }
  template("android_assets") {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

    _build_config = "$target_gen_dir/$target_name.build_config.json"
    _build_config_target_name = "$target_name$build_config_target_suffix"

    write_build_config(_build_config_target_name) {
      type = "android_assets"
      build_config = _build_config

      forward_variables_from(invoker,
                             [
                               "disable_compression",
                               "treat_as_locale_paks",
                             ])

      if (defined(invoker.deps)) {
        possible_config_deps = invoker.deps
      }

      if (defined(invoker.sources)) {
        asset_sources = invoker.sources
      }
      if (defined(invoker.renaming_sources)) {
        assert(defined(invoker.renaming_destinations))
        _source_count = 0
        foreach(_, invoker.renaming_sources) {
          _source_count += 1
        }
        _dest_count = 0
        foreach(_, invoker.renaming_destinations) {
          _dest_count += 1
        }
        assert(
            _source_count == _dest_count,
            "android_assets() renaming_sources.length != renaming_destinations.length")
        asset_renaming_sources = invoker.renaming_sources
        asset_renaming_destinations = invoker.renaming_destinations
      }
    }

    group(target_name) {
      forward_variables_from(invoker, [ "deps" ])
      public_deps = [ ":$_build_config_target_name" ]
    }
  }

  # Declare a group() that supports forwarding java dependency information.
  #
  # Example
  #  java_group("conditional_deps") {
  #    if (enable_foo) {
  #      deps = [":foo_java"]
  #    }
  #  }
  template("java_group") {
    _build_config_vars = [
      "input_jars_paths",
      "mergeable_android_manifests",
      "proguard_configs",
    ]
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    write_build_config("$target_name$build_config_target_suffix") {
      forward_variables_from(invoker, _build_config_vars)
      type = "group"
      build_config = "$target_gen_dir/${invoker.target_name}.build_config.json"
      supports_android = true
      if (defined(invoker.deps)) {
        possible_config_deps = invoker.deps
      }
    }
    foreach(_group_name,
            [
              "header",
              "impl",
              "assetres",
            ]) {
      java_lib_group("${target_name}__${_group_name}") {
        forward_variables_from(invoker, [ "deps" ])
        group_name = _group_name
      }
    }
    group(target_name) {
      forward_variables_from(invoker,
                             "*",
                             _build_config_vars + TESTONLY_AND_VISIBILITY)
      if (!defined(deps)) {
        deps = []
      }
      deps += [ ":$target_name$build_config_target_suffix" ]
    }
  }

  # Declare a Java executable target
  #
  # Same as java_library, but also creates a wrapper script within
  # $root_out_dir/bin.
  #
  # Supports all variables of java_library(), plus:
  #   main_class: When specified, a wrapper script is created within
  #     $root_build_dir/bin to launch the binary with the given class as the
  #     entrypoint.
  #   wrapper_script_name: Filename for the wrapper script (default=target_name)
  #   wrapper_script_args: List of additional arguments for the wrapper script.
  #
  # Example
  #   java_binary("foo") {
  #     sources = [ "org/chromium/foo/FooMain.java" ]
  #     deps = [ ":bar_java" ]
  #     main_class = "org.chromium.foo.FooMain"
  #   }
  #
  #   java_binary("foo") {
  #     jar_path = "lib/prebuilt.jar"
  #     deps = [ ":bar_java" ]
  #     main_class = "org.chromium.foo.FooMain"
  #   }
  template("java_binary") {
    java_library_impl(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      type = "java_binary"
      if (!defined(data_deps)) {
        data_deps = []
      }
      data_deps += [ "//third_party/jdk:java_data" ]
    }
  }

  # Declare a Java Annotation Processor.
  #
  # Supports all variables of java_library(), plus:
  #   jar_path: Path to a prebuilt jar. Mutually exclusive with sources &
  #     srcjar_deps.
  #   main_class: The fully-quallified class name of the processor's entry
  #       point.
  #
  # Example
  #   java_annotation_processor("foo_processor") {
  #     sources = [ "org/chromium/foo/FooProcessor.java" ]
  #     deps = [ ":bar_java" ]
  #     main_class = "org.chromium.foo.FooProcessor"
  #   }
  #
  #   java_annotation_processor("foo_processor") {
  #     jar_path = "lib/prebuilt.jar"
  #     main_class = "org.chromium.foo.FooMain"
  #   }
  #
  #   java_library("...") {
  #     annotation_processor_deps = [":foo_processor"]
  #   }
  #
  template("java_annotation_processor") {
    java_library_impl(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      type = "java_annotation_processor"
    }
  }

  # Declare a Junit executable target
  #
  # This target creates an executable from java code for running as a junit test
  # suite. The executable will be in the output folder's /bin/ directory.
  #
  # Supports all variables of java_binary().
  #
  # Example
  #   junit_binary("foo") {
  #     sources = [ "org/chromium/foo/FooTest.java" ]
  #     deps = [ ":bar_java" ]
  #   }
  template("junit_binary") {
    testonly = true

    _java_binary_target_name = "${target_name}__java_binary"
    _test_runner_target_name = "${target_name}__test_runner_script"
    _main_class = "org.chromium.testing.local.JunitTestMain"

    _build_config = "$target_gen_dir/$target_name.build_config.json"
    _build_config_target_name = "$target_name$build_config_target_suffix"
    _deps = [
      "//testing/android/junit:junit_test_support",
      "//third_party/android_deps:robolectric_all_java",
      "//third_party/junit",
      "//third_party/mockito:mockito_java",
    ]
    if (defined(invoker.deps)) {
      _deps += invoker.deps
    }
    if (defined(invoker.alternative_android_sdk_dep)) {
      _android_sdk_dep = invoker.alternative_android_sdk_dep
    } else {
      _android_sdk_dep = "//third_party/android_sdk:android_sdk_java"
    }

    # a package name or a manifest is required to have resources. This is
    # added so that junit tests that do not care about the package name can
    # still use resources without having to explicitly set one.
    if (defined(invoker.package_name)) {
      _package_name = invoker.package_name
    } else if (!defined(invoker.android_manifest)) {
      _package_name = "org.chromium.test"
    }

    _resource_arsc_output = "${target_gen_dir}/${target_name}.ap_"
    _compile_resources_target = "${target_name}__compile_resources"
    compile_resources(_compile_resources_target) {
      forward_variables_from(invoker, [ "android_manifest" ])
      deps = _deps
      android_sdk_dep = _android_sdk_dep
      build_config_dep = ":$_build_config_target_name"
      build_config = _build_config
      if (defined(_package_name)) {
        rename_manifest_package = _package_name
      }
      if (!defined(android_manifest)) {
        android_manifest = "//chromium/build/android/AndroidManifest.xml"
      }
      arsc_output = _resource_arsc_output
      min_sdk_version = default_min_sdk_version
      target_sdk_version = android_sdk_version
    }

    _jni_srcjar_target = "${target_name}__final_jni"
    _outer_target_name = target_name
    generate_jni_registration(_jni_srcjar_target) {
      enable_native_mocks = true
      require_native_mocks = true
      targets = [ ":$_outer_target_name" ]
    }

    java_library_impl(_java_binary_target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY + [ "deps" ])
      type = "junit_binary"
      main_target_name = invoker.target_name

      # Include the android SDK jar(s) for resource processing.
      include_android_sdk = true

      # Robolectric can handle deps that set !supports_android as well those
      # that set requires_android.
      bypass_platform_checks = true
      deps = _deps
      testonly = true
      main_class = _main_class
      wrapper_script_name = "helper/$main_target_name"

      # As of April 2021, adding -XX:TieredStopAtLevel=1 does not affect the
      # wall time of a single robolectric shard, but does reduce the CPU time by
      # 66%, which makes sharding more effective.
      tiered_stop_at_level_one = true

      if (!defined(srcjar_deps)) {
        srcjar_deps = []
      }
      srcjar_deps += [
        ":$_compile_resources_target",
        ":$_jni_srcjar_target",

        # This dep is required for any targets that depend on //base:base_java.
        "//chromium/build/android:build_config_gen",
      ]
    }

    test_runner_script(_test_runner_target_name) {
      test_name = invoker.target_name
      test_suite = invoker.target_name
      test_type = "junit"
      ignore_all_data_deps = true
      resource_apk = _resource_arsc_output
    }

    group(target_name) {
      forward_variables_from(invoker,
                             [
                               "assert_no_deps",
                               "visibility",
                             ])
      public_deps = [
        ":$_build_config_target_name",
        ":$_java_binary_target_name",
        ":$_test_runner_target_name",
      ]
    }
  }

  # Declare a java library target
  #
  # Variables
  #   deps: Specifies the dependencies of this target. Java targets in this list
  #     will be added to the javac classpath.
  #   public_deps: Dependencies that this target exposes as part of its public API.
  #     public_deps do not need to be listed in both the 'deps' and 'public_deps' lists.
  #   annotation_processor_deps: List of java_annotation_processor targets to
  #     use when compiling.
  #
  #   jar_path: Path to a prebuilt jar. Mutually exclusive with sources &
  #     srcjar_deps.
  #   sources: List of .java files included in this library.
  #   srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
  #     will be added to sources and be included in this library.
  #
  #   input_jars_paths: A list of paths to the jars that should be included
  #     in the compile-time classpath. These are in addition to library .jars
  #     that appear in deps.
  #
  #   chromium_code: If true, extra analysis warning/errors will be enabled.
  #   enable_errorprone: If true, enables the errorprone compiler.
  #   skip_build_server: If true, avoids sending tasks to the build server.
  #
  #   jar_excluded_patterns: List of patterns of .class files to exclude.
  #   jar_included_patterns: List of patterns of .class files to include.
  #     When omitted, all classes not matched by jar_excluded_patterns are
  #     included. When specified, all non-matching .class files are stripped.
  #
  #   low_classpath_priority: Indicates that the library should be placed at the
  #     end of the classpath. The default classpath order has libraries ordered
  #     before the libraries that they depend on. 'low_classpath_priority' is
  #     useful when one java_library() overrides another via
  #     'jar_excluded_patterns' and the overriding library does not depend on
  #     the overridee.
  #
  #   output_name: File name for the output .jar (not including extension).
  #     Defaults to the input .jar file name.
  #
  #   proguard_configs: List of proguard configs to use in final apk step for
  #     any apk that depends on this library.
  #
  #   supports_android: If true, Android targets (android_library, android_apk)
  #     may depend on this target. Note: if true, this target must only use the
  #     subset of Java available on Android.
  #   bypass_platform_checks: Disables checks about cross-platform (Java/Android)
  #     dependencies for this target. This will allow depending on an
  #     android_library target, for example.
  #   enable_desugar: If false, disables desugaring of lambdas, etc. Use this
  #     only when you are sure the library does not require desugaring. E.g.
  #     to hide warnings shown from desugaring.
  #
  #   additional_jar_files: Use to package additional files (Java resources)
  #     into the output jar. Pass a list of length-2 lists with format:
  #         [ [ path_to_file, path_to_put_in_jar ] ]
  #
  #   javac_args: Additional arguments to pass to javac.
  #   errorprone_args: Additional arguments to pass to errorprone.
  #
  #   data_deps, testonly
  #
  # Example
  #   java_library("foo_java") {
  #     sources = [
  #       "org/chromium/foo/Foo.java",
  #       "org/chromium/foo/FooInterface.java",
  #       "org/chromium/foo/FooService.java",
  #     ]
  #     deps = [
  #       ":bar_java"
  #     ]
  #     srcjar_deps = [
  #       ":foo_generated_enum"
  #     ]
  #     jar_excluded_patterns = [
  #       "*/FooService.class", "org/chromium/FooService\$*.class"
  #     ]
  #   }
  template("java_library") {
    java_library_impl(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      type = "java_library"
    }
  }

  # Declare a java library target for a prebuilt jar
  #
  # Supports all variables of java_library().
  #
  # Example
  #   java_prebuilt("foo_java") {
  #     jar_path = "foo.jar"
  #     deps = [
  #       ":foo_resources",
  #       ":bar_java"
  #     ]
  #   }
  template("java_prebuilt") {
    java_library_impl(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      type = "java_library"
    }
  }

  # Combines all dependent .jar files into a single .jar file.
  #
  # Variables:
  #   output: Path to the output jar.
  #   override_build_config: Use a pre-existing .build_config. Must be of type
  #     "apk".
  #   use_interface_jars: Use all dependent interface .jars rather than
  #     implementation .jars.
  #   use_unprocessed_jars: Use unprocessed / undesugared .jars.
  #   direct_deps_only: Do not recurse on deps.
  #   jar_excluded_patterns (optional)
  #     List of globs for paths to exclude.
  #
  # Example
  #   dist_jar("lib_fatjar") {
  #     deps = [ ":my_java_lib" ]
  #     output = "$root_build_dir/MyLibrary.jar"
  #   }
  template("dist_jar") {
    # TODO(crbug.com/1042017): Remove.
    not_needed(invoker, [ "no_build_hooks" ])
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    _supports_android =
        !defined(invoker.supports_android) || invoker.supports_android
    _use_interface_jars =
        defined(invoker.use_interface_jars) && invoker.use_interface_jars
    _use_unprocessed_jars =
        defined(invoker.use_unprocessed_jars) && invoker.use_unprocessed_jars
    _direct_deps_only =
        defined(invoker.direct_deps_only) && invoker.direct_deps_only
    assert(!(_use_unprocessed_jars && _use_interface_jars),
           "Cannot set both use_interface_jars and use_unprocessed_jars")

    _jar_target_name = target_name

    _deps = []
    if (defined(invoker.deps)) {
      _deps = invoker.deps
    }
    if (_supports_android) {
      _deps += [ "//third_party/android_sdk:android_sdk_java" ]
    }

    if (defined(invoker.override_build_config)) {
      _build_config = invoker.override_build_config
    } else {
      _build_config = "$target_gen_dir/$target_name.build_config.json"
      _build_config_target_name = "$target_name$build_config_target_suffix"

      write_build_config(_build_config_target_name) {
        type = "dist_jar"
        supports_android = _supports_android
        requires_android =
            defined(invoker.requires_android) && invoker.requires_android
        possible_config_deps = _deps
        ignore_dependency_public_deps = _direct_deps_only
        build_config = _build_config
      }

      _deps += [ ":$_build_config_target_name" ]
    }

    _rebased_build_config = rebase_path(_build_config, root_build_dir)
    action_with_pydeps(_jar_target_name) {
      forward_variables_from(invoker, [ "data" ])
      script = "//chromium/build/android/gyp/zip.py"
      depfile = "$target_gen_dir/$target_name.d"
      deps = _deps

      inputs = [ _build_config ]

      outputs = [ invoker.output ]

      args = [
        "--depfile",
        rebase_path(depfile, root_build_dir),
        "--output",
        rebase_path(invoker.output, root_build_dir),
        "--no-compress",
      ]

      if (_direct_deps_only) {
        if (_use_interface_jars) {
          args += [ "--input-zips=@FileArg($_rebased_build_config:javac:interface_classpath)" ]
        } else if (_use_unprocessed_jars) {
          args += [
            "--input-zips=@FileArg($_rebased_build_config:javac:classpath)",
          ]
        } else {
          assert(
              false,
              "direct_deps_only does not work without use_interface_jars or use_unprocessed_jars")
        }
      } else {
        if (_use_interface_jars) {
          args += [ "--input-zips=@FileArg($_rebased_build_config:dist_jar:all_interface_jars)" ]
        } else if (_use_unprocessed_jars) {
          args += [ "--input-zips=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)" ]
        } else {
          args += [ "--input-zips=@FileArg($_rebased_build_config:deps_info:device_classpath)" ]
        }
      }
      _excludes = []
      if (defined(invoker.jar_excluded_patterns)) {
        _excludes += invoker.jar_excluded_patterns
      }
      if (_use_interface_jars) {
        # Turbine adds files like: META-INF/TRANSITIVE/.../Foo.class
        # These confuse proguard: https://crbug.com/1081443
        _excludes += [ "META-INF/*" ]
      }
      if (_excludes != []) {
        args += [ "--input-zips-excluded-globs=$_excludes" ]
      }
    }
  }

  # Combines all dependent .jar files into a single proguarded .dex file.
  #
  # Variables:
  #   output: Path to the output dex.
  #   proguard_enabled: Whether to enable R8.
  #   proguard_configs: List of proguard configs.
  #   proguard_enable_obfuscation: Whether to enable obfuscation (default=true).
  #
  # Example
  #   dist_dex("lib_fatjar") {
  #     deps = [ ":my_java_lib" ]
  #     output = "$root_build_dir/MyLibrary.jar"
  #   }
  template("dist_dex") {
    _deps = [ "//third_party/android_sdk:android_sdk_java" ]
    if (defined(invoker.deps)) {
      _deps += invoker.deps
    }

    _build_config = "$target_gen_dir/$target_name.build_config.json"
    _build_config_target_name = "$target_name$build_config_target_suffix"

    write_build_config(_build_config_target_name) {
      type = "dist_jar"
      forward_variables_from(invoker,
                             [
                               "proguard_configs",
                               "proguard_enabled",
                             ])
      supports_android = true
      requires_android = true
      possible_config_deps = _deps
      build_config = _build_config
    }

    _deps += [ ":$_build_config_target_name" ]

    dex(target_name) {
      forward_variables_from(invoker,
                             TESTONLY_AND_VISIBILITY + [
                                   "data",
                                   "data_deps",
                                   "proguard_configs",
                                   "proguard_enabled",
                                   "proguard_enable_obfuscation",
                                   "min_sdk_version",
                                 ])
      deps = _deps
      build_config = _build_config
      enable_multidex = false
      output = invoker.output
      if (defined(proguard_enabled) && proguard_enabled) {
        # The individual dependencies would have caught real missing deps in
        # their respective dex steps. False positives that were suppressed at
        # per-target dex steps are emitted here since this is using jar files
        # rather than dex files.
        ignore_desugar_missing_deps = true

        # When trying to build a stand-alone .dex, don't add in jdk_libs_dex.
        supports_jdk_library_desugaring = false
      } else {
        _rebased_build_config = rebase_path(_build_config, root_build_dir)
        input_dex_filearg =
            "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)"
      }
    }
  }

  # Creates an Android .aar library.
  #
  # Currently supports:
  #   * AndroidManifest.xml
  #   * classes.jar
  #   * jni/
  #   * res/
  #   * R.txt
  #   * proguard.txt
  # Does not yet support:
  #   * public.txt
  #   * annotations.zip
  #   * assets/
  # See: https://developer.android.com/studio/projects/android-library.html#aar-contents
  #
  # Variables:
  #   output: Path to the output .aar.
  #   proguard_configs: List of proguard configs (optional).
  #   android_manifest: Path to AndroidManifest.xml (optional).
  #   native_libraries: list of native libraries (optional).
  #   direct_deps_only: Do not recurse on deps. (optional, defaults false).
  #   jar_excluded_patterns (optional): List of globs for paths to exclude.
  #   jar_included_patterns (optional): List of globs for paths to include.
  #
  # Example
  #   dist_aar("my_aar") {
  #     deps = [ ":my_java_lib" ]
  #     output = "$root_build_dir/MyLibrary.aar"
  #   }
  template("dist_aar") {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

    _deps = []
    if (defined(invoker.deps)) {
      _deps = invoker.deps
    }

    _direct_deps_only =
        defined(invoker.direct_deps_only) && invoker.direct_deps_only

    _build_config = "$target_gen_dir/$target_name.build_config.json"
    _build_config_target_name = "$target_name$build_config_target_suffix"

    write_build_config(_build_config_target_name) {
      type = "dist_aar"
      forward_variables_from(invoker, [ "proguard_configs" ])
      possible_config_deps = _deps
      supports_android = true
      requires_android = true
      ignore_dependency_public_deps = _direct_deps_only
      build_config = _build_config
    }

    _deps += [ ":$_build_config_target_name" ]

    _rebased_build_config = rebase_path(_build_config, root_build_dir)

    action_with_pydeps(target_name) {
      forward_variables_from(invoker, [ "data" ])
      depfile = "$target_gen_dir/$target_name.d"
      deps = _deps
      script = "//chromium/build/android/gyp/dist_aar.py"

      inputs = [ _build_config ]

      # Although these will be listed as deps in the depfile, they must also
      # appear here so that "gn analyze" knows about them.
      # https://crbug.com/827197
      if (defined(invoker.proguard_configs)) {
        inputs += invoker.proguard_configs
      }

      outputs = [ invoker.output ]

      args = [
        "--depfile",
        rebase_path(depfile, root_build_dir),
        "--output",
        rebase_path(invoker.output, root_build_dir),
        "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)",
        "--r-text-files=@FileArg($_rebased_build_config:deps_info:dependency_r_txt_files)",
        "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)",
      ]
      if (_direct_deps_only) {
        args += [ "--jars=@FileArg($_rebased_build_config:javac:classpath)" ]
      } else {
        args += [ "--jars=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)" ]
      }
      if (defined(invoker.android_manifest)) {
        args += [
          "--android-manifest",
          rebase_path(invoker.android_manifest, root_build_dir),
        ]
      }
      if (defined(invoker.native_libraries) && invoker.native_libraries != []) {
        inputs += invoker.native_libraries
        _rebased_native_libraries =
            rebase_path(invoker.native_libraries, root_build_dir)

        args += [
          "--native-libraries=$_rebased_native_libraries",
          "--abi=$android_app_abi",
        ]
      }
      if (defined(invoker.jar_excluded_patterns)) {
        args += [ "--jar-excluded-globs=${invoker.jar_excluded_patterns}" ]
      }
      if (defined(invoker.jar_included_patterns)) {
        args += [ "--jar-included-globs=${invoker.jar_included_patterns}" ]
      }
      if (defined(invoker.resource_included_patterns)) {
        args += [
          "--resource-included-globs=${invoker.resource_included_patterns}",
        ]
      }
    }
  }

  # Declare an Android library target
  #
  # This target creates an Android library containing java code and Android
  # resources.
  #
  # Supports all variables of java_library(), plus:
  #   deps: In addition to defining java deps, this can also include
  #     android_assets() and android_resources() targets.
  #   alternative_android_sdk_ijar: if set, the given android_sdk_ijar file
  #     replaces the default android_sdk_ijar.
  #   alternative_android_sdk_ijar_dep: the target that generates
  #      alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar
  #      is used.
  #   alternative_android_sdk_jar: actual jar corresponding to
  #      alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar
  #      is used.
  #
  # Example
  #   android_library("foo_java") {
  #     sources = [
  #       "android/org/chromium/foo/Foo.java",
  #       "android/org/chromium/foo/FooInterface.java",
  #       "android/org/chromium/foo/FooService.java",
  #     ]
  #     deps = [
  #       ":bar_java"
  #     ]
  #     srcjar_deps = [
  #       ":foo_generated_enum"
  #     ]
  #     jar_excluded_patterns = [
  #       "*/FooService.class", "org/chromium/FooService\$*.class"
  #     ]
  #   }
  template("android_library") {
    java_library(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

      supports_android = true
      requires_android = true

      if (!defined(jar_excluded_patterns)) {
        jar_excluded_patterns = []
      }
      jar_excluded_patterns += [
        "*/R.class",
        "*/R\$*.class",
        "*/Manifest.class",
        "*/Manifest\$*.class",
        "*/GEN_JNI.class",
      ]
    }
  }

  # Declare an Android library target for a prebuilt jar
  #
  # This target creates an Android library containing java code and Android
  # resources.
  #
  # Supports all variables of android_library().
  #
  # Example
  #   android_java_prebuilt("foo_java") {
  #     jar_path = "foo.jar"
  #     deps = [
  #       ":foo_resources",
  #       ":bar_java"
  #     ]
  #   }
  template("android_java_prebuilt") {
    android_library(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    }
  }

  template("android_system_java_prebuilt") {
    java_library_impl(target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      supports_android = true
      type = "system_java_library"
    }
  }

  # Creates org/chromium/build/BuildConfig.java
  # This doesn't really belong in //build since it genates a file for //base.
  # However, we don't currently have a better way to include this file in all
  # apks that depend on //base:base_java.
  #
  # Variables:
  #   use_final_fields: True to use final fields. When false, all other
  #       variables must not be set.
  #   enable_multidex: Value for ENABLE_MULTIDEX.
  #   min_sdk_version: Value for MIN_SDK_VERSION.
  #   bundles_supported: Whether or not this target can be treated as a bundle.
  #   resources_version_variable:
  #   is_incremental_install:
  #   isolated_splits_enabled: Value for ISOLATED_SPLITS_ENABLED.
  template("generate_build_config_srcjar") {
    java_cpp_template(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      sources = [ "//chromium/build/android/java/templates/BuildConfig.template" ]
      defines = []

      # Set these even when !use_final_fields so that they have correct default
      # values within junit_binary(), which ignores jar_excluded_patterns.
      if (enable_java_asserts) {
        defines += [ "_ENABLE_ASSERTS" ]
      }
      if (use_cfi_diag || is_ubsan || is_ubsan_security || is_ubsan_vptr) {
        defines += [ "_IS_UBSAN" ]
      }

      if (is_chrome_branded) {
        defines += [ "_IS_CHROME_BRANDED" ]
      }

      if (is_chromecast && chromecast_branding == "internal") {
        defines += [ "_IS_CHROMECAST_BRANDING_INTERNAL" ]
      }

      if (defined(invoker.bundles_supported) && invoker.bundles_supported) {
        defines += [ "_BUNDLES_SUPPORTED" ]
      }

      if (defined(invoker.isolated_splits_enabled) &&
          invoker.isolated_splits_enabled) {
        defines += [ "_ISOLATED_SPLITS_ENABLED" ]
      }

      if (defined(invoker.is_incremental_install) &&
          invoker.is_incremental_install) {
        defines += [ "_IS_INCREMENTAL_INSTALL" ]
      }

      if (invoker.use_final_fields) {
        forward_variables_from(invoker, [ "deps" ])
        defines += [ "USE_FINAL" ]
        if (invoker.enable_multidex) {
          defines += [ "ENABLE_MULTIDEX" ]
        }
        if (defined(invoker.min_sdk_version)) {
          defines += [ "_MIN_SDK_VERSION=${invoker.min_sdk_version}" ]
        }
        if (defined(invoker.resources_version_variable)) {
          defines += [
            "_RESOURCES_VERSION_VARIABLE=${invoker.resources_version_variable}",
          ]
        }
      }
    }
  }

  # Creates ProductConfig.java, a file containing product-specific configuration.
  #
  # Currently, this includes the list of locales, both in their compressed and
  # uncompressed format, as well as library loading
  #
  # Variables:
  #   build_config: Path to build_config used for locale lists.
  #   is_bundle_module: Whether or not this target is part of a bundle build.
  #   java_package: Java package for the generated class.
  #   use_chromium_linker:
  #   use_modern_linker:
  template("generate_product_config_srcjar") {
    java_cpp_template(target_name) {
      defines = []
      _use_final =
          defined(invoker.build_config) ||
          defined(invoker.use_chromium_linker) ||
          defined(invoker.use_modern_linker) || defined(invoker.is_bundle)
      if (_use_final) {
        defines += [ "USE_FINAL" ]
      }

      sources = [ "//chromium/build/android/java/templates/ProductConfig.template" ]
      defines += [ "PACKAGE=${invoker.java_package}" ]

      _use_chromium_linker =
          defined(invoker.use_chromium_linker) && invoker.use_chromium_linker
      _use_modern_linker =
          defined(invoker.use_modern_linker) && invoker.use_modern_linker
      _is_bundle = defined(invoker.is_bundle_module) && invoker.is_bundle_module
      defines += [
        "USE_CHROMIUM_LINKER_VALUE=$_use_chromium_linker",
        "USE_MODERN_LINKER_VALUE=$_use_modern_linker",
        "IS_BUNDLE_VALUE=$_is_bundle",
      ]
      if (defined(invoker.build_config)) {
        forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ])
        _rebased_build_config =
            rebase_path(invoker.build_config, root_build_dir)
        defines += [ "LOCALE_LIST=@FileArg($_rebased_build_config:deps_info:locales_java_list)" ]
      }
    }
  }

  # Declare an Android app module target, which is used as the basis for an
  # Android APK or an Android app bundle module.
  #
  # Supports all variables of android_library(), plus:
  #   android_manifest: Path to AndroidManifest.xml. NOTE: This manifest must
  #     not contain a <uses-sdk> element. Use [min|target|max]_sdk_version
  #     instead.
  #   android_manifest_dep: Target that generates AndroidManifest (if applicable)
  #   png_to_webp: If true, pngs (with the exception of 9-patch) are
  #     converted to webp during resource packaging.
  #   loadable_modules: List of paths to native libraries to include. Different
  #     from |shared_libraries| in that:
  #       * dependencies of this .so are not automatically included
  #       * ".cr.so" is never added
  #       * they are not side-loaded when incremental_install=true.
  #       * load_library_from_apk, use_chromium_linker,
  #         and enable_relocation_packing do not apply
  #     Use this instead of shared_libraries when you are going to load the library
  #     conditionally, and only when shared_libraries doesn't work for you.
  #   secondary_abi_loadable_modules: This is the loadable_modules analog to
  #     secondary_abi_shared_libraries.
  #   shared_libraries: List shared_library targets to bundle. If these
  #     libraries depend on other shared_library targets, those dependencies will
  #     also be included in the apk (e.g. for is_component_build).
  #   secondary_abi_shared_libraries: secondary abi shared_library targets to
  #     bundle. If these libraries depend on other shared_library targets, those
  #     dependencies will also be included in the apk (e.g. for is_component_build).
  #   native_lib_placeholders: List of placeholder filenames to add to the apk
  #     (optional).
  #   secondary_native_lib_placeholders: List of placeholder filenames to add to
  #     the apk for the secondary ABI (optional).
  #   generate_buildconfig_java: If defined and false, skip generating the
  #     BuildConfig java class describing the build configuration. The default
  #     is true when building with Chromium for non-test APKs.
  #   generate_final_jni: If defined and false, skip generating the
  #     GEN_JNI srcjar.
  #   jni_registration_header: If specified, causes the
  #     ${target_name}__final_jni target to additionally output a
  #     header file to this path for use with manual JNI registration.
  #   jni_sources_exclusions: List of source path to exclude from the
  #     final_jni step.
  #   aapt_locale_allowlist: If set, all locales not in this list will be
  #     stripped from resources.arsc.
  #   resource_exclusion_regex: Causes all drawable images matching the regex to
  #     be excluded (mipmaps are still included).
  #   resource_exclusion_exceptions: A list of globs used when
  #     resource_exclusion_regex is set. Files that match this list will
  #     still be included.
  #   resource_values_filter_rules: List of "source_path:name_regex" used to
  #     filter out unwanted values/ resources.
  #   shared_resources: True if this is a runtime shared library APK, like
  #     the system_webview_apk target. Ensures that its resources can be
  #     used by the loading application process.
  #   app_as_shared_lib: True if this is a regular application apk that can
  #     also serve as a runtime shared library, like the monochrome_public_apk
  #     target. Ensures that the resources are usable both by the APK running
  #     as an application, or by another process that loads it at runtime.
  #   shared_resources_allowlist_target: Optional name of a target specifying
  #     an input R.txt file that lists the resources that can be exported
  #     by the APK when shared_resources or app_as_shared_lib is defined.
  #   uncompress_shared_libraries: True if shared libraries should be stored
  #     uncompressed in the APK. Must be unset or true if load_library_from_apk
  #     is set to true.
  #   uncompress_dex: Store final .dex files uncompressed in the apk.
  #   strip_resource_names: True if resource names should be stripped from the
  #     resources.arsc file in the apk or module.
  #   strip_unused_resources: True if unused resources should be stripped from
  #     the apk or module.
  #   short_resource_paths: True if resource paths should be shortened in the
  #     apk or module.
  #   resources_config_paths: List of paths to the aapt2 optimize config files
  #     that tags resources with acceptable/non-acceptable optimizations.
  #   expected_android_manifest: Enables verification of expected merged
  #     manifest based on a golden file.
  #   resource_ids_provider_dep: If passed, this target will use the resource
  #     IDs generated by {resource_ids_provider_dep}__compile_res during
  #     resource compilation.
  #   enforce_resource_overlays_in_tests: Enables check for testonly targets that
  #     dependent resource targets which override another target set
  #     overlay_resources=true. This check is on for non-test targets and
  #     cannot be disabled.
  #   static_library_dependent_targets: A list of scopes describing targets that
  #     use this target as a static library. Common Java code from the targets
  #     listed in static_library_dependent_targets will be moved into this
  #     target. Scope members are name and is_resource_ids_provider.
  #   static_library_provider: Specifies a single target that this target will
  #     use as a static library APK.
  #   static_library_synchronized_proguard: When proguard is enabled, the
  #     static_library_provider target will provide the dex file(s) for this
  #     target.
  #   min_sdk_version: The minimum Android SDK version this target supports.
  #     Optional, default $default_min_sdk_version.
  #   target_sdk_version: The target Android SDK version for this target.
  #     Optional, default to android_sdk_version.
  #   max_sdk_version: The maximum Android SDK version this target supports.
  #     Optional, default not set.
  #   require_native_mocks: Enforce that any native calls using
  #     org.chromium.base.annotations.NativeMethods must have a mock set
  #     (optional).
  #   enable_native_mocks: Allow native calls using
  #     org.chromium.base.annotations.NativeMethods to be mocked in tests
  #     (optional).
  #   product_config_java_packages: Optional list of java packages. If given, a
  #     ProductConfig.java file will be generated for each package.
  #   enable_proguard_checks: Turns on -checkdiscard directives and missing
  #     symbols check in the proguard step (default=true).
  #   disable_r8_outlining: Turn off outlining during the proguard step.
  #   annotation_processor_deps: List of java_annotation_processor targets to
  #     use when compiling the sources given to this target (optional).
  #   processor_args_javac: List of args to pass to annotation processors when
  #     compiling sources given to this target (optional).
  #   bundles_supported: Enable Java code to treat this target as a bundle
  #     whether (by default determined by the target type).
  #   main_component_library: Specifies the name of the base component's library
  #     in a component build. If given, the system will find dependent native
  #     libraries at runtime by inspecting this library (optional).
  #   expected_libs_and_assets: Verify the list of included native libraries
  #     and assets is consistent with the given expectation file.
  #   expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff
  #     with this file as the base.
  #   expected_proguard_config: Checks that the merged set of proguard flags
  #     matches the given config.
  #   expected_proguard_config_base: Treat expected_proguard_config as a diff
  #     with this file as the base.
  template("android_apk_or_module") {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    assert(defined(invoker.android_manifest))
    _base_path = "$target_out_dir/$target_name/$target_name"
    _build_config = "$target_gen_dir/$target_name.build_config.json"
    _build_config_target = "$target_name$build_config_target_suffix"

    _min_sdk_version = default_min_sdk_version
    _target_sdk_version = android_sdk_version
    if (defined(invoker.min_sdk_version)) {
      _min_sdk_version = invoker.min_sdk_version
    }
    if (defined(invoker.target_sdk_version)) {
      _target_sdk_version = invoker.target_sdk_version
    }

    _template_name = target_name

    _is_bundle_module =
        defined(invoker.is_bundle_module) && invoker.is_bundle_module
    if (_is_bundle_module) {
      _is_base_module =
          defined(invoker.is_base_module) && invoker.is_base_module
    }

    _enable_multidex =
        !defined(invoker.enable_multidex) || invoker.enable_multidex

    if (!_is_bundle_module) {
      _final_apk_path = invoker.final_apk_path
      _final_rtxt_path = "${_final_apk_path}.R.txt"
    }

    _res_size_info_path = "$target_out_dir/$target_name.ap_.info"
    if (!_is_bundle_module) {
      _final_apk_path_no_ext_list =
          process_file_template([ _final_apk_path ],
                                "{{source_dir}}/{{source_name_part}}")
      _final_apk_path_no_ext = _final_apk_path_no_ext_list[0]
      not_needed([ "_final_apk_path_no_ext" ])
    }

    # Non-base bundle modules create only proto resources.
    if (!_is_bundle_module || _is_base_module) {
      _arsc_resources_path = "$target_out_dir/$target_name.ap_"
    }
    if (_is_bundle_module) {
      # Path to the intermediate proto-format resources zip file.
      _proto_resources_path = "$target_out_dir/$target_name.proto.ap_"
    } else {
      # resource_sizes.py needs to be able to find the unpacked resources.arsc
      # file based on apk name to compute normatlized size.
      _resource_sizes_arsc_path =
          "$root_out_dir/arsc/" +
          rebase_path(_final_apk_path_no_ext, root_build_dir) + ".ap_"
    }

    if (defined(invoker.version_code)) {
      _version_code = invoker.version_code
    } else {
      _version_code = android_default_version_code
    }

    if (android_override_version_code != "") {
      _version_code = android_override_version_code
    }

    if (defined(invoker.version_name)) {
      _version_name = invoker.version_name
    } else {
      _version_name = android_default_version_name
    }

    if (android_override_version_name != "") {
      _version_name = android_override_version_name
    }

    _deps = []
    if (defined(invoker.deps)) {
      _deps = invoker.deps
    }

    _srcjar_deps = []
    if (defined(invoker.srcjar_deps)) {
      _srcjar_deps = invoker.srcjar_deps
    }

    _android_root_manifest_deps = []
    if (defined(invoker.android_manifest_dep)) {
      _android_root_manifest_deps = [ invoker.android_manifest_dep ]
    }
    _android_root_manifest = invoker.android_manifest

    _use_chromium_linker =
        defined(invoker.use_chromium_linker) && invoker.use_chromium_linker
    _use_modern_linker =
        defined(invoker.use_modern_linker) && invoker.use_modern_linker

    _load_library_from_apk =
        defined(invoker.load_library_from_apk) && invoker.load_library_from_apk

    not_needed([
                 "_use_chromium_linker",
                 "_use_modern_linker",
               ])
    assert(!_load_library_from_apk || _use_chromium_linker,
           "load_library_from_apk requires use_chromium_linker")

    # Make sure that uncompress_shared_libraries is set to true if
    # load_library_from_apk is true.
    if (defined(invoker.uncompress_shared_libraries)) {
      _uncompress_shared_libraries = invoker.uncompress_shared_libraries
      assert(!_load_library_from_apk || _uncompress_shared_libraries)
    } else {
      _uncompress_shared_libraries = _load_library_from_apk
    }

    # The dependency that makes the chromium linker, if any is needed.
    _native_libs_deps = []
    _shared_libraries_is_valid =
        defined(invoker.shared_libraries) && invoker.shared_libraries != []

    if (_shared_libraries_is_valid) {
      _native_libs_deps += invoker.shared_libraries

      # Write shared library output files of all dependencies to a file. Those
      # will be the shared libraries packaged into the APK.
      _shared_library_list_file =
          "$target_gen_dir/${_template_name}.native_libs"
      generated_file("${_template_name}__shared_library_list") {
        deps = _native_libs_deps
        outputs = [ _shared_library_list_file ]
        data_keys = [ "shared_libraries" ]
        walk_keys = [ "shared_libraries_barrier" ]
        rebase = root_build_dir
      }
    } else {
      # Must exist for instrumentation_test_apk() to depend on.
      group("${_template_name}__shared_library_list") {
      }
    }

    _secondary_abi_native_libs_deps = []

    if (defined(invoker.secondary_abi_shared_libraries) &&
        invoker.secondary_abi_shared_libraries != []) {
      _secondary_abi_native_libs_deps = invoker.secondary_abi_shared_libraries

      # Write shared library output files of all dependencies to a file. Those
      # will be the shared libraries packaged into the APK.
      _secondary_abi_shared_library_list_file =
          "$target_gen_dir/${_template_name}.secondary_abi_native_libs"
      generated_file("${_template_name}__secondary_abi_shared_library_list") {
        deps = _secondary_abi_native_libs_deps
        outputs = [ _secondary_abi_shared_library_list_file ]
        data_keys = [ "shared_libraries" ]
        walk_keys = [ "shared_libraries_barrier" ]
        rebase = root_build_dir
      }
    } else {
      # Must exist for instrumentation_test_apk() to depend on.
      group("${_template_name}__secondary_abi_shared_library_list") {
      }
    }

    _rebased_build_config = rebase_path(_build_config, root_build_dir)
    assert(_rebased_build_config != "")  # Mark as used.

    _generate_buildconfig_java = !defined(invoker.apk_under_test)
    if (defined(invoker.generate_buildconfig_java)) {
      _generate_buildconfig_java = invoker.generate_buildconfig_java
    }

    _generate_productconfig_java = defined(invoker.product_config_java_packages)

    # JNI generation usually goes hand-in-hand with buildconfig generation.
    _generate_final_jni = _generate_buildconfig_java
    if (defined(invoker.generate_final_jni)) {
      _generate_final_jni = invoker.generate_final_jni
    }

    _proguard_enabled =
        defined(invoker.proguard_enabled) && invoker.proguard_enabled

    if (!_is_bundle_module && _proguard_enabled) {
      _proguard_mapping_path = "$_final_apk_path.mapping"
    }

    # TODO(http://crbug.com/901465): Move shared Java code to static libraries
    # when !_proguard_enabled too.
    _is_static_library_provider =
        defined(invoker.static_library_dependent_targets) && _proguard_enabled
    if (_is_static_library_provider) {
      _static_library_sync_dex_path = "$_base_path.synchronized.r8dex.jar"
      _resource_ids_provider_deps = []
      foreach(_target, invoker.static_library_dependent_targets) {
        if (_target.is_resource_ids_provider) {
          assert(_resource_ids_provider_deps == [],
                 "Can only have 1 resource_ids_provider_dep")
          _resource_ids_provider_deps += [ _target.name ]
        }
      }
      _resource_ids_provider_dep = _resource_ids_provider_deps[0]
    } else if (defined(invoker.resource_ids_provider_dep)) {
      _resource_ids_provider_dep = invoker.resource_ids_provider_dep
    }

    if (_is_static_library_provider) {
      _shared_resources_allowlist_target = _resource_ids_provider_dep
    } else if (defined(invoker.shared_resources_allowlist_target)) {
      _shared_resources_allowlist_target =
          invoker.shared_resources_allowlist_target
    }

    _uses_static_library = defined(invoker.static_library_provider)
    _uses_static_library_synchronized_proguard =
        defined(invoker.static_library_synchronized_proguard) &&
        invoker.static_library_synchronized_proguard

    if (_uses_static_library_synchronized_proguard) {
      assert(_uses_static_library)

      # These will be provided by the static library APK.
      _generate_buildconfig_java = false
      _generate_final_jni = false
    }

    # TODO(crbug.com/864142): Allow incremental installs of bundle modules.
    _incremental_apk = !_is_bundle_module &&
                       !(defined(invoker.never_incremental) &&
                         invoker.never_incremental) && incremental_install
    if (_incremental_apk) {
      _target_dir_name = get_label_info(target_name, "dir")
      _incremental_install_json_path = "$root_out_dir/gen.runtime/$_target_dir_name/$target_name.incremental.json"
      _incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk"
    }

    if (!_incremental_apk) {
      # Bundle modules don't build the dex here, but need to write this path
      # to their .build_config.json file.
      if (_proguard_enabled) {
        _final_dex_path = "$_base_path.r8dex.jar"
      } else {
        _final_dex_path = "$_base_path.mergeddex.jar"
      }
    }

    _android_manifest =
        "$target_gen_dir/${_template_name}_manifest/AndroidManifest.xml"
    _merge_manifest_target = "${_template_name}__merge_manifests"
    merge_manifests(_merge_manifest_target) {
      forward_variables_from(invoker,
                             [
                               "manifest_package",
                               "max_sdk_version",
                             ])
      input_manifest = _android_root_manifest
      output_manifest = _android_manifest
      build_config = _build_config
      min_sdk_version = _min_sdk_version
      target_sdk_version = _target_sdk_version
      deps = _android_root_manifest_deps + [ ":$_build_config_target" ]
    }

    _final_deps = []

    _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21
    if (_enable_main_dex_list) {
      _generated_proguard_main_dex_config =
          "$_base_path.resources.main-dex-proguard.txt"
    }
    _generated_proguard_config = "$_base_path.resources.proguard.txt"

    if (_generate_buildconfig_java &&
        defined(invoker.product_version_resources_dep)) {
      # Needs to be added as a .build_config.json dep to pick up resources.
      _deps += [ invoker.product_version_resources_dep ]
    }

    if (defined(invoker.alternative_android_sdk_dep)) {
      _android_sdk_dep = invoker.alternative_android_sdk_dep
    } else {
      _android_sdk_dep = "//third_party/android_sdk:android_sdk_java"
    }

    if (defined(_shared_resources_allowlist_target)) {
      _allowlist_gen_dir =
          get_label_info(_shared_resources_allowlist_target, "target_gen_dir")
      _allowlist_target_name =
          get_label_info(_shared_resources_allowlist_target, "name")
      _allowlist_r_txt_path =
          "${_allowlist_gen_dir}/${_allowlist_target_name}" +
          "__compile_resources_R.txt"
      _allowlist_deps =
          "${_shared_resources_allowlist_target}__compile_resources"
    }

    _compile_resources_target = "${_template_name}__compile_resources"
    _compile_resources_rtxt_out =
        "${target_gen_dir}/${_compile_resources_target}_R.txt"
    _compile_resources_emit_ids_out =
        "${target_gen_dir}/${_compile_resources_target}.resource_ids"
    compile_resources(_compile_resources_target) {
      forward_variables_from(invoker,
                             [
                               "aapt_locale_allowlist",
                               "app_as_shared_lib",
                               "enforce_resource_overlays_in_tests",
                               "expected_android_manifest",
                               "expected_android_manifest_base",
                               "extra_verification_manifest",
                               "extra_verification_manifest_dep",
                               "manifest_package",
                               "max_sdk_version",
                               "no_xml_namespaces",
                               "package_id",
                               "package_name",
                               "png_to_webp",
                               "r_java_root_package_name",
                               "resource_exclusion_exceptions",
                               "resource_exclusion_regex",
                               "resource_values_filter_rules",
                               "shared_resources",
                               "shared_resources_allowlist_locales",
                               "uses_split",
                             ])
      android_manifest = _android_manifest
      android_manifest_dep = ":$_merge_manifest_target"
      version_code = _version_code
      version_name = _version_name
      min_sdk_version = _min_sdk_version
      target_sdk_version = _target_sdk_version

      if (defined(expected_android_manifest)) {
        top_target_name = _template_name
      }

      if (defined(_resource_ids_provider_dep)) {
        resource_ids_provider_dep = _resource_ids_provider_dep
      }

      if (defined(invoker.post_process_package_resources_script)) {
        post_process_script = invoker.post_process_package_resources_script
      }
      r_text_out_path = _compile_resources_rtxt_out
      emit_ids_out_path = _compile_resources_emit_ids_out
      size_info_path = _res_size_info_path
      proguard_file = _generated_proguard_config
      if (_enable_main_dex_list) {
        proguard_file_main_dex = _generated_proguard_main_dex_config
      }

      build_config = _build_config
      build_config_dep = ":$_build_config_target"
      android_sdk_dep = _android_sdk_dep
      deps = _deps

      # The static library uses the R.txt files generated by the
      # static_library_dependent_targets when generating the final R.java file.
      if (_is_static_library_provider) {
        foreach(_dep, invoker.static_library_dependent_targets) {
          deps += [ "${_dep.name}__compile_resources" ]
        }
      }

      if (defined(invoker.apk_under_test)) {
        # Set the arsc package name to match the apk_under_test package name
        # So that test resources can references under_test resources via
        # @type/name syntax.
        r_java_root_package_name = "test"
        arsc_package_name =
            "@FileArg($_rebased_build_config:deps_info:arsc_package_name)"

        # Passing in the --emit-ids mapping will cause aapt2 to assign resources
        # IDs that do not conflict with those from apk_under_test.
        assert(!defined(resource_ids_provider_dep))
        resource_ids_provider_dep = invoker.apk_under_test

        include_resource =
            get_label_info(invoker.apk_under_test, "target_out_dir") + "/" +
            get_label_info(invoker.apk_under_test, "name") + ".ap_"
        _link_against = invoker.apk_under_test
      }

      if (_is_bundle_module) {
        is_bundle_module = true
        proto_output = _proto_resources_path

        if (defined(invoker.base_module_target)) {
          include_resource =
              get_label_info(invoker.base_module_target, "target_out_dir") +
              "/" + get_label_info(invoker.base_module_target, "name") + ".ap_"
          _link_against = invoker.base_module_target
        }
      }

      if (defined(_link_against)) {
        deps += [ "${_link_against}__compile_resources" ]
        include_resource = get_label_info(_link_against, "target_out_dir") +
                           "/" + get_label_info(_link_against, "name") + ".ap_"
      }

      # Bundle modules have to reference resources from the base module.
      if (!_is_bundle_module || _is_base_module) {
        arsc_output = _arsc_resources_path
      }

      if (defined(_shared_resources_allowlist_target)) {
        # Used to ensure that the WebView resources are properly shared
        # (i.e. are non-final and with package ID 0).
        shared_resources_allowlist = _allowlist_r_txt_path
        deps += [ _allowlist_deps ]
      }
    }
    _srcjar_deps += [ ":$_compile_resources_target" ]

    # We don't ship apks anymore, only optimize bundle builds
    if (_is_bundle_module) {
      _short_resource_paths =
          defined(invoker.short_resource_paths) &&
          invoker.short_resource_paths && enable_arsc_obfuscation
      _strip_resource_names =
          defined(invoker.strip_resource_names) &&
          invoker.strip_resource_names && enable_arsc_obfuscation
      _strip_unused_resources = defined(invoker.strip_unused_resources) &&
                                invoker.strip_unused_resources
      _optimize_resources = _strip_resource_names || _short_resource_paths ||
                            _strip_unused_resources
    }

    if (_is_bundle_module && _optimize_resources) {
      _optimized_proto_resources_path =
          "$target_out_dir/$target_name.optimized.proto.ap_"
      if (_short_resource_paths) {
        _resources_path_map_out_path =
            "${target_gen_dir}/${_template_name}_resources_path_map.txt"
      }
      _optimize_resources_target = "${_template_name}__optimize_resources"
      optimize_resources(_optimize_resources_target) {
        deps = _deps + [ ":$_compile_resources_target" ]
        short_resource_paths = _short_resource_paths
        strip_resource_names = _strip_resource_names
        if (_short_resource_paths) {
          resources_path_map_out_path = _resources_path_map_out_path
        }
        r_text_path = _compile_resources_rtxt_out
        proto_input_path = _proto_resources_path
        optimized_proto_output = _optimized_proto_resources_path
        if (_strip_unused_resources) {
          # These need to be kept in sync with the target names + output paths
          # in the android_app_bundle template.
          _unused_resources_target = "${_template_name}__unused_resources"
          _unused_resources_config_path =
              "$target_gen_dir/${_template_name}_unused_resources.config"
          resources_config_paths = [ _unused_resources_config_path ]
          deps += [ ":$_unused_resources_target" ]
        } else {
          resources_config_paths = []
        }
        if (defined(invoker.resources_config_paths)) {
          resources_config_paths += invoker.resources_config_paths
        }
      }
    }

    if (!_is_bundle_module) {
      # Output the R.txt file to a more easily discoverable location for
      # archiving. This is necessary when stripping resource names so that we
      # have an archive of resource names to ids for shipped apks (for
      # debugging purposes). We copy the file rather than change the location
      # of the original because other targets rely on the location of the R.txt
      # file.
      _copy_rtxt_target = "${_template_name}__copy_rtxt"
      copy(_copy_rtxt_target) {
        deps = [ ":$_compile_resources_target" ]
        sources = [ _compile_resources_rtxt_out ]
        outputs = [ _final_rtxt_path ]
      }
      _final_deps += [ ":$_copy_rtxt_target" ]
    }

    if (defined(_resource_sizes_arsc_path)) {
      _copy_arsc_target = "${_template_name}__copy_arsc"
      copy(_copy_arsc_target) {
        deps = [ ":$_compile_resources_target" ]

        # resource_sizes.py doesn't care if it gets the optimized .arsc.
        sources = [ _arsc_resources_path ]
        outputs = [ _resource_sizes_arsc_path ]
      }
      _final_deps += [ ":$_copy_arsc_target" ]
    }

    _generate_native_libraries_java =
        (!_is_bundle_module || _is_base_module) &&
        (_native_libs_deps != [] || _secondary_abi_native_libs_deps != []) &&
        !_uses_static_library_synchronized_proguard
    if (_generate_native_libraries_java) {
      write_native_libraries_java("${_template_name}__native_libraries") {
        forward_variables_from(invoker, [ "main_component_library" ])

        # Do not add a dep on the generated_file target in order to avoid having
        # to build the native libraries before this target. The dependency is
        # instead captured via a depfile.
        if (_native_libs_deps != []) {
          native_libraries_list_file = _shared_library_list_file
        } else {
          native_libraries_list_file = _secondary_abi_shared_library_list_file
        }
        enable_chromium_linker = _use_chromium_linker
        load_library_from_apk = _load_library_from_apk
        use_modern_linker = _use_modern_linker
        use_final_fields = true
      }
      _srcjar_deps += [ ":${_template_name}__native_libraries" ]
    }

    _loadable_modules = []
    if (defined(invoker.loadable_modules)) {
      _loadable_modules = invoker.loadable_modules
    }

    if (_native_libs_deps != []) {
      _loadable_modules += _sanitizer_runtimes
    }

    if (_generate_buildconfig_java) {
      generate_build_config_srcjar("${_template_name}__build_config_srcjar") {
        forward_variables_from(invoker,
                               [
                                 "min_sdk_version",
                                 "isolated_splits_enabled",
                               ])
        _bundles_supported = _is_bundle_module || _is_static_library_provider
        if (defined(invoker.bundles_supported)) {
          _bundles_supported = invoker.bundles_supported
        }
        bundles_supported = _bundles_supported
        use_final_fields = true
        enable_multidex = _enable_multidex
        is_incremental_install = _incremental_apk
        if (defined(invoker.product_version_resources_dep)) {
          resources_version_variable =
              "org.chromium.base.R.string.product_version"
        }
        deps = [ ":$_build_config_target" ]
      }
      _srcjar_deps += [ ":${_template_name}__build_config_srcjar" ]
    }

    if (_generate_productconfig_java) {
      foreach(_package, invoker.product_config_java_packages) {
        _locale_target_name =
            "${_template_name}_${_package}__product_config_srcjar"
        generate_product_config_srcjar("$_locale_target_name") {
          forward_variables_from(invoker, [ "is_bundle_module" ])
          build_config = _build_config
          java_package = _package
          use_chromium_linker = _use_chromium_linker
          use_modern_linker = _use_modern_linker
          deps = [ ":$_build_config_target" ]
        }
        _srcjar_deps += [ ":$_locale_target_name" ]
      }
    }

    if (_generate_final_jni) {
      generate_jni_registration("${_template_name}__final_jni") {
        forward_variables_from(invoker,
                               [
                                 "enable_native_mocks",
                                 "require_native_mocks",
                               ])
        if (defined(invoker.bundle_target)) {
          targets = [ invoker.bundle_target ]
        } else {
          targets = [ ":$_template_name" ]
        }
        if (_is_static_library_provider) {
          foreach(_target, invoker.static_library_dependent_targets) {
            targets += [ _target.name ]
          }
        }
        if (defined(invoker.jni_registration_header)) {
          header_output = invoker.jni_registration_header
        }
        if (defined(invoker.jni_sources_exclusions)) {
          sources_exclusions = invoker.jni_sources_exclusions
        }
      }
      _srcjar_deps += [ ":${_template_name}__final_jni" ]
    } else {
      not_needed(invoker,
                 [
                   "enable_native_mocks",
                   "jni_registration_header",
                 ])
    }

    _java_target = "${_template_name}__java"

    java_library_impl(_java_target) {
      forward_variables_from(invoker,
                             [
                               "alternative_android_sdk_dep",
                               "android_manifest",
                               "android_manifest_dep",
                               "annotation_processor_deps",
                               "apk_under_test",
                               "base_module_target",
                               "chromium_code",
                               "jacoco_never_instrument",
                               "jar_excluded_patterns",
                               "javac_args",
                               "native_lib_placeholders",
                               "processor_args_javac",
                               "secondary_abi_loadable_modules",
                               "secondary_native_lib_placeholders",
                               "sources",
                               "static_library_dependent_targets",
                               "use_classic_desugar",
                               "library_always_compress",
                               "library_renames",
                             ])
      deps = _deps
      if (_uses_static_library_synchronized_proguard) {
        if (!defined(jar_excluded_patterns)) {
          jar_excluded_patterns = []
        }

        # The static library will provide all R.java files, but we still need to
        # make the base module R.java files available at compile time since DFM
        # R.java classes extend base module classes.
        jar_excluded_patterns += [
          "*/R.class",
          "*/R\$*.class",
        ]
      }
      if (_is_bundle_module) {
        type = "android_app_bundle_module"
        res_size_info_path = _res_size_info_path
        is_base_module = _is_base_module
        forward_variables_from(invoker,
                               [
                                 "version_code",
                                 "version_name",
                               ])
      } else {
        type = "android_apk"
      }
      r_text_path = _compile_resources_rtxt_out
      main_target_name = _template_name
      supports_android = true
      requires_android = true
      srcjar_deps = _srcjar_deps
      merged_android_manifest = _android_manifest
      if (defined(_final_dex_path)) {
        final_dex_path = _final_dex_path
      }

      if (_is_bundle_module) {
        proto_resources_path = _proto_resources_path
        if (_optimize_resources) {
          proto_resources_path = _optimized_proto_resources_path
          if (_short_resource_paths) {
            module_pathmap_path = _resources_path_map_out_path
          }
        }
      } else {
        apk_path = _final_apk_path
        if (_incremental_apk) {
          incremental_apk_path = _incremental_apk_path
          incremental_install_json_path = _incremental_install_json_path
        }
      }

      proguard_enabled = _proguard_enabled
      if (_proguard_enabled) {
        proguard_configs = [ _generated_proguard_config ]
        if (defined(invoker.proguard_configs)) {
          proguard_configs += invoker.proguard_configs
        }
        if (!enable_java_asserts && (!defined(testonly) || !testonly) &&
            # Injected JaCoCo code causes -checkdiscards to fail.
            !use_jacoco_coverage) {
          proguard_configs += [ "//chromium/build/android/dcheck_is_off.flags" ]
        }
        if (!_is_bundle_module) {
          proguard_mapping_path = _proguard_mapping_path
        }
      }

      # Do not add a dep on the generated_file target in order to avoid having
      # to build the native libraries before this target. The dependency is
      # instead captured via a depfile.
      if (_native_libs_deps != []) {
        shared_libraries_runtime_deps_file = _shared_library_list_file
      }
      if (defined(_secondary_abi_shared_library_list_file)) {
        secondary_abi_shared_libraries_runtime_deps_file =
            _secondary_abi_shared_library_list_file
      }

      loadable_modules = _loadable_modules

      uncompress_shared_libraries = _uncompress_shared_libraries

      if (defined(_allowlist_r_txt_path) && _is_bundle_module) {
        # Used to write the file path to the target's .build_config.json only.
        base_allowlist_rtxt_path = _allowlist_r_txt_path
      }
    }

    # TODO(cjhopman): This is only ever needed to calculate the list of tests to
    # run. See build/android/pylib/instrumentation/test_jar.py. We should be
    # able to just do that calculation at build time instead.
    if (defined(invoker.dist_ijar_path)) {
      _dist_ijar_path = invoker.dist_ijar_path
      dist_jar("${_template_name}_dist_ijar") {
        override_build_config = _build_config
        output = _dist_ijar_path
        data = [ _dist_ijar_path ]
        use_interface_jars = true
        deps = [
          ":$_build_config_target",
          ":$_java_target",
        ]
      }
    }

    if (_uses_static_library_synchronized_proguard) {
      _final_dex_target_dep = "${invoker.static_library_provider}__dexsplitter"
    } else if (_is_bundle_module && _proguard_enabled) {
      _final_deps += [ ":$_java_target" ]
    } else if (_incremental_apk) {
      if (defined(invoker.enable_proguard_checks)) {
        not_needed(invoker, [ "enable_proguard_checks" ])
      }
      if (defined(invoker.disable_r8_outlining)) {
        not_needed(invoker, [ "disable_r8_outlining" ])
      }
      if (defined(invoker.dexlayout_profile)) {
        not_needed(invoker, [ "dexlayout_profile" ])
      }
    } else {
      # Dex generation for app bundle modules with proguarding enabled takes
      # place later due to synchronized proguarding.
      _final_dex_target_name = "${_template_name}__final_dex"
      dex(_final_dex_target_name) {
        forward_variables_from(invoker,
                               [
                                 "disable_r8_outlining",
                                 "dexlayout_profile",
                                 "enable_proguard_checks",
                                 "proguard_enable_obfuscation",
                               ])
        min_sdk_version = _min_sdk_version
        proguard_enabled = _proguard_enabled
        build_config = _build_config
        deps = [
          ":$_build_config_target",
          ":$_java_target",
        ]
        if (_proguard_enabled) {
          deps += _deps + [ ":$_compile_resources_target" ]
          proguard_mapping_path = _proguard_mapping_path
          proguard_sourcefile_suffix = "$android_channel-$_version_code"
          has_apk_under_test = defined(invoker.apk_under_test)
        } else if (_min_sdk_version >= default_min_sdk_version) {
          # Enable dex merging only when min_sdk_version is >= what the library
          # .dex files were created with.
          input_dex_filearg =
              "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)"
        } else {
          input_classes_filearg =
              "@FileArg($_rebased_build_config:deps_info:device_classpath)"
        }

        if (_is_static_library_provider) {
          # The list of input jars is already recorded in the .build_config.json, but
          # we need to explicitly add the java deps here to ensure they're
          # available to be used as inputs to the dex step.
          foreach(_dep, invoker.static_library_dependent_targets) {
            _target_label = get_label_info(_dep.name, "label_no_toolchain")
            deps += [ "${_target_label}__java" ]
          }
          output = _static_library_sync_dex_path
          is_static_library = true
        } else {
          output = _final_dex_path
        }
        enable_multidex = _enable_multidex

        # The individual dependencies would have caught real missing deps in
        # their respective dex steps. False positives that were suppressed at
        # per-target dex steps are emitted here since this may use jar files
        # rather than dex files.
        ignore_desugar_missing_deps = true

        if (_enable_main_dex_list) {
          extra_main_dex_proguard_config = _generated_proguard_main_dex_config
          deps += [ ":$_compile_resources_target" ]
        }
      }

      _final_dex_target_dep = ":$_final_dex_target_name"

      # For static libraries, a single Proguard run is performed that includes
      # code from the static library APK and the APKs that use the static
      # library (done via. classpath merging in write_build_config.py).
      # This dexsplitter target splits the synchronized dex output into dex
      # files for each APK/Bundle. In the Bundle case, another dexsplitter step
      # is later performed to split the dex further for each feature module.
      if (_is_static_library_provider && _proguard_enabled) {
        _static_library_modules = []
        foreach(_target, invoker.static_library_dependent_targets) {
          _apk_as_module = _target.name
          _module_config_target = "${_apk_as_module}$build_config_target_suffix"
          _module_gen_dir = get_label_info(_apk_as_module, "target_gen_dir")
          _module_name = get_label_info(_apk_as_module, "name")
          _module_config = "$_module_gen_dir/$_module_name.build_config.json"
          _static_library_modules += [
            {
              name = _module_name
              build_config = _module_config
              build_config_target = _module_config_target
            },
          ]
        }

        _static_library_dexsplitter_target = "${_template_name}__dexsplitter"
        dexsplitter(_static_library_dexsplitter_target) {
          input_dex_zip = _static_library_sync_dex_path
          proguard_mapping = _proguard_mapping_path
          deps = [
            ":$_build_config_target",
            "$_final_dex_target_dep",
          ]
          all_modules = [
                          {
                            name = "base"
                            build_config = _build_config
                            build_config_target = ":$_build_config_target"
                          },
                        ] + _static_library_modules
          feature_jars_args = [
            "--feature-jars",
            "@FileArg($_rebased_build_config:deps_info:" +
                "static_library_dependent_classpath_configs:" +
                "$_rebased_build_config)",
          ]
          foreach(_module, _static_library_modules) {
            _rebased_module_config =
                rebase_path(_module.build_config, root_build_dir)
            feature_jars_args += [
              "--feature-jars",
              "@FileArg($_rebased_build_config:deps_info:" +
                  "static_library_dependent_classpath_configs:" +
                  "$_rebased_module_config)",
            ]
          }
        }
        _final_deps += [ ":$_static_library_dexsplitter_target" ]
        _validate_dex_target = "${_template_name}__validate_dex"
        action_with_pydeps(_validate_dex_target) {
          depfile = "$target_gen_dir/$target_name.d"
          script =
              "//chromium/build/android/gyp/validate_static_library_dex_references.py"
          inputs = [ _build_config ]
          _stamp = "$target_gen_dir/$target_name.stamp"
          outputs = [ _stamp ]
          deps = [
            ":$_build_config_target",
            ":$_static_library_dexsplitter_target",
          ]
          args = [
            "--depfile",
            rebase_path(depfile, root_build_dir),
            "--stamp",
            rebase_path(_stamp, root_build_dir),
            "--static-library-dex",
            "@FileArg($_rebased_build_config:final_dex:path)",
          ]
          foreach(_module, _static_library_modules) {
            inputs += [ _module.build_config ]
            _rebased_config = rebase_path(_module.build_config, root_build_dir)
            deps += [ _module.build_config_target ]
            args += [
              "--static-library-dependent-dex",
              "@FileArg($_rebased_config:final_dex:path)",
            ]
          }
        }

        # TODO(crbug.com/1032609): Switch to using R8's support for feature
        # aware ProGuard and get rid of "_validate_dex_target" or figure out
        # why some classes aren't properly being kept.
        # _final_deps += [ ":$_validate_dex_target" ]
        _final_dex_target_dep = ":$_static_library_dexsplitter_target"
      }
    }

    _all_native_libs_deps = _native_libs_deps + _secondary_abi_native_libs_deps
    if (_all_native_libs_deps != []) {
      _native_libs_filearg_dep = ":$_build_config_target"
      _all_native_libs_deps += [ _native_libs_filearg_dep ]

      if (!_is_bundle_module) {
        _native_libs_filearg =
            "@FileArg($_rebased_build_config:native:libraries)"
      }
    }

    if (_is_bundle_module) {
      _final_deps += [
                       ":$_merge_manifest_target",
                       ":$_build_config_target",
                       ":$_compile_resources_target",
                     ] + _all_native_libs_deps
      if (_optimize_resources) {
        _final_deps += [ ":$_optimize_resources_target" ]
      }
      if (defined(_final_dex_target_dep)) {
        not_needed([ "_final_dex_target_dep" ])
      }
    } else {
      # Generate size-info/*.jar.info files.
      if (defined(invoker.name)) {
        # Create size info files for targets that care about size
        # (have proguard enabled).
        _include_size_info =
            defined(invoker.include_size_info) && invoker.include_size_info
        if (_include_size_info || _proguard_enabled) {
          _size_info_target = "${target_name}__size_info"
          create_size_info_files(_size_info_target) {
            name = "${invoker.name}.apk"
            build_config = _build_config
            res_size_info_path = _res_size_info_path
            deps = _deps + [
                     ":$_build_config_target",
                     ":$_compile_resources_target",
                     ":$_java_target",
                   ]
          }
          _final_deps += [ ":$_size_info_target" ]
        } else {
          not_needed(invoker, [ "name" ])
        }
      }

      _keystore_path = android_keystore_path
      _keystore_name = android_keystore_name
      _keystore_password = android_keystore_password

      if (defined(invoker.keystore_path)) {
        _keystore_path = invoker.keystore_path
        _keystore_name = invoker.keystore_name
        _keystore_password = invoker.keystore_password
      }

      if (_incremental_apk) {
        _incremental_compiled_resources_path = "${_base_path}_incremental.ap_"
        _incremental_compile_resources_target_name =
            "${target_name}__compile_incremental_resources"

        action_with_pydeps(_incremental_compile_resources_target_name) {
          deps = [
            ":$_build_config_target",
            ":$_compile_resources_target",
            ":$_merge_manifest_target",
          ]
          script =
              "//chromium/build/android/incremental_install/generate_android_manifest.py"
          inputs = [
            _android_manifest,
            _build_config,
            _arsc_resources_path,
          ]
          outputs = [ _incremental_compiled_resources_path ]

          args = [
            "--disable-isolated-processes",
            "--src-manifest",
            rebase_path(_android_manifest, root_build_dir),
            "--in-apk",
            rebase_path(_arsc_resources_path, root_build_dir),
            "--out-apk",
            rebase_path(_incremental_compiled_resources_path, root_build_dir),
            "--aapt2-path",
            rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir),
            "--android-sdk-jars=@FileArg($_rebased_build_config:android:sdk_jars)",
          ]
        }
      }

      _create_apk_target = "${_template_name}__create"
      _final_deps += [ ":$_create_apk_target" ]
      package_apk("$_create_apk_target") {
        forward_variables_from(invoker,
                               [
                                 "expected_libs_and_assets",
                                 "expected_libs_and_assets_base",
                                 "native_lib_placeholders",
                                 "secondary_abi_loadable_modules",
                                 "secondary_native_lib_placeholders",
                                 "uncompress_dex",
                                 "uncompress_shared_libraries",
                                 "library_always_compress",
                                 "library_renames",
                               ])

        if (defined(expected_libs_and_assets)) {
          build_config_dep = ":$_build_config_target"
          top_target_name = _template_name
        }

        build_config = _build_config
        keystore_name = _keystore_name
        keystore_path = _keystore_path
        keystore_password = _keystore_password
        min_sdk_version = _min_sdk_version
        uncompress_shared_libraries = _uncompress_shared_libraries

        deps = _deps + [ ":$_build_config_target" ]

        if ((!_proguard_enabled || _incremental_apk) &&
            enable_jdk_library_desugaring) {
          _all_jdk_libs = "//chromium/build/android:all_jdk_libs"
          deps += [ _all_jdk_libs ]
          jdk_libs_dex = get_label_info(_all_jdk_libs, "target_out_dir") +
                         "/all_jdk_libs.l8.dex"
        }

        if (_incremental_apk) {
          _dex_target = "//chromium/build/android/incremental_install:apk_dex"

          deps += [
            ":${_incremental_compile_resources_target_name}",
            _dex_target,
          ]

          dex_path = get_label_info(_dex_target, "target_out_dir") + "/apk.dex"

          # All native libraries are side-loaded, so use a placeholder to force
          # the proper bitness for the app.
          _has_native_libs =
              defined(_native_libs_filearg) || _loadable_modules != []
          if (_has_native_libs && !defined(native_lib_placeholders)) {
            native_lib_placeholders = [ "libfix.crbug.384638.so" ]
          }

          packaged_resources_path = _incremental_compiled_resources_path
          output_apk_path = _incremental_apk_path
        } else {
          loadable_modules = _loadable_modules
          deps += _all_native_libs_deps + [
                    ":$_merge_manifest_target",
                    ":$_compile_resources_target",
                  ]

          if (defined(_final_dex_path)) {
            dex_path = _final_dex_path
            deps += [ _final_dex_target_dep ]
          }

          packaged_resources_path = _arsc_resources_path

          if (defined(_native_libs_filearg)) {
            native_libs_filearg = _native_libs_filearg
            secondary_abi_native_libs_filearg = "@FileArg($_rebased_build_config:native:secondary_abi_libraries)"
          }
          output_apk_path = _final_apk_path
        }
      }
    }

    if (_incremental_apk) {
      _write_installer_json_rule_name = "${_template_name}__incremental_json"
      action_with_pydeps(_write_installer_json_rule_name) {
        script = "//chromium/build/android/incremental_install/write_installer_json.py"
        deps = [ ":$_build_config_target" ] + _all_native_libs_deps

        data = [ _incremental_install_json_path ]
        inputs = [ _build_config ]
        outputs = [ _incremental_install_json_path ]

        _rebased_incremental_apk_path =
            rebase_path(_incremental_apk_path, root_build_dir)
        _rebased_incremental_install_json_path =
            rebase_path(_incremental_install_json_path, root_build_dir)
        args = [
          "--apk-path=$_rebased_incremental_apk_path",
          "--output-path=$_rebased_incremental_install_json_path",
          "--dex-file=@FileArg($_rebased_build_config:final_dex:all_dex_files)",
        ]
        if (_proguard_enabled) {
          args += [ "--show-proguard-warning" ]
        }
        if (defined(_native_libs_filearg)) {
          args += [ "--native-libs=$_native_libs_filearg" ]
          deps += [ _native_libs_filearg_dep ]
        }
        if (_loadable_modules != []) {
          _rebased_loadable_modules =
              rebase_path(_loadable_modules, root_build_dir)
          args += [ "--native-libs=$_rebased_loadable_modules" ]
        }
      }
      _final_deps += [
        ":$_java_target",
        ":$_write_installer_json_rule_name",
      ]
    }

    # Generate apk operation related script.
    if (!_is_bundle_module &&
        (!defined(invoker.create_apk_script) || invoker.create_apk_script)) {
      if (_uses_static_library) {
        _install_artifacts_target = "${target_name}__install_artifacts"
        _install_artifacts_json =
            "${target_gen_dir}/${target_name}.install_artifacts"
        generated_file(_install_artifacts_target) {
          output_conversion = "json"
          deps = [ invoker.static_library_provider ]
          outputs = [ _install_artifacts_json ]
          data_keys = [ "install_artifacts" ]
          rebase = root_build_dir
        }
      }
      _apk_operations_target_name = "${target_name}__apk_operations"
      action_with_pydeps(_apk_operations_target_name) {
        _generated_script = "$root_build_dir/bin/${invoker.target_name}"
        script = "//chromium/build/android/gyp/create_apk_operations_script.py"
        outputs = [ _generated_script ]
        args = [
          "--script-output-path",
          rebase_path(_generated_script, root_build_dir),
          "--target-cpu=$target_cpu",
        ]
        if (defined(invoker.command_line_flags_file)) {
          args += [
            "--command-line-flags-file",
            invoker.command_line_flags_file,
          ]
        }
        if (_incremental_apk) {
          args += [
            "--incremental-install-json-path",
            rebase_path(_incremental_install_json_path, root_build_dir),
          ]
        } else {
          args += [
            "--apk-path",
            rebase_path(_final_apk_path, root_build_dir),
          ]
        }
        if (_uses_static_library) {
          deps = [ ":$_install_artifacts_target" ]
          _rebased_install_artifacts_json =
              rebase_path(_install_artifacts_json, root_build_dir)
          _static_library_apk_path =
              "@FileArg($_rebased_install_artifacts_json[])"
          args += [
            "--additional-apk",
            _static_library_apk_path,
          ]
        }
        data = []
        data_deps = [
          "//chromium/build/android:apk_operations_py",
          "//chromium/build/android:stack_tools",
        ]

        if (_proguard_enabled && !_incremental_apk) {
          # Required by logcat command.
          data_deps += [ "//chromium/build/android/stacktrace:java_deobfuscate" ]
          data += [ "$_final_apk_path.mapping" ]
          args += [
            "--proguard-mapping-path",
            rebase_path("$_final_apk_path.mapping", root_build_dir),
          ]
        }
      }
      _final_deps += [ ":$_apk_operations_target_name" ]
    }

    _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint &&
                   !disable_android_lint
    if (_enable_lint) {
      android_lint("${target_name}__lint") {
        forward_variables_from(invoker,
                               [
                                 "lint_baseline_file",
                                 "lint_suppressions_file",
                                 "min_sdk_version",
                               ])
        build_config = _build_config
        build_config_dep = ":$_build_config_target"
        deps = [ ":$_java_target" ]
        if (defined(invoker.lint_suppressions_dep)) {
          deps += [ invoker.lint_suppressions_dep ]
        }
        if (defined(invoker.lint_min_sdk_version)) {
          min_sdk_version = invoker.lint_min_sdk_version
        }
      }
    } else {
      not_needed(invoker,
                 [
                   "lint_baseline_file",
                   "lint_min_sdk_version",
                   "lint_suppressions_dep",
                   "lint_suppressions_file",
                 ])
    }

    group(target_name) {
      forward_variables_from(invoker,
                             [
                               "assert_no_deps",
                               "data",
                               "data_deps",
                               "metadata",
                             ])

      # Generate apk related operations at runtime.
      public_deps = _final_deps

      if (!defined(data_deps)) {
        data_deps = []
      }

      # Include unstripped native libraries so tests can symbolize stacks.
      data_deps += _all_native_libs_deps

      if (_enable_lint) {
        data_deps += [ ":${target_name}__lint" ]
      }

      if (_uses_static_library) {
        data_deps += [ invoker.static_library_provider ]
      }
    }
  }

  # Declare an Android APK target
  #
  # This target creates an Android APK containing java code, resources, assets,
  # and (possibly) native libraries.
  #
  # Supports all variables of android_apk_or_module(), plus:
  #   apk_name: Name for final apk.
  #   final_apk_path: (Optional) path to output APK.
  #
  # Example
  #   android_apk("foo_apk") {
  #     android_manifest = "AndroidManifest.xml"
  #     sources = [
  #       "android/org/chromium/foo/FooApplication.java",
  #       "android/org/chromium/foo/FooActivity.java",
  #     ]
  #     deps = [
  #       ":foo_support_java"
  #       ":foo_resources"
  #     ]
  #     srcjar_deps = [
  #       ":foo_generated_enum"
  #     ]
  #     shared_libraries = [
  #       ":my_shared_lib",
  #     ]
  #   }
  template("android_apk") {
    # TODO(crbug.com/1042017): Remove.
    not_needed(invoker, [ "no_build_hooks" ])
    android_apk_or_module(target_name) {
      forward_variables_from(invoker,
                             [
                               "aapt_locale_allowlist",
                               "additional_jar_files",
                               "alternative_android_sdk_dep",
                               "android_manifest",
                               "android_manifest_dep",
                               "annotation_processor_deps",
                               "apk_under_test",
                               "app_as_shared_lib",
                               "assert_no_deps",
                               "bundles_supported",
                               "chromium_code",
                               "command_line_flags_file",
                               "create_apk_script",
                               "data",
                               "data_deps",
                               "deps",
                               "dexlayout_profile",
                               "disable_r8_outlining",
                               "dist_ijar_path",
                               "enable_lint",
                               "enable_multidex",
                               "enable_native_mocks",
                               "enable_proguard_checks",
                               "enforce_resource_overlays_in_tests",
                               "expected_android_manifest",
                               "expected_android_manifest_base",
                               "expected_libs_and_assets",
                               "expected_libs_and_assets_base",
                               "generate_buildconfig_java",
                               "generate_final_jni",
                               "include_size_info",
                               "input_jars_paths",
                               "use_modern_linker",
                               "jacoco_never_instrument",
                               "javac_args",
                               "jni_registration_header",
                               "jni_sources_exclusions",
                               "keystore_name",
                               "keystore_password",
                               "keystore_path",
                               "lint_baseline_file",
                               "lint_min_sdk_version",
                               "lint_suppressions_dep",
                               "lint_suppressions_file",
                               "load_library_from_apk",
                               "loadable_modules",
                               "manifest_package",
                               "max_sdk_version",
                               "product_config_java_packages",
                               "main_component_library",
                               "min_sdk_version",
                               "native_lib_placeholders",
                               "never_incremental",
                               "no_xml_namespaces",
                               "png_to_webp",
                               "post_process_package_resources_script",
                               "processor_args_javac",
                               "product_version_resources_dep",
                               "proguard_configs",
                               "proguard_enabled",
                               "proguard_enable_obfuscation",
                               "r_java_root_package_name",
                               "resource_exclusion_exceptions",
                               "resource_exclusion_regex",
                               "resource_ids_provider_dep",
                               "resource_values_filter_rules",
                               "require_native_mocks",
                               "secondary_abi_loadable_modules",
                               "secondary_abi_shared_libraries",
                               "secondary_native_lib_placeholders",
                               "shared_libraries",
                               "shared_resources",
                               "shared_resources_allowlist_locales",
                               "shared_resources_allowlist_target",
                               "sources",
                               "srcjar_deps",
                               "static_library_dependent_targets",
                               "static_library_provider",
                               "static_library_synchronized_proguard",
                               "target_sdk_version",
                               "testonly",
                               "uncompress_dex",
                               "uncompress_shared_libraries",
                               "use_classic_desugar",
                               "library_always_compress",
                               "library_renames",
                               "use_chromium_linker",
                               "version_code",
                               "version_name",
                               "visibility",
                             ])
      is_bundle_module = false
      name = invoker.apk_name
      if (defined(invoker.final_apk_path)) {
        final_apk_path = invoker.final_apk_path
      } else {
        final_apk_path = "$root_build_dir/apks/${invoker.apk_name}.apk"
      }
      metadata = {
        install_artifacts = [ final_apk_path ]
      }
      if (defined(invoker.static_library_provider)) {
        metadata.install_artifacts_barrier = []
      }
    }
  }

  # Declare an Android app bundle module target.
  #
  # The module can be used for an android_apk_or_module().
  #
  # Supports all variables of android_library(), plus:
  #   module_name: Name of the module.
  #   is_base_module: If defined and true, indicates that this is the bundle's
  #     base module (optional).
  #   base_module_target: Base module target of the bundle this module will be
  #     added to (optional). Can only be specified for non-base modules.
  #   bundle_target: Bundle target that this module belongs to (optional).
  #     Can only be specified for base modules.
  template("android_app_bundle_module") {
    _is_base_module = defined(invoker.is_base_module) && invoker.is_base_module

    if (_is_base_module) {
      assert(!defined(invoker.base_module_target))
    } else {
      assert(!defined(invoker.app_as_shared_lib))
      assert(!defined(invoker.shared_resources))
      assert(!defined(invoker.shared_resources_allowlist_target))
      assert(!defined(invoker.shared_resources_allowlist_locales))
      assert(defined(invoker.base_module_target))
      assert(!defined(invoker.bundle_target))
    }

    # TODO(tiborg): We have several flags that are necessary for workarounds
    # that come from the fact that the resources get compiled in the bundle
    # module target, but bundle modules have to have certain flags in
    # common or bundle modules have to know information about the base module.
    # Those flags include version_code, version_name, and base_module_target.
    # It would be better to move the resource compile target into the bundle
    # target. Doing so would keep the bundle modules independent from the bundle
    # and potentially reuse the same bundle modules for multiple bundles.
    android_apk_or_module(target_name) {
      forward_variables_from(invoker,
                             [
                               "aapt_locale_allowlist",
                               "additional_jar_files",
                               "alternative_android_sdk_dep",
                               "android_manifest",
                               "android_manifest_dep",
                               "annotation_processor_deps",
                               "app_as_shared_lib",
                               "assert_no_deps",
                               "base_module_target",
                               "bundle_target",
                               "chromium_code",
                               "data",
                               "data_deps",
                               "deps",
                               "enable_multidex",
                               "expected_android_manifest",
                               "expected_android_manifest_base",
                               "extra_verification_manifest",
                               "extra_verification_manifest_dep",
                               "generate_buildconfig_java",
                               "generate_final_jni",
                               "input_jars_paths",
                               "isolated_splits_enabled",
                               "is_base_module",
                               "jacoco_never_instrument",
                               "jar_excluded_patterns",
                               "javac_args",
                               "jni_registration_header",
                               "jni_sources_exclusions",
                               "load_library_from_apk",
                               "loadable_modules",
                               "product_config_java_packages",
                               "manifest_package",
                               "max_sdk_version",
                               "min_sdk_version",
                               "native_lib_placeholders",
                               "no_xml_namespaces",
                               "package_id",
                               "package_name",
                               "png_to_webp",
                               "processor_args_javac",
                               "product_version_resources_dep",
                               "proguard_configs",
                               "proguard_enabled",
                               "proguard_enable_obfuscation",
                               "resource_exclusion_exceptions",
                               "resource_exclusion_regex",
                               "resource_ids_provider_dep",
                               "resource_values_filter_rules",
                               "resources_config_paths",
                               "secondary_abi_loadable_modules",
                               "secondary_abi_shared_libraries",
                               "secondary_native_lib_placeholders",
                               "shared_libraries",
                               "shared_resources",
                               "shared_resources_allowlist_locales",
                               "shared_resources_allowlist_target",
                               "short_resource_paths",
                               "srcjar_deps",
                               "static_library_provider",
                               "static_library_synchronized_proguard",
                               "strip_resource_names",
                               "strip_unused_resources",
                               "target_sdk_version",
                               "testonly",
                               "uncompress_shared_libraries",
                               "library_always_compress",
                               "library_renames",
                               "use_chromium_linker",
                               "use_modern_linker",
                               "uses_split",
                               "version_code",
                               "version_name",
                               "visibility",
                             ])
      is_bundle_module = true
      generate_buildconfig_java = _is_base_module
    }
  }

  # Declare an Android instrumentation test runner.
  #
  # This target creates a wrapper script to run Android instrumentation tests.
  #
  # Arguments:
  #   android_test_apk: The target containing the tests.
  #   android_test_apk_name: The apk_name in android_test_apk
  #
  #   The following args are optional:
  #   apk_under_test: The target being tested.
  #   additional_apks: Additional targets to install on device.
  #   data: List of runtime data file dependencies.
  #   data_deps: List of non-linked dependencies.
  #   deps: List of private dependencies.
  #   extra_args: Extra arguments set for test runner.
  #   ignore_all_data_deps: Don't build data_deps and additional_apks.
  #   modules: Extra dynamic feature modules to install for test target. Can
  #     only be used if |apk_under_test| is an Android app bundle.
  #   fake_modules: Similar to |modules| but fake installed instead.
  #   never_incremental: Disable incremental builds.
  #   proguard_enabled: Enable proguard
  #   public_deps: List of public dependencies
  #
  # Example
  #   instrumentation_test_runner("foo_test_for_bar") {
  #     android_test_apk: ":foo"
  #     android_test_apk_name: "Foo"
  #     apk_under_test: ":bar"
  #   }
  template("instrumentation_test_runner") {
    if (use_rts) {
      action("${invoker.target_name}__rts_filters") {
        script = "//chromium/build/add_rts_filters.py"
        rts_file = "${root_build_dir}/gen/rts/${invoker.target_name}.filter"
        args = [ rebase_path(rts_file, root_build_dir) ]
        outputs = [ rts_file ]
      }
    }
    test_runner_script(target_name) {
      forward_variables_from(invoker,
                             [
                               "additional_apks",
                               "additional_locales",
                               "apk_under_test",
                               "data",
                               "data_deps",
                               "deps",
                               "extra_args",
                               "fake_modules",
                               "ignore_all_data_deps",
                               "modules",
                               "proguard_enabled",
                               "public_deps",
                               "use_webview_provider",
                             ])
      test_name = invoker.target_name
      test_type = "instrumentation"
      _apk_target_name = get_label_info(invoker.android_test_apk, "name")
      apk_target = ":$_apk_target_name"
      test_jar = "$root_build_dir/test.lib.java/" +
                 invoker.android_test_apk_name + ".jar"
      incremental_apk = !(defined(invoker.never_incremental) &&
                          invoker.never_incremental) && incremental_install

      public_deps = [
        ":$_apk_target_name",

        # Required by test runner to enumerate test list.
        ":${_apk_target_name}_dist_ijar",
      ]
      if (defined(invoker.apk_under_test)) {
        public_deps += [ invoker.apk_under_test ]
      }
      if (defined(invoker.additional_apks)) {
        public_deps += invoker.additional_apks
      }
      if (use_rts) {
        if (!defined(data_deps)) {
          data_deps = []
        }
        data_deps += [ ":${invoker.target_name}__rts_filters" ]
      }
    }
  }

  # Declare an Android instrumentation test apk
  #
  # This target creates an Android instrumentation test apk.
  #
  # Supports all variables of android_apk(), plus:
  #   apk_under_test: The apk being tested (optional).
  #
  # Example
  #   android_test_apk("foo_test_apk") {
  #     android_manifest = "AndroidManifest.xml"
  #     apk_name = "FooTest"
  #     apk_under_test = "Foo"
  #     sources = [
  #       "android/org/chromium/foo/FooTestCase.java",
  #       "android/org/chromium/foo/FooExampleTest.java",
  #     ]
  #     deps = [
  #       ":foo_test_support_java"
  #     ]
  #   }
  template("android_test_apk") {
    android_apk(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      testonly = true

      # The size info enables the test_runner to find the source file location
      # of a test after it is ran.
      include_size_info = true
      data = [ "$root_build_dir/size-info/${invoker.apk_name}.apk.jar.info" ]
      if (defined(invoker.data)) {
        data += invoker.data
      }

      deps = [ "//testing/android/broker:broker_java" ]
      if (defined(invoker.deps)) {
        deps += invoker.deps
      }
      data_deps = [
        # Ensure unstripped libraries are included in runtime deps so that
        # symbolization can be done.
        ":${target_name}__secondary_abi_shared_library_list",
        ":${target_name}__shared_library_list",
      ]
      if (defined(invoker.data_deps)) {
        data_deps += invoker.data_deps
      }
      if (defined(invoker.apk_under_test)) {
        data_deps += [ invoker.apk_under_test ]
      } else {
        enable_native_mocks = true
      }

      if (defined(invoker.apk_under_test)) {
        _under_test_label =
            get_label_info(invoker.apk_under_test, "label_no_toolchain")
        data_deps += [
          "${_under_test_label}__secondary_abi_shared_library_list",
          "${_under_test_label}__shared_library_list",
        ]
      }

      if (defined(invoker.additional_apks)) {
        data_deps += invoker.additional_apks
      }
      if (defined(invoker.use_webview_provider)) {
        data_deps += [ invoker.use_webview_provider ]
      }

      if (defined(invoker.proguard_enabled) && invoker.proguard_enabled &&
          !incremental_install) {
        # When ProGuard is on, we use ProGuard to combine the under test java
        # code and the test java code. This is to allow us to apply all ProGuard
        # optimizations that we ship with, but not have them break tests. The
        # apk under test will still have the same resources, assets, and
        # manifest, all of which are the ones used in the tests.
        proguard_configs = [ "//testing/android/proguard_for_test.flags" ]
        if (defined(invoker.proguard_configs)) {
          proguard_configs += invoker.proguard_configs
        }
        enable_proguard_checks = false
        if (defined(invoker.final_apk_path)) {
          _final_apk_path = final_apk_path
        } else {
          _final_apk_path = "$root_build_dir/apks/${invoker.apk_name}.apk"
        }
        data += [ "$_final_apk_path.mapping" ]
      }

      dist_ijar_path = "$root_build_dir/test.lib.java/${invoker.apk_name}.jar"
      create_apk_script = false

      forward_variables_from(invoker,
                             "*",
                             TESTONLY_AND_VISIBILITY + [
                                   "data",
                                   "data_deps",
                                   "deps",
                                   "proguard_configs",
                                 ])
    }
  }

  # Declare an Android instrumentation test apk with wrapper script.
  #
  # This target creates an Android instrumentation test apk with wrapper script
  # to run the test.
  #
  # Supports all variables of android_test_apk.
  template("instrumentation_test_apk") {
    assert(defined(invoker.apk_name))
    _apk_target_name = "${target_name}__test_apk"
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    android_test_apk(_apk_target_name) {
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
    }
    instrumentation_test_runner(target_name) {
      forward_variables_from(invoker,
                             [
                               "additional_apks",
                               "apk_under_test",
                               "data",
                               "data_deps",
                               "deps",
                               "extra_args",
                               "ignore_all_data_deps",
                               "modules",
                               "never_incremental",
                               "proguard_enabled",
                               "proguard_enable_obfuscation",
                               "public_deps",
                               "use_webview_provider",
                             ])
      android_test_apk = ":${_apk_target_name}"
      android_test_apk_name = invoker.apk_name
    }
  }

  # Declare an Android gtest apk
  #
  # This target creates an Android apk for running gtest-based unittests.
  #
  # Variables
  #   deps: Specifies the dependencies of this target. These will be passed to
  #     the underlying android_apk invocation and should include the java and
  #     resource dependencies of the apk.
  #   shared_library: shared_library target that contains the unit tests.
  #   apk_name: The name of the produced apk. If unspecified, it uses the name
  #             of the shared_library target suffixed with "_apk".
  #   use_default_launcher: Whether the default activity (NativeUnitTestActivity)
  #     should be used for launching tests.
  #   allow_cleartext_traffic: (Optional) Whether to allow cleartext network
  #     requests during the test.
  #   use_native_activity: Test implements ANativeActivity_onCreate().
  #
  # Example
  #   unittest_apk("foo_unittests_apk") {
  #     deps = [ ":foo_java", ":foo_resources" ]
  #     shared_library = ":foo_unittests"
  #   }
  template("unittest_apk") {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    _use_native_activity =
        defined(invoker.use_native_activity) && invoker.use_native_activity
    _android_manifest = "$target_gen_dir/$target_name/AndroidManifest.xml"
    assert(invoker.shared_library != "")

    # This trivial assert is needed in case android_manifest is defined,
    # as otherwise _use_native_activity and _android_manifest would not be used.
    assert(_use_native_activity != "" && _android_manifest != "")

    if (!defined(invoker.android_manifest)) {
      _allow_cleartext_traffic = defined(invoker.allow_cleartext_traffic) &&
                                 invoker.allow_cleartext_traffic
      jinja_template("${target_name}_manifest") {
        _native_library_name = get_label_info(invoker.shared_library, "name")
        if (defined(invoker.android_manifest_template)) {
          input = invoker.android_manifest_template
        } else {
          input =
              "//testing/android/native_test/java/AndroidManifest.xml.jinja2"
        }
        output = _android_manifest
        variables = [
          "is_component_build=${is_component_build}",
          "native_library_name=${_native_library_name}",
          "use_native_activity=${_use_native_activity}",
          "allow_cleartext_traffic=${_allow_cleartext_traffic}",
        ]
      }
    }

    android_apk(target_name) {
      data_deps = []
      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
      testonly = true
      create_apk_script = false
      enable_native_mocks = true

      # TODO(crbug.com/1099849): Figure out why angle tests fail to launch
      #     with newer target_sdk_version.
      if (!defined(invoker.target_sdk_version) && _use_native_activity) {
        target_sdk_version = 24
      }

      assert(!defined(invoker.proguard_enabled) || !invoker.proguard_enabled ||
             invoker.proguard_configs != [])

      if (!defined(apk_name)) {
        apk_name = get_label_info(invoker.shared_library, "name")
      }

      if (!defined(android_manifest)) {
        android_manifest_dep = ":${target_name}_manifest"
        android_manifest = _android_manifest
      }

      final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk"

      if (!defined(use_default_launcher) || use_default_launcher) {
        deps += [
          "//base:base_java",
          "//chromium/build/android/gtest_apk:native_test_instrumentation_test_runner_java",
          "//testing/android/native_test:native_test_java",
        ]
      }
      shared_libraries = [ invoker.shared_library ]
      deps += [
        ":${target_name}__secondary_abi_shared_library_list",
        ":${target_name}__shared_library_list",
      ]
    }
  }

  # Generate .java files from .aidl files.
  #
  # This target will store the .java files in a srcjar and should be included in
  # an android_library or android_apk's srcjar_deps.
  #
  # Variables
  #   sources: Paths to .aidl files to compile.
  #   import_include: Path to directory containing .java files imported by the
  #     .aidl files.
  #   interface_file: Preprocessed aidl file to import.
  #
  # Example
  #   android_aidl("foo_aidl") {
  #     import_include = "java/src"
  #     sources = [
  #       "java/src/com/foo/bar/FooBarService.aidl",
  #       "java/src/com/foo/bar/FooBarServiceCallback.aidl",
  #     ]
  #   }
  template("android_aidl") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

      script = "//chromium/build/android/gyp/aidl.py"
      depfile = "$target_gen_dir/$target_name.d"
      sources = invoker.sources

      _srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
      _aidl_path = "${android_sdk_build_tools}/aidl"
      _framework_aidl = "$android_sdk/framework.aidl"
      _imports = [ _framework_aidl ]
      if (defined(invoker.interface_file)) {
        assert(invoker.interface_file != "")
        _imports += [ invoker.interface_file ]
      }

      inputs = [ _aidl_path ] + _imports

      outputs = [ _srcjar_path ]
      _rebased_imports = rebase_path(_imports, root_build_dir)
      args = [
        "--aidl-path",
        rebase_path(_aidl_path, root_build_dir),
        "--imports=$_rebased_imports",
        "--srcjar",
        rebase_path(_srcjar_path, root_build_dir),
        "--depfile",
        rebase_path(depfile, root_build_dir),
      ]
      if (defined(invoker.import_include) && invoker.import_include != []) {
        _rebased_import_paths = []
        foreach(_import_path, invoker.import_include) {
          _rebased_import_path = []
          _rebased_import_path = [ rebase_path(_import_path, root_build_dir) ]
          _rebased_import_paths += _rebased_import_path
        }
        args += [ "--includes=$_rebased_import_paths" ]
      }
      args += rebase_path(sources, root_build_dir)
    }
  }

  # Compile a protocol buffer to java.
  #
  # This generates java files from protocol buffers and creates an Android library
  # containing the classes.
  #
  # Variables
  #   sources (required)
  #       Paths to .proto files to compile.
  #
  #   proto_path (required)
  #       Root directory of .proto files.
  #
  #   deps (optional)
  #       Additional dependencies. Passed through to both the action and the
  #       android_library targets.
  #
  #   import_dirs (optional)
  #       A list of extra import directories to be passed to protoc compiler.
  #       WARNING: This circumvents proto checkdeps, and should only be used
  #       when needed, typically when proto files cannot cleanly import through
  #       absolute paths, such as for third_party or generated .proto files.
  #       http://crbug.com/691451 tracks fixing this.
  #
  # Example:
  #  proto_java_library("foo_proto_java") {
  #    proto_path = "src/foo"
  #    sources = [ "$proto_path/foo.proto" ]
  #  }
  template("proto_java_library") {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

    _template_name = target_name

    action_with_pydeps("${_template_name}__protoc_java") {
      # The suffix "__protoc_java.srcjar" is used by SuperSize to identify
      # protobuf symbols.
      _srcjar_path = "$target_gen_dir/$target_name.srcjar"
      script = "//chromium/build/protoc_java.py"

      deps = []
      if (defined(invoker.deps)) {
        deps += invoker.deps
      }

      sources = invoker.sources
      depfile = "$target_gen_dir/$target_name.d"
      outputs = [ _srcjar_path ]
      args = [
               "--depfile",
               rebase_path(depfile, root_build_dir),
               "--protoc",
               rebase_path(android_protoc_bin, root_build_dir),
               "--proto-path",
               rebase_path(invoker.proto_path, root_build_dir),
               "--srcjar",
               rebase_path(_srcjar_path, root_build_dir),
             ] + rebase_path(sources, root_build_dir)

      if (defined(invoker.import_dirs)) {
        foreach(_import_dir, invoker.import_dirs) {
          args += [
            "--import-dir",
            rebase_path(_import_dir, root_build_dir),
          ]
        }
      }
    }

    android_library(target_name) {
      chromium_code = false
      sources = []
      srcjar_deps = [ ":${_template_name}__protoc_java" ]
      deps = [ "//third_party/android_deps:protobuf_lite_runtime_java" ]
      if (defined(invoker.deps)) {
        deps += invoker.deps
      }
    }
  }

  # Declare an Android library target for a prebuilt AAR.
  #
  # This target creates an Android library containing java code and Android
  # resources. For libraries without resources, it will not generate
  # corresponding android_resources targets.
  #
  # To avoid slowing down "gn gen", an associated .info file must be committed
  # along with the .aar file. In order to create this file, define the target
  # and then run once with the gn arg "update_android_aar_prebuilts = true".
  #
  # Variables
  #   aar_path: Path to the AAR.
  #   info_path: Path to the .aar.info file (generated via
  #       update_android_aar_prebuilts GN arg).
  #   proguard_configs: List of proguard configs to use in final apk step for
  #       any apk that depends on this library.
  #   ignore_aidl: Whether to ignore .aidl files found with the .aar.
  #   ignore_assets: Whether to ignore assets found in the .aar.
  #   ignore_manifest: Whether to ignore creating manifest.
  #   ignore_native_libraries: Whether to ignore .so files found in the .aar.
  #       See also extract_native_libraries.
  #   ignore_proguard_configs: Whether to ignore proguard configs.
  #   ignore_info_updates: Whether to ignore the info file when
  #       update_android_aar_prebuilts gn arg is true. However, the info file
  #       will still be verified regardless of the value of this flag.
  #   strip_resources: Whether to ignore android resources found in the .aar.
  #   custom_package: Java package for generated R.java files.
  #   extract_native_libraries: Whether to extract .so files found in the .aar.
  #       If the file contains .so, either extract_native_libraries or
  #       ignore_native_libraries must be set.
  #   TODO(jbudorick@): remove this arguments after crbug.com/522043 is fixed.
  #   requires_android: Whether this target can only be used for compiling
  #       Android related targets.
  #
  # Example
  #   android_aar_prebuilt("foo_java") {
  #     aar_path = "foo.aar"
  #   }
  template("android_aar_prebuilt") {
    _info_path = "$target_name.info"
    if (defined(invoker.info_path)) {
      _info_path = invoker.info_path
    }
    _output_path = "${target_out_dir}/${target_name}"

    # Some targets only differ by _java with other targets so _java and _junit
    # need to be replaced by non-empty strings to avoid duplicate targets. (e.g.
    # androidx_window_window_java vs androidx_window_window_java_java).
    _target_name_without_java_or_junit =
        string_replace(string_replace(target_name, "_java", "_J"),
                       "_junit",
                       "_U")

    # This unpack target is a python action, not a valid java target. Since the
    # java targets below depend on it, its name must not match the java patterns
    # in internal_rules.gni.
    _unpack_target_name = "${_target_name_without_java_or_junit}__unpack_aar"
    _ignore_aidl = defined(invoker.ignore_aidl) && invoker.ignore_aidl
    _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets
    _ignore_manifest =
        defined(invoker.ignore_manifest) && invoker.ignore_manifest
    _ignore_native_libraries = defined(invoker.ignore_native_libraries) &&
                               invoker.ignore_native_libraries
    _ignore_proguard_configs = defined(invoker.ignore_proguard_configs) &&
                               invoker.ignore_proguard_configs
    _extract_native_libraries = defined(invoker.extract_native_libraries) &&
                                invoker.extract_native_libraries
    _strip_resources =
        defined(invoker.strip_resources) && invoker.strip_resources

    # Allow 'resource_overlay' parameter even if there are no resources in order
    # to keep the logic for generated 'android_aar_prebuilt' rules simple.
    not_needed(invoker, [ "resource_overlay" ])

    _ignore_info_updates =
        defined(invoker.ignore_info_updates) && invoker.ignore_info_updates

    # Scan the AAR file and determine the resources and jar files.
    # Some libraries might not have resources; others might have two jars.
    if (!_ignore_info_updates && update_android_aar_prebuilts) {
      print("Writing " + rebase_path(_info_path, "//"))
      exec_script("//chromium/build/android/gyp/aar.py",
                  [
                    "list",
                    rebase_path(invoker.aar_path, root_build_dir),
                    "--output",
                    rebase_path(_info_path, root_build_dir),
                  ])
    }

    # If "gn gen" is failing on the following line, you need to generate an
    # .info file for your new target by running:
    #   gn gen --args='target_os="android" update_android_aar_prebuilts=true' out/tmp
    #   rm -r out/tmp
    _scanned_files = read_file(_info_path, "scope")

    _use_scanned_assets = !_ignore_assets && _scanned_files.assets != []

    assert(_ignore_aidl || _scanned_files.aidl == [],
           "android_aar_prebuilt() aidl not yet supported." +
               " Implement or use ignore_aidl = true." +
               " http://crbug.com/644439")
    assert(
        !_scanned_files.has_native_libraries ||
            (_ignore_native_libraries || _extract_native_libraries),
        "android_aar_prebuilt() contains .so files." +
            " Please set ignore_native_libraries or extract_native_libraries.")
    assert(
        !(_ignore_native_libraries && _extract_native_libraries),
        "ignore_native_libraries and extract_native_libraries cannot both be set.")
    assert(!_scanned_files.has_native_libraries ||
           _scanned_files.native_libraries != [])
    assert(_scanned_files.has_classes_jar || _scanned_files.subjars == [])

    action_with_pydeps(_unpack_target_name) {
      script = "//chromium/build/android/gyp/aar.py"  # Unzips the AAR
      args = [
        "extract",
        rebase_path(invoker.aar_path, root_build_dir),
        "--output-dir",
        rebase_path(_output_path, root_build_dir),
        "--assert-info-file",
        rebase_path(_info_path, root_build_dir),
      ]
      if (_strip_resources) {
        args += [ "--ignore-resources" ]
      }
      inputs = [ invoker.aar_path ]
      outputs = [ "${_output_path}/AndroidManifest.xml" ]
      if (!_strip_resources && _scanned_files.has_r_text_file) {
        # Certain packages, in particular Play Services have no R.txt even
        # though its presence is mandated by AAR spec. Such packages cause
        # spurious rebuilds if this output is specified unconditionally.
        outputs += [ "${_output_path}/R.txt" ]
      }

      if (!_strip_resources && _scanned_files.resources != []) {
        outputs += get_path_info(
                rebase_path(_scanned_files.resources, "", _output_path),
                "abspath")
      }
      if (_scanned_files.has_classes_jar) {
        outputs += [ "${_output_path}/classes.jar" ]
      }
      outputs +=
          get_path_info(rebase_path(_scanned_files.subjars, "", _output_path),
                        "abspath")
      if (!_ignore_proguard_configs) {
        if (_scanned_files.has_proguard_flags) {
          outputs += [ "${_output_path}/proguard.txt" ]
        }
      }

      if (_extract_native_libraries && _scanned_files.has_native_libraries) {
        outputs += get_path_info(
                rebase_path(_scanned_files.native_libraries, "", _output_path),
                "abspath")
      }
      if (_use_scanned_assets) {
        outputs +=
            get_path_info(rebase_path(_scanned_files.assets, "", _output_path),
                          "abspath")
      }
    }

    _has_unignored_resources =
        !_strip_resources &&
        (_scanned_files.resources != [] || _scanned_files.has_r_text_file)

    _should_process_manifest =
        !_ignore_manifest && !_scanned_files.is_manifest_empty

    # Create the android_resources target for resources.
    if (_has_unignored_resources || _should_process_manifest) {
      _res_target_name = "${target_name}__resources"
      android_resources(_res_target_name) {
        forward_variables_from(invoker,
                               [
                                 "custom_package",
                                 "resource_overlay",
                                 "testonly",
                                 "strip_drawables",
                               ])
        deps = [ ":$_unpack_target_name" ]
        if (_should_process_manifest) {
          android_manifest_dep = ":$_unpack_target_name"
          android_manifest = "${_output_path}/AndroidManifest.xml"
        } else if (defined(_scanned_files.manifest_package) &&
                   !defined(custom_package)) {
          custom_package = _scanned_files.manifest_package
        }

        sources = []
        if (!_strip_resources) {
          sources = rebase_path(_scanned_files.resources, "", _output_path)
        }
        if (!_strip_resources && _scanned_files.has_r_text_file) {
          r_text_file = "${_output_path}/R.txt"
        }
      }
    } else if (defined(invoker.strip_drawables)) {
      not_needed(invoker, [ "strip_drawables" ])
    }

    if (_ignore_manifest) {
      # Having this available can be useful for DFMs that depend on AARs. It
      # provides a way to have manifest entries go into the base split while
      # the code goes into a DFM.
      java_group("${target_name}__ignored_manifest") {
        forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
        deps = [ ":$_unpack_target_name" ]
        mergeable_android_manifests = [ "${_output_path}/AndroidManifest.xml" ]
      }
    }

    # Create the android_assets target for assets
    if (_use_scanned_assets) {
      _assets_target_name = "${target_name}__assets"
      android_assets(_assets_target_name) {
        forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
        renaming_sources = []
        renaming_destinations = []
        foreach(_asset_file, _scanned_files.assets) {
          _original_path =
              get_path_info(rebase_path(_asset_file, "", _output_path),
                            "abspath")
          _updated_path = string_replace(_asset_file, "assets/", "", 1)
          renaming_sources += [ _original_path ]
          renaming_destinations += [ _updated_path ]
        }
      }
    }

    # Create android_java_prebuilt target for classes.jar.
    if (_scanned_files.has_classes_jar) {
      _java_library_vars = [
        "bytecode_rewriter_target",
        "enable_bytecode_checks",
        "jar_excluded_patterns",
        "jar_included_patterns",
        "missing_classes_allowlist",
        "requires_android",
        "testonly",
        "use_classic_desugar",
      ]

      # Create android_java_prebuilt target for extra jars within jars/.
      _subjar_targets = []
      foreach(_tuple, _scanned_files.subjar_tuples) {
        _current_target = "${target_name}__subjar_${_tuple[0]}"
        _subjar_targets += [ ":$_current_target" ]
        java_prebuilt(_current_target) {
          forward_variables_from(invoker, _java_library_vars)
          deps = [ ":$_unpack_target_name" ]
          if (!defined(requires_android)) {
            requires_android = true
          }
          supports_android = true
          jar_path = "$_output_path/${_tuple[1]}"
          _base_output_name = get_path_info(jar_path, "name")
          output_name = "${invoker.target_name}-$_base_output_name"
          public_target_label = invoker.target_name
        }
      }

      _jar_target_name = "${target_name}__classes"
      java_prebuilt(_jar_target_name) {
        forward_variables_from(invoker, _java_library_vars)
        forward_variables_from(invoker,
                               [
                                 "deps",
                                 "input_jars_paths",
                                 "proguard_configs",
                               ])
        if (!defined(deps)) {
          deps = []
        }
        deps += _subjar_targets + [ ":$_unpack_target_name" ]
        if (defined(_res_target_name)) {
          deps += [ ":$_res_target_name" ]
        }
        if (!defined(requires_android)) {
          requires_android = true
        }
        supports_android = true
        jar_path = "$_output_path/classes.jar"
        aar_path = invoker.aar_path
        output_name = invoker.target_name

        if (!_ignore_proguard_configs) {
          if (!defined(proguard_configs)) {
            proguard_configs = []
          }
          if (_scanned_files.has_proguard_flags) {
            proguard_configs += [ "$_output_path/proguard.txt" ]
          }
        }
        public_target_label = invoker.target_name
      }
    }

    java_group(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
      public_deps = [ ":$_unpack_target_name" ]
      deps = []
      if (defined(_jar_target_name)) {
        deps += [ ":$_jar_target_name" ]

        # Although subjars are meant to be private, we add them as deps here
        # because in practice they seem to contain classes required to be in the
        # classpath.
        deps += _subjar_targets
      }
      if (defined(_res_target_name)) {
        deps += [ ":$_res_target_name" ]
      }
      if (defined(_assets_target_name)) {
        deps += [ ":$_assets_target_name" ]
      }
    }
  }

  # Create an Android application bundle from one base android_apk target,
  # and zero or more associated android_apk.
  #
  # Variables:
  #    base_module_target: Name of the android_app_bundle_module target
  #      corresponding to the base module for this application bundle. The
  #      bundle file will include the same content in its base module, though in
  #      a slightly different format.
  #
  #    bundle_base_path: Optional. If set, the bundle will be output to this
  #      directory. Defaults to "$root_build_dir/apks".
  #
  #    bundle_name: Optional. If set, the bundle will be output to the
  #      filename "${bundle_name}.aab".
  #
  #    extra_modules: Optional list of scopes, one per extra module used by
  #      this bundle. Each scope must have a 'name' field that specifies the
  #      module name (which cannot be 'base', since this is reserved for the
  #      base module), and an 'apk_target' field that specified the
  #      corresponding android_apk target name the module is modeled on.
  #
  #    enable_language_splits: Optional. If true, enable APK splits based
  #      on languages.
  #
  #    keystore_path: optional keystore path, used only when generating APKs.
  #    keystore_name: optional keystore name, used only when generating APKs.
  #    keystore_password: optional keystore password, used only when
  #      generating APKs.
  #
  #    command_line_flags_file: Optional. If provided, named of the on-device
  #      file that will be used to store command-line arguments. The default
  #      is 'command_line_flags_file', but this is typically redefined to
  #      something more specific for certain bundles (e.g. the Chromium based
  #      APKs use 'chrome-command-line', the WebView one uses
  #      'webview-command-line').
  #
  #    proguard_enabled: Optional. True if proguarding is enabled for this
  #      bundle. Default is to enable this only for release builds. Note that
  #      this will always perform synchronized proguarding.
  #
  #    proguard_enable_obfuscation: Whether to enable obfuscation (default=true)
  #
  #    enable_multidex: Optional. Enable multidexing of optimized modules jars
  #      when using synchronized proguarding. Only applies to base module.
  #
  #    proguard_android_sdk_dep: Optional. android_system_java_prebuilt() target
  #      used as a library jar for synchronized proguarding.
  #
  #    compress_shared_libraries: Optional. Whether to compress shared libraries
  #      such that they are extracted upon install. Libraries prefixed with
  #      "crazy." are never compressed.
  #
  #    system_image_locale_allowlist: List of locales that should be included
  #      on system APKs generated from this bundle.
  #
  #    static_library_provider: Specifies a single target that this target will
  #      use as a static library APK.
  #      Additionally, when allotting libraries to be packaged into modules, the
  #      libraries packaged into the static library will be accounted for to
  #      avoid library duplication. Effectively, the static library will be
  #      treated as the parent of the base module.
  #
  #    expected_libs_and_assets: Verify the list of included native libraries
  #      and assets is consistent with the given expectation file.
  #    expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff
  #      with this file as the base.
  #    expected_proguard_config: Checks that the merged set of proguard flags
  #      matches the given config.
  #    expected_proguard_config_base: Treat expected_proguard_config as a diff
  #      with this file as the base.
  #
  #    version_code: Optional. Version code of the target.
  #
  #    is_multi_abi: If true will add a library placeholder for the missing ABI
  #      if either the primary or the secondary ABI has no native libraries set.
  #
  #    default_modules_for_testing: (optional): A list of DFM that the wrapper
  #      script should install. This is for local testing only, and does not
  #      affect the actual DFM in production.
  # Example:
  #   android_app_bundle("chrome_public_bundle") {
  #      base_module_target = "//chrome/android:chrome_public_apk"
  #      extra_modules = [
  #        { # NOTE: Scopes require one field per line, and no comma separators.
  #          name = "my_module"
  #          module_target = ":my_module"
  #        },
  #      ]
  #   }
  #
  template("android_app_bundle") {
    _target_name = target_name
    _uses_static_library = defined(invoker.static_library_provider)
    _proguard_enabled =
        defined(invoker.proguard_enabled) && invoker.proguard_enabled

    if (defined(invoker.version_code)) {
      _version_code = invoker.version_code
    } else {
      _version_code = android_default_version_code
    }

    if (android_override_version_code != "") {
      _version_code = android_override_version_code
    }

    # Prevent "unused variable".
    not_needed([ "_version_code" ])

    _bundle_base_path = "$root_build_dir/apks"
    if (defined(invoker.bundle_base_path)) {
      _bundle_base_path = invoker.bundle_base_path
    }

    _bundle_name = _target_name
    if (defined(invoker.bundle_name)) {
      _bundle_name = invoker.bundle_name
    }
    _bundle_path = "$_bundle_base_path/${_bundle_name}.aab"
    _rebased_bundle_path = rebase_path(_bundle_path, root_build_dir)

    _base_target_name = get_label_info(invoker.base_module_target, "name")
    _base_target_gen_dir =
        get_label_info(invoker.base_module_target, "target_gen_dir")
    _base_module_build_config =
        "$_base_target_gen_dir/${_base_target_name}.build_config.json"
    _base_module_build_config_target =
        "${invoker.base_module_target}$build_config_target_suffix"
    _rebased_base_module_build_config =
        rebase_path(_base_module_build_config, root_build_dir)

    _modules = [
      {
        name = "base"
        module_target = invoker.base_module_target
        build_config = _base_module_build_config
        build_config_target = _base_module_build_config_target
        if (_uses_static_library) {
          parent = "lib"
        }
      },
    ]

    _enable_multidex =
        !defined(invoker.enable_multidex) || invoker.enable_multidex

    # Prevent "unused variable".
    not_needed([ "_enable_multidex" ])

    if (_proguard_enabled) {
      _uses_static_library_synchronized_proguard =
          defined(invoker.static_library_synchronized_proguard) &&
          invoker.static_library_synchronized_proguard

      # TODO(crbug.com/1032609): Remove dexsplitter from Trichrome Proguard.
      _dex_target = "${_target_name}__dex"
      _proguard_mapping_path = "${_bundle_path}.mapping"
    }

    assert(_proguard_enabled || !defined(invoker.enable_multidex),
           "Bundle only adds dexing step if proguarding is enabled.")

    if (defined(invoker.extra_modules)) {
      _module_count = 0
      not_needed([ "_module_count" ])

      foreach(_module, invoker.extra_modules) {
        _module_count += 1
        assert(defined(_module.name),
               "Missing 'name' field for extra module #${_module_count}.")
        assert(_module.name != "base",
               "Module name 'base' is reserved for the main bundle module")
        assert(
            defined(_module.module_target),
            "Missing 'module_target' field for extra module ${_module.name}.")
        _module_target = _module.module_target
        _module_target_name = get_label_info(_module_target, "name")
        _module_target_gen_dir =
            get_label_info(_module_target, "target_gen_dir")
        _module.build_config =
            "$_module_target_gen_dir/${_module_target_name}.build_config.json"
        _module.build_config_target =
            "$_module_target$build_config_target_suffix"
        _module.parent = "base"
        _modules += [ _module ]
      }
    }

    # Make build config, which is required for synchronized proguarding.
    _module_java_targets = []
    _module_build_configs = []
    _module_targets = []
    foreach(_module, _modules) {
      _module_targets += [ _module.module_target ]
      _module_java_targets += [ "${_module.module_target}__java" ]
      _module_build_configs += [ _module.build_config ]
    }

    if (_uses_static_library) {
      _lib_proxy_module = {
        name = "lib"
      }
      _static_library_target_name =
          get_label_info(invoker.static_library_provider, "name")
      _static_library_gen_dir =
          get_label_info(invoker.static_library_provider, "target_gen_dir")
      _lib_proxy_module.build_config = "$_static_library_gen_dir/$_static_library_target_name.build_config.json"
      _lib_proxy_module.build_config_target =
          "${invoker.static_library_provider}$build_config_target_suffix"
    }

    # Allot native libraries to modules they should be packaged into. This is
    # necessary since all libraries that are depended on by multiple modules
    # have to go into base or the static shared library if it exists.
    # TODO(crbug.com/1021565): It would be nice if this lived outside the
    # android_app_bundle template and the static shared library would pull in
    # the libs as allotted by this step.
    _native_libraries_config =
        "$target_gen_dir/$_target_name.native_libraries_config"
    _native_libraries_config_target = "${_target_name}__allot_native_libraries"
    allot_native_libraries(_native_libraries_config_target) {
      modules = _modules
      native_libraries_filearg_keys = [
        "native:libraries",
        "native:loadable_modules",
      ]
      output = _native_libraries_config
      if (_uses_static_library) {
        modules += [ _lib_proxy_module ]
      }
    }
    if (defined(android_app_secondary_abi)) {
      _secondary_abi_native_libraries_config =
          "$target_gen_dir/$_target_name.secondary_abi_native_libraries_config"
      _secondary_abi_native_libraries_config_target =
          "${_target_name}__allot_secondary_abi_native_libraries"
      allot_native_libraries(_secondary_abi_native_libraries_config_target) {
        modules = _modules
        native_libraries_filearg_keys = [
          "native:secondary_abi_libraries",
          "native:secondary_abi_loadable_modules",
        ]
        output = _secondary_abi_native_libraries_config
        if (_uses_static_library) {
          modules += [ _lib_proxy_module ]
        }
      }
    }

    # Used to expose the module Java targets of the bundle.
    group("${_target_name}__java") {
      deps = _module_java_targets
    }
    group("${_target_name}__compile_resources") {
      deps = [ "${invoker.base_module_target}__compile_resources" ]
    }

    _build_config = "$target_gen_dir/${_target_name}.build_config.json"
    _rebased_build_config = rebase_path(_build_config, root_build_dir)
    _build_config_target = "$_target_name$build_config_target_suffix"
    if (defined(invoker.proguard_android_sdk_dep)) {
      proguard_android_sdk_dep_ = invoker.proguard_android_sdk_dep
    } else {
      proguard_android_sdk_dep_ = "//third_party/android_sdk:android_sdk_java"
    }

    if (_proguard_enabled) {
      _proguard_mapping_path = "${_bundle_path}.mapping"
    }

    write_build_config(_build_config_target) {
      type = "android_app_bundle"
      possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ]
      build_config = _build_config
      proguard_enabled = _proguard_enabled
      module_build_configs = _module_build_configs

      if (_proguard_enabled) {
        proguard_mapping_path = _proguard_mapping_path
      }
    }

    if (_proguard_enabled) {
      # If this Bundle uses a static library, the static library APK will
      # create the synchronized dex file path.
      if (!_uses_static_library_synchronized_proguard) {
        dex(_dex_target) {
          forward_variables_from(invoker,
                                 [
                                   "expected_proguard_config",
                                   "expected_proguard_config_base",
                                   "min_sdk_version",
                                   "proguard_enable_obfuscation",
                                 ])
          if (defined(expected_proguard_config)) {
            top_target_name = _target_name
          }
          enable_multidex = _enable_multidex
          proguard_enabled = true
          proguard_mapping_path = _proguard_mapping_path
          proguard_sourcefile_suffix = "$android_channel-$_version_code"
          build_config = _build_config

          deps = _module_java_targets + [ ":$_build_config_target" ]
          modules = _modules
        }
      }
    }

    _all_create_module_targets = []
    _all_module_zip_paths = []
    _all_module_build_configs = []
    _all_module_unused_resources_deps = []
    foreach(_module, _modules) {
      _module_target = _module.module_target
      _module_build_config = _module.build_config
      _module_build_config_target = _module.build_config_target

      if (!_proguard_enabled) {
        _dex_target_for_module = "${_module_target}__final_dex"
      } else {
        _dex_target_for_module = ":$_dex_target"
      }

      # Generate one module .zip file per bundle module.
      #
      # Important: the bundle tool uses the module's zip filename as
      # the internal module name inside the final bundle, in other words,
      # this file *must* be named ${_module.name}.zip
      _create_module_target = "${_target_name}__${_module.name}__create"
      _module_zip_path = "$target_gen_dir/$target_name/${_module.name}.zip"
      create_android_app_bundle_module(_create_module_target) {
        forward_variables_from(invoker,
                               [
                                 "is_multi_abi",
                                 "min_sdk_version",
                                 "uncompress_dex",
                                 "proguard_enabled",
                               ])
        module_name = _module.name
        build_config = _module_build_config
        module_zip_path = _module_zip_path
        native_libraries_config = _native_libraries_config

        if (module_name == "base" &&
            defined(invoker.expected_libs_and_assets)) {
          forward_variables_from(invoker,
                                 [
                                   "expected_libs_and_assets",
                                   "expected_libs_and_assets_base",
                                 ])
          top_target_name = _target_name
          build_config_target = _module_build_config_target
          native_libraries_config_target = ":$_native_libraries_config_target"
          if (defined(android_app_secondary_abi)) {
            secondary_abi_native_libraries_config_target =
                ":$_secondary_abi_native_libraries_config_target"
          }
        }

        deps = [
          ":$_native_libraries_config_target",
          _dex_target_for_module,
          _module_build_config_target,
          _module_target,
        ]

        if (defined(android_app_secondary_abi)) {
          secondary_abi_native_libraries_config =
              _secondary_abi_native_libraries_config
          deps += [ ":$_secondary_abi_native_libraries_config_target" ]
        }
      }

      _all_create_module_targets += [
        ":$_create_module_target",
        _module_build_config_target,
        "${_module_target}__compile_resources",
      ]
      _all_module_zip_paths += [ _module_zip_path ]
      _all_module_build_configs += [ _module_build_config ]
      _all_module_unused_resources_deps += [
        "${_module_target}__compile_resources",
        _dex_target_for_module,
        _module_build_config_target,
      ]
    }
    if (defined(invoker.strip_unused_resources) &&
        invoker.strip_unused_resources) {
      # Resources only live in the base module so we define the unused resources
      # target only on the base module target.
      _unused_resources_target = "${_base_target_name}__unused_resources"
      _unused_resources_config =
          "${_base_target_gen_dir}/${_base_target_name}_unused_resources.config"
      unused_resources(_unused_resources_target) {
        deps = _all_module_unused_resources_deps
        all_module_build_configs = _all_module_build_configs
        build_config = _base_module_build_config
        if (_proguard_enabled) {
          proguard_mapping_path = _proguard_mapping_path
        }
        output_config = _unused_resources_config
      }
    }

    _all_rebased_module_zip_paths =
        rebase_path(_all_module_zip_paths, root_build_dir)

    _enable_language_splits = defined(invoker.enable_language_splits) &&
                              invoker.enable_language_splits

    _split_dimensions = []
    if (_enable_language_splits) {
      _split_dimensions += [ "language" ]
    }

    _keystore_path = android_keystore_path
    _keystore_password = android_keystore_password
    _keystore_name = android_keystore_name

    if (defined(invoker.keystore_path)) {
      _keystore_path = invoker.keystore_path
      _keystore_password = invoker.keystore_password
      _keystore_name = invoker.keystore_name
    }

    _rebased_keystore_path = rebase_path(_keystore_path, root_build_dir)

    _bundle_target_name = "${_target_name}__bundle"
    action_with_pydeps(_bundle_target_name) {
      script = "//chromium/build/android/gyp/create_app_bundle.py"
      inputs = _all_module_zip_paths + _all_module_build_configs
      outputs = [ _bundle_path ]
      deps = _all_create_module_targets + [ ":$_build_config_target" ]
      args = [
        "--out-bundle=$_rebased_bundle_path",
        "--rtxt-out-path=$_rebased_bundle_path.R.txt",
        "--pathmap-out-path=$_rebased_bundle_path.pathmap.txt",
        "--module-zips=$_all_rebased_module_zip_paths",
      ]
      if (_split_dimensions != []) {
        args += [ "--split-dimensions=$_split_dimensions" ]
      }
      if (defined(invoker.compress_shared_libraries) &&
          invoker.compress_shared_libraries) {
        args += [ "--compress-shared-libraries" ]
      }
      _min_sdk_version = default_min_sdk_version
      if (defined(invoker.min_sdk_version)) {
        _min_sdk_version = invoker.min_sdk_version
      }

      # Android P+ support loading from stored dex.
      if (_min_sdk_version < 27) {
        args += [ "--compress-dex" ]
      }

      if (treat_warnings_as_errors) {
        args += [ "--warnings-as-errors" ]
      }

      if (_enable_language_splits) {
        args += [
          "--base-allowlist-rtxt-path=@FileArg(" + "${_rebased_base_module_build_config}:deps_info:base_allowlist_rtxt_path)",
          "--base-module-rtxt-path=@FileArg(" +
              "${_rebased_base_module_build_config}:deps_info:r_text_path)",
        ]
      }
      if (defined(invoker.validate_services) && invoker.validate_services) {
        args += [ "--validate-services" ]
      }

      foreach(_module, _modules) {
        _rebased_build_config =
            rebase_path(_module.build_config, root_build_dir)
        args += [
          "--uncompressed-assets=@FileArg(" +
              "$_rebased_build_config:uncompressed_assets)",
          "--rtxt-in-paths=@FileArg(" +
              "$_rebased_build_config:deps_info:r_text_path)",
          "--pathmap-in-paths=@FileArg(" +
              "$_rebased_build_config:deps_info:module_pathmap_path)",
          "--module-name=" + _module.name,
        ]
      }

      # http://crbug.com/725224. Fix for bots running out of memory.
      if (defined(java_cmd_pool_size)) {
        pool = "//chromium/build/config/android:java_cmd_pool($default_toolchain)"
      } else {
        pool = "//chromium/build/toolchain:link_pool($default_toolchain)"
      }
    }

    # Create size info files for targets that care about size
    # (have proguard enabled).
    if (_proguard_enabled) {
      # Merge all module targets to obtain size info files for all targets.
      _all_module_targets = _module_targets

      _size_info_target = "${_target_name}__size_info"
      create_size_info_files(_size_info_target) {
        name = "$_bundle_name.aab"
        deps = _all_module_targets + [ ":$_build_config_target" ]
        module_build_configs = _all_module_build_configs
      }
    }

    if (_uses_static_library) {
      _install_artifacts_target = "${target_name}__install_artifacts"
      _install_artifacts_json =
          "${target_gen_dir}/${target_name}.install_artifacts"
      generated_file(_install_artifacts_target) {
        output_conversion = "json"
        deps = [ invoker.static_library_provider ]
        outputs = [ _install_artifacts_json ]
        data_keys = [ "install_artifacts" ]
        rebase = root_build_dir
      }
    }

    # Generate a wrapper script for the bundle.
    _android_aapt2_path = android_sdk_tools_bundle_aapt2

    _bundle_apks_path = "$_bundle_base_path/$_bundle_name.apks"
    _bundle_wrapper_script_dir = "$root_build_dir/bin"
    _bundle_wrapper_script_path = "$_bundle_wrapper_script_dir/$_target_name"

    action_with_pydeps("${_target_name}__wrapper_script") {
      script = "//chromium/build/android/gyp/create_bundle_wrapper_script.py"
      inputs = [ _base_module_build_config ]
      outputs = [ _bundle_wrapper_script_path ]

      # Telemetry for bundles uses the wrapper script for installation.
      data = [
        _bundle_wrapper_script_path,
        _android_aapt2_path,
        _keystore_path,
        _bundle_path,
      ]
      data_deps = [
        "//chromium/build/android:apk_operations_py",
        "//chromium/build/android:stack_tools",
      ]

      deps = [ _base_module_build_config_target ]
      args = [
        "--script-output-path",
        rebase_path(_bundle_wrapper_script_path, root_build_dir),
        "--package-name=@FileArg(" +
            "$_rebased_base_module_build_config:deps_info:package_name)",
        "--aapt2",
        rebase_path(_android_aapt2_path, root_build_dir),
        "--bundle-path",
        _rebased_bundle_path,
        "--bundle-apks-path",
        rebase_path(_bundle_apks_path, root_build_dir),
        "--target-cpu=$target_cpu",
        "--keystore-path",
        _rebased_keystore_path,
        "--keystore-password",
        _keystore_password,
        "--key-name",
        _keystore_name,
      ]
      if (defined(invoker.default_modules_for_testing)) {
        args += [ "--default-modules" ] + invoker.default_modules_for_testing
      }
      if (defined(invoker.system_image_locale_allowlist)) {
        args += [
          "--system-image-locales=${invoker.system_image_locale_allowlist}",
        ]
      }
      if (defined(invoker.command_line_flags_file)) {
        args += [
          "--command-line-flags-file",
          invoker.command_line_flags_file,
        ]
      }
      if (_uses_static_library) {
        deps += [ ":$_install_artifacts_target" ]
        _rebased_install_artifacts_json =
            rebase_path(_install_artifacts_json, root_build_dir)
        _static_library_apk_path =
            "@FileArg($_rebased_install_artifacts_json[])"
        args += [
          "--additional-apk",
          _static_library_apk_path,
        ]
      }

      if (_proguard_enabled) {
        args += [
          "--proguard-mapping-path",
          rebase_path(_proguard_mapping_path, root_build_dir),
        ]

        # Required by logcat command.
        data_deps += [ "//chromium/build/android/stacktrace:java_deobfuscate" ]
        data += [ _proguard_mapping_path ]
      }
    }

    _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint &&
                   !disable_android_lint
    if (_enable_lint) {
      android_lint("${target_name}__lint") {
        forward_variables_from(invoker,
                               [
                                 "lint_baseline_file",
                                 "lint_suppressions_file",
                                 "min_sdk_version",
                               ])
        build_config = _build_config
        build_config_dep = ":$_build_config_target"
        deps = _module_java_targets
        if (defined(invoker.lint_suppressions_dep)) {
          deps += [ invoker.lint_suppressions_dep ]
        }
        if (defined(invoker.lint_min_sdk_version)) {
          min_sdk_version = invoker.lint_min_sdk_version
        }
      }
    } else {
      not_needed(invoker,
                 [
                   "lint_baseline_file",
                   "lint_min_sdk_version",
                   "lint_suppressions_dep",
                   "lint_suppressions_file",
                 ])
    }

    group(_target_name) {
      public_deps = [
        ":$_bundle_target_name",
        ":${_target_name}__wrapper_script",
      ]
      if (defined(_size_info_target)) {
        public_deps += [ ":$_size_info_target" ]
      }
      if (_enable_lint) {
        if (!defined(data_deps)) {
          data_deps = []
        }
        data_deps += [ ":${target_name}__lint" ]
      }
    }

    _apks_path = "$root_build_dir/apks/$_bundle_name.apks"
    action_with_pydeps("${_target_name}_apks") {
      script = "//chromium/build/android/gyp/create_app_bundle_apks.py"
      inputs = [ _bundle_path ]
      outputs = [ _apks_path ]
      data = [ _apks_path ]
      args = [
        "--bundle",
        _rebased_bundle_path,
        "--output",
        rebase_path(_apks_path, root_build_dir),
        "--aapt2-path",
        rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir),
        "--keystore-path",
        rebase_path(android_keystore_path, root_build_dir),
        "--keystore-name",
        android_keystore_name,
        "--keystore-password",
        android_keystore_password,
      ]
      if (debuggable_apks) {
        args += [ "--local-testing" ]
      }
      deps = [ ":$_bundle_target_name" ]
      metadata = {
        install_artifacts = [ _apks_path ]
      }
      if (defined(invoker.static_library_provider)) {
        metadata.install_artifacts_barrier = []
      }

      # http://crbug.com/725224. Fix for bots running out of memory.
      if (defined(java_cmd_pool_size)) {
        pool = "//chromium/build/config/android:java_cmd_pool($default_toolchain)"
      } else {
        pool = "//chromium/build/toolchain:link_pool($default_toolchain)"
      }
    }
  }

  # Create an .apks file from an .aab file. The .apks file will contain the
  # minimal set of .apk files needed for tracking binary size.
  # The file will be created at "$bundle_path_without_extension.minimal.apks".
  #
  # Variables:
  #   bundle_path: Path to the input .aab file.
  #
  # Example:
  #   create_app_bundle_minimal_apks("minimal_apks") {
  #     deps = [
  #       ":bundle_target",
  #     ]
  #     bundle_path = "$root_build_dir/apks/Bundle.aab"
  #   }
  template("create_app_bundle_minimal_apks") {
    action_with_pydeps(target_name) {
      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ])
      script = "//chromium/build/android/gyp/create_app_bundle_apks.py"
      _dir = get_path_info(invoker.bundle_path, "dir")
      _name = get_path_info(invoker.bundle_path, "name")
      _output_path = "$_dir/$_name.minimal.apks"
      outputs = [ _output_path ]
      inputs = [ invoker.bundle_path ]
      args = [
        "--bundle",
        rebase_path(invoker.bundle_path, root_build_dir),
        "--output",
        rebase_path(_output_path, root_build_dir),
        "--aapt2-path",
        rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir),
        "--keystore-path",
        rebase_path(android_keystore_path, root_build_dir),
        "--keystore-name",
        android_keystore_name,
        "--keystore-password",
        android_keystore_password,
        "--minimal",
      ]
    }
  }
}

# Generate an Android resources target that contains localized strings
# describing the current locale used by the Android framework to display
# UI strings. These are used by
# org.chromium.chrome.browser.ChromeLocalizationUtils.
#
# Variables:
#    ui_locales: List of Chromium locale names to generate resources for.
#
template("generate_ui_locale_resources") {
  _generating_target_name = "${target_name}__generate"
  _rebased_output_zip_path = rebase_path(target_gen_dir, root_gen_dir)
  _output_zip = "${root_out_dir}/resource_zips/${_rebased_output_zip_path}/" +
                "${target_name}.zip"

  action_with_pydeps(_generating_target_name) {
    script = "//chromium/build/android/gyp/create_ui_locale_resources.py"
    outputs = [ _output_zip ]
    args = [
      "--locale-list=${invoker.ui_locales}",
      "--output-zip",
      rebase_path(_output_zip, root_build_dir),
    ]
  }

  android_generated_resources(target_name) {
    generating_target = ":$_generating_target_name"
    generated_resources_zip = _output_zip
  }
}

[zur Elbe Produktseite wechseln0.89QuellennavigatorsAnalyse erneut starten2026-04-26]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge