chromium/build/config/android/system_image.gni

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

import("//build/config/android/rules.gni")

# Creates a stub .apk suitable for use with compressed system APKs.
#
# Variables:
#   package_name: Package name to use for the stub.
#   version_code: Version code for the stub.
#   version_name: Version name for the stub.
#   package_info_from_target: Use the package name and version_code from this
#       apk/bundle target.
#   static_library_name: For static library apks, name for the <static-library>.
#   static_library_version: For static library apks, version for the
#       <static-library> tag (for TrichromeLibrary, we set this to be the same
#       as the package's version_code)
#   stub_output: Path to output stub apk (default: do not create a stub).
#
# package_name and package_info_from_target are mutually exclusive.
template("system_image_stub_apk") {
  # Android requires stubs end with -Stub.apk.
  assert(filter_exclude([ invoker.stub_output ], [ "*-Stub.apk" ]) == [],
         "stub_output \"${invoker.stub_output}\" must end with \"-Stub.apk\"")

  _resource_apk_path = "${target_out_dir}/$target_name.ap_"
  _resource_apk_target_name = "${target_name}__compile_resources"

  _manifest_target_name = "${target_name}__manifest"
  _manifest_path = "$target_gen_dir/$_manifest_target_name.xml"
  action("$_manifest_target_name") {
    outputs = [ _manifest_path ]
    script = "//build/android/gyp/create_stub_manifest.py"
    args = [
      "--output",
      rebase_path(_manifest_path, root_build_dir),
    ]
    if (defined(invoker.static_library_name)) {
      args += [
        "--static-library-name",
        invoker.static_library_name,
      ]

      # TODO(crbug.com/40253411): Make static_library_version mandatory.
      if (defined(invoker.static_library_version)) {
        args += [
          "--static-library-version",
          invoker.static_library_version,
        ]
      } else {
        args += [ "--static-library-version=1" ]
      }
    }
  }

  _target_sdk_version = default_android_sdk_version
  if (defined(invoker.override_target_sdk)) {
    _target_sdk_version = invoker.override_target_sdk
  }

  action_with_pydeps(_resource_apk_target_name) {
    script = "//build/android/gyp/compile_resources.py"
    inputs = [
      _manifest_path,
      android_sdk_tools_bundle_aapt2,
      android_sdk_jar,

      # TODO(b/315080809#comment4): remove these files after fixing
      # build/print_python_deps.py.
      "//third_party/protobuf/python/google/__init__.py",
      "//third_party/protobuf/python/google/protobuf/__init__.py",
      "//third_party/protobuf/python/google/protobuf/compiler/__init__.py",
      "//third_party/protobuf/python/google/protobuf/compiler/plugin_pb2.py",
      "//third_party/protobuf/python/google/protobuf/descriptor.py",
      "//third_party/protobuf/python/google/protobuf/descriptor_database.py",
      "//third_party/protobuf/python/google/protobuf/descriptor_pb2.py",
      "//third_party/protobuf/python/google/protobuf/descriptor_pool.py",
      "//third_party/protobuf/python/google/protobuf/internal/__init__.py",
      "//third_party/protobuf/python/google/protobuf/internal/_parameterized.py",
      "//third_party/protobuf/python/google/protobuf/internal/api_implementation.py",
      "//third_party/protobuf/python/google/protobuf/internal/builder.py",
      "//third_party/protobuf/python/google/protobuf/internal/containers.py",
      "//third_party/protobuf/python/google/protobuf/internal/decoder.py",
      "//third_party/protobuf/python/google/protobuf/internal/descriptor_database_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/descriptor_pool_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/descriptor_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/encoder.py",
      "//third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py",
      "//third_party/protobuf/python/google/protobuf/internal/extension_dict.py",
      "//third_party/protobuf/python/google/protobuf/internal/generator_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/import_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/import_test_package/__init__.py",
      "//third_party/protobuf/python/google/protobuf/internal/json_format_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/keywords_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/message_factory_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/message_listener.py",
      "//third_party/protobuf/python/google/protobuf/internal/message_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/proto_builder_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/python_message.py",
      "//third_party/protobuf/python/google/protobuf/internal/reflection_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/service_reflection_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/symbol_database_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/test_util.py",
      "//third_party/protobuf/python/google/protobuf/internal/testing_refleaks.py",
      "//third_party/protobuf/python/google/protobuf/internal/text_encoding_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/text_format_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/type_checkers.py",
      "//third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/well_known_types.py",
      "//third_party/protobuf/python/google/protobuf/internal/well_known_types_test.py",
      "//third_party/protobuf/python/google/protobuf/internal/wire_format.py",
      "//third_party/protobuf/python/google/protobuf/internal/wire_format_test.py",
      "//third_party/protobuf/python/google/protobuf/json_format.py",
      "//third_party/protobuf/python/google/protobuf/message.py",
      "//third_party/protobuf/python/google/protobuf/message_factory.py",
      "//third_party/protobuf/python/google/protobuf/proto_builder.py",
      "//third_party/protobuf/python/google/protobuf/pyext/__init__.py",
      "//third_party/protobuf/python/google/protobuf/pyext/cpp_message.py",
      "//third_party/protobuf/python/google/protobuf/reflection.py",
      "//third_party/protobuf/python/google/protobuf/service.py",
      "//third_party/protobuf/python/google/protobuf/service_reflection.py",
      "//third_party/protobuf/python/google/protobuf/symbol_database.py",
      "//third_party/protobuf/python/google/protobuf/text_encoding.py",
      "//third_party/protobuf/python/google/protobuf/text_format.py",
      "//third_party/protobuf/python/google/protobuf/unknown_fields.py",
      "//third_party/protobuf/python/google/protobuf/util/__init__.py",
    ]
    outputs = [ _resource_apk_path ]
    args = [
      "--aapt2-path",
      rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir),
      "--min-sdk-version=$default_min_sdk_version",
      "--target-sdk-version=$_target_sdk_version",
      "--android-manifest",
      rebase_path(_manifest_path, root_build_dir),
      "--arsc-path",
      rebase_path(_resource_apk_path, root_build_dir),
    ]
    deps = [ ":$_manifest_target_name" ]
    if (defined(invoker.package_name)) {
      _package_name = invoker.package_name
      _version_code = invoker.version_code
      _version_name = invoker.version_name

      # TODO(crbug.com/40253411): Make static_library_version mandatory.
      if (defined(invoker.static_library_version)) {
        assert(invoker.static_library_version == _version_code,
               "$invoker.static_library_version must equal $_version_code.")
      }
    } else {
      _target = invoker.package_info_from_target
      deps += [ "${_target}$build_config_target_suffix" ]
      _build_config = get_label_info(_target, "target_gen_dir") + "/" +
                      get_label_info(_target, "name") + ".build_config.json"
      inputs += [ _build_config ]
      _rebased_build_config = rebase_path(_build_config, root_build_dir)
      _package_name = "@FileArg($_rebased_build_config:deps_info:package_name)"
      _version_code = "@FileArg($_rebased_build_config:deps_info:version_code)"
      _version_name = "@FileArg($_rebased_build_config:deps_info:version_name)"

      # TODO(crbug.com/40253411): Make static_library_version mandatory.
      # Pass this through to ensure that the version code in the build config is
      # the same as the static library version.
      if (defined(invoker.static_library_version)) {
        args += [
          "--static-library-version",
          invoker.static_library_version,
        ]
      }
    }

    args += [
      "--rename-manifest-package=$_package_name",
      "--arsc-package-name=$_package_name",
      "--version-code=$_version_code",
      "--version-name=$_version_name",
      "--include-resources",
      rebase_path(android_sdk_jar, root_build_dir),
    ]
  }

  package_apk(target_name) {
    forward_variables_from(invoker,
                           [
                             "keystore_name",
                             "keystore_path",
                             "keystore_password",
                           ])
    min_sdk_version = default_min_sdk_version
    deps = [ ":$_resource_apk_target_name" ]

    packaged_resources_path = _resource_apk_path
    output_apk_path = invoker.stub_output
  }
}

# Generates artifacts for system APKs.
#
# Variables:
#   apk_or_bundle_target: Target that creates input bundle or apk.
#   input_apk_or_bundle: Path to input .apk or .aab.
#   static_library_name: For static library apks, name for the <static-library>.
#   static_library_version: For static library apks, version for the
#       <static-library> tag (for TrichromeLibrary, we set this to be the same
#       as the package's version_code)
#   output: Path to the output system .apk or .zip.
#   fuse_apk: Fuse all apk splits into a single .apk (default: false).
#   stub_output: Path to output stub apk (default: do not create a stub).
#
template("system_image_apks") {
  if (defined(invoker.stub_output)) {
    _stub_apk_target_name = "${target_name}__stub"
    system_image_stub_apk(_stub_apk_target_name) {
      forward_variables_from(invoker,
                             [
                               "static_library_name",
                               "static_library_version",
                               "override_target_sdk",
                             ])
      package_info_from_target = invoker.apk_or_bundle_target
      stub_output = invoker.stub_output
    }
  }

  action_with_pydeps(target_name) {
    script = "//build/android/gyp/system_image_apks.py"
    deps = [ invoker.apk_or_bundle_target ]
    inputs = [ invoker.input_apk_or_bundle ]
    if (defined(invoker.stub_output)) {
      public_deps = [ ":$_stub_apk_target_name" ]
    }
    outputs = [ invoker.output ]
    args = [
      "--input",
      rebase_path(invoker.input_apk_or_bundle, root_out_dir),
      "--output",
      rebase_path(invoker.output, root_out_dir),
    ]

    _is_bundle =
        filter_exclude([ invoker.input_apk_or_bundle ], [ "*.aab" ]) == []

    if (_is_bundle) {
      _wrapper_path = "$root_out_dir/bin/" +
                      get_label_info(invoker.apk_or_bundle_target, "name")
      args += [
        "--bundle-wrapper",
        rebase_path(_wrapper_path, root_out_dir),
      ]
      inputs += [ _wrapper_path ]
      deps += [ "//build/android:apk_operations_py" ]
      if (defined(invoker.fuse_apk) && invoker.fuse_apk) {
        args += [ "--fuse-apk" ]
      }
    }
  }
}