0

Reland "JNI: Only using 1 registration per apk"

This reverts commit 6f773ca0c8.

Reason for revert: Now I'm keeping around the extra jni_registration
until I can migrate all uses off of it.

Original change's description:
> Revert "JNI: Only using 1 registration per apk"
>
> This reverts commit a74d255224.
>
> Reason for revert: broke internal bots
>
> Original change's description:
> > JNI: Only using 1 registration per apk
> >
> > We now associate a JNI registration with a native library, via our new
> > native_with_jni template. We no longer have a generate_jni_registration
> > happening with pure Java in the apk template.
> >
> > We now only output 1 GEN_JNI per srcjar, and instead of collecting all
> > JNI from modules and outputting many GEN_JNIs in one srcjar.
> >
> > Bug: 1406611
> > Change-Id: Iec40dc7c443e206f177fa8a7d5f9635cefa4c747
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4219332
> > Commit-Queue: Sam Maier <smaier@chromium.org>
> > Owners-Override: Sam Maier <smaier@chromium.org>
> > Reviewed-by: Andrew Grieve <agrieve@chromium.org>
> > Cr-Commit-Position: refs/heads/main@{#1142236}
>
> Bug: 1406611
> Change-Id: Ifedf95de229bd16039ae026dfe3ccc90b66f154c
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4518235
> Commit-Queue: Lijin Shen <lazzzis@google.com>
> Auto-Submit: Sam Maier <smaier@chromium.org>
> Reviewed-by: Lijin Shen <lazzzis@google.com>
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Owners-Override: Lijin Shen <lazzzis@google.com>
> Cr-Commit-Position: refs/heads/main@{#1142294}

Bug: 1406611
Change-Id: Ic483f87d33d58bf5c8655878b133e31755b6a25e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4518389
Auto-Submit: Sam Maier <smaier@chromium.org>
Commit-Queue: Sam Maier <smaier@chromium.org>
Owners-Override: Andrew Grieve <agrieve@chromium.org>
Reviewed-by: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1144064}
This commit is contained in:
Sam Maier
2023-05-15 14:00:22 +00:00
committed by Chromium LUCI CQ
parent 527edb2c8a
commit 7acb8d6bc8
30 changed files with 741 additions and 319 deletions
android_webview
base/android/jni_generator
build/config/android
chrome/android
components/cronet/android
content/shell/android
mojo/public/java/system
net/android
testing

@ -9,6 +9,7 @@ import("//android_webview/webview_repack_locales.gni")
import("//build/android/resource_sizes.gni")
import("//build/config/android/channel.gni")
import("//build/config/android/config.gni")
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
import("//build/config/cronet/config.gni")
import("//build/config/locales.gni")
@ -38,6 +39,14 @@ if (enable_resource_allowlist_generation) {
"$target_gen_dir/system_webview_pak_allowlist.txt"
}
if (android_64bit_target_cpu) {
# We are assuming that all webview targets have the same Java - if this
# is no longer true, we should add more targets to this array.
webview_java_for_jni_targets = [ ":system_webview_64_bundle" ]
} else {
webview_java_for_jni_targets = [ ":system_webview_bundle" ]
}
template("standalone_system_webview_apk_tmpl") {
system_webview_apk_or_module_tmpl(target_name) {
forward_variables_from(invoker, "*")
@ -93,7 +102,6 @@ if (android_64bit_target_cpu && skip_secondary_abi_for_cq) {
standalone_system_webview_apk_tmpl("system_webview_base_bundle_module") {
target_type = "android_app_bundle_module"
is_base_module = true
bundle_target = ":system_webview_bundle"
if (enable_manifest_verification) {
expected_android_manifest =
@ -131,7 +139,6 @@ if (android_64bit_target_cpu) {
standalone_system_webview_apk_tmpl("system_webview_64_base_bundle_module") {
target_type = "android_app_bundle_module"
is_base_module = true
bundle_target = ":system_webview_64_bundle"
include_32_bit_webview = false
}
@ -153,7 +160,6 @@ if (android_64bit_target_cpu) {
target_type = "android_app_bundle_module"
include_64_bit_webview = false
is_base_module = true
bundle_target = ":system_webview_32_bundle"
}
system_webview_bundle("system_webview_32_bundle") {
@ -205,7 +211,6 @@ if (android_64bit_target_cpu && skip_secondary_abi_for_cq) {
trichrome_webview_tmpl("trichrome_webview_base_bundle_module") {
target_type = "android_app_bundle_module"
is_base_module = true
bundle_target = ":trichrome_webview_bundle"
if (android_64bit_target_cpu) {
is_64_bit_browser = false
include_64_bit_webview = true
@ -245,7 +250,6 @@ if (android_64bit_target_cpu) {
trichrome_webview_tmpl("trichrome_webview_64_base_bundle_module") {
target_type = "android_app_bundle_module"
is_base_module = true
bundle_target = ":trichrome_webview_64_bundle"
is_64_bit_browser = true
include_32_bit_webview = false
static_library_provider = "//chrome/android:trichrome_library_64_apk"
@ -285,7 +289,6 @@ if (android_64bit_target_cpu && !skip_secondary_abi_for_cq) {
trichrome_webview_64_32_tmpl("trichrome_webview_64_32_base_bundle_module") {
target_type = "android_app_bundle_module"
is_base_module = true
bundle_target = ":trichrome_webview_64_32_bundle"
}
system_webview_bundle("trichrome_webview_64_32_bundle") {
@ -318,7 +321,6 @@ if (android_64bit_target_cpu && !skip_secondary_abi_for_cq) {
trichrome_webview_32_tmpl("trichrome_webview_32_base_bundle_module") {
target_type = "android_app_bundle_module"
is_base_module = true
bundle_target = ":trichrome_webview_32_bundle"
}
system_webview_bundle("trichrome_webview_32_bundle") {
@ -333,16 +335,9 @@ if (android_64bit_target_cpu && !skip_secondary_abi_for_cq) {
}
}
if (allow_jni_multiplexing && current_toolchain == default_toolchain) {
generate_jni_registration("webview_jni_registration") {
targets = [ _main_webview_bundle_target ]
enable_jni_multiplexing = true
}
}
# The shared library used by standalone WebView.
template("libwebviewchromium_tmpl") {
shared_library(target_name) {
shared_library_with_jni(target_name) {
forward_variables_from(invoker, "*")
deps = [
"//android_webview/lib",
@ -350,14 +345,18 @@ template("libwebviewchromium_tmpl") {
"//android_webview/nonembedded",
"//third_party/blink/public:blink",
]
if (allow_jni_multiplexing) {
deps += [ ":webview_jni_registration($default_toolchain)" ]
}
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [
"//build/config/android:hide_all_but_jni",
"//build/config/compiler:chrome_orderfile_config",
]
java_targets = webview_java_for_jni_targets
# WebView's native side has more JNI present than the Java side. This is
# because our native dependencies don't match 1:1 to our Java dependencies,
# so there are some Chrome-only native dependencies that sneak into WebView.
# To fix, we can just remove any uncalled Java->Native methods.
remove_uncalled_jni = true
}
}
@ -384,11 +383,12 @@ template("webview_alternate_library") {
"//android_webview/lib:webview_entry_point",
"//android_webview/nonembedded",
]
if (allow_jni_multiplexing) {
deps += [ ":webview_jni_registration($default_toolchain)" ]
enable_jni_multiplexing = true
}
is_webview = true
java_targets = webview_java_for_jni_targets
# Webview's native side naturally will have more JNI present than the Java
# side. We can just remove any uncalled Java->Native methods.
remove_uncalled_jni = true
}
}

@ -67,11 +67,6 @@ source_set("webview_entry_point") {
sources = [ "webview_entry_point.cc" ]
defines = []
if (allow_jni_multiplexing) {
defines += [ "JNI_REGISTRATION_REQUIRED" ]
deps += [ "//android_webview:webview_jni_registration($default_toolchain)" ]
}
if (webview_includes_weblayer) {
defines += [ "WEBVIEW_INCLUDES_WEBLAYER" ]
deps += [ "//weblayer:weblayer_lib" ]

@ -244,6 +244,28 @@ template("system_webview_apk_or_module_tmpl") {
native_lib_placeholders = [ "libdummy.so" ]
}
}
if (defined(shared_libraries)) {
_jni_registrations = shared_libraries
} else if (defined(secondary_abi_shared_libraries)) {
_jni_registrations = secondary_abi_shared_libraries
} else if (_is_trichrome) {
# Here, the only native library present in trichrome is the one shared
# between Chrome and WebView, so we depend on it instead.
if (android_64bit_target_cpu) {
_jni_registrations = [ "//chrome/android:libmonochrome_64" ]
} else {
_jni_registrations = [ "//chrome/android:libmonochrome" ]
}
}
if (defined(_jni_registrations)) {
srcjar_deps = []
foreach(_lib, _jni_registrations) {
_label =
get_label_info(_lib, "label_no_toolchain") + "__jni_registration"
_toolchain = get_label_info(_lib, "toolchain")
srcjar_deps += [ "$_label($_toolchain)" ]
}
}
_include_arcore =
webview_includes_weblayer && enable_arcore && !_exclude_weblayer_java &&

@ -4,6 +4,7 @@
import("//android_webview/system_webview_apk_tmpl.gni")
import("//android_webview/variables.gni")
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
import("//build/config/python.gni")
import("//device/vr/buildflags/buildflags.gni")
@ -143,6 +144,7 @@ android_apk("webview_instrumentation_apk") {
product_config_java_packages = [ webview_product_config_java_package ]
shared_libraries = [ ":libstandalonelibwebviewchromium" ]
srcjar_deps = [ ":libstandalonelibwebviewchromium__jni_registration" ]
command_line_flags_file = "android-webview-command-line"
}
@ -198,7 +200,7 @@ android_library("draw_fn_impl_java") {
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
shared_library("libstandalonelibwebviewchromium") {
shared_library_with_jni("libstandalonelibwebviewchromium") {
testonly = true
sources = [
"shell/src/draw_fn/allocator.cc",
@ -230,6 +232,7 @@ shared_library("libstandalonelibwebviewchromium") {
libs = [ "android" ]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
java_targets = [ ":webview_instrumentation_apk" ]
}
instrumentation_test_apk("webview_instrumentation_test_apk") {
@ -493,6 +496,7 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
"//android_webview/test/embedded_test_server:aw_net_test_support_apk",
"//net/android:net_test_support_apk",
]
srcjar_deps = [ ":libstandalonelibwebviewchromium__jni_registration" ]
}
android_library("webview_instrumentation_test_mock_services_java") {

@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/android/config.gni")
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
android_library("aw_net_java_test_support") {
@ -48,7 +49,7 @@ source_set("aw_java_test_native_support") {
]
}
shared_library("aw_net_java_test_native_support") {
shared_library_with_jni("aw_net_java_test_native_support") {
testonly = true
deps = [
":aw_java_test_native_support",
@ -56,6 +57,7 @@ shared_library("aw_net_java_test_native_support") {
]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
java_targets = [ ":aw_net_test_support_apk" ]
}
android_apk("aw_net_test_support_apk") {
@ -72,4 +74,5 @@ android_apk("aw_net_test_support_apk") {
android_manifest = "java/AndroidManifest.xml"
apk_name = "ChromiumNetTestAwSupport"
shared_libraries = [ ":aw_net_java_test_native_support" ]
srcjar_deps = [ ":aw_net_java_test_native_support__jni_registration" ]
}

@ -49,7 +49,7 @@ source_set("jni_sample_native_side") {
}
generate_jni_registration("jni_registration") {
targets = [ ":jni_sample_java" ]
java_targets = [ ":jni_sample_java" ]
manual_jni_registration = true
}

@ -0,0 +1,62 @@
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.base.natives;
// This file is autogenerated by
// base/android/jni_generator/jni_registration_generator.py
// Please do not change its content.
public class GEN_JNI {
public static final boolean TESTING_ENABLED = false;
public static final boolean REQUIRE_MOCK = false;
// Hashed name: Java_J_N_MygCV2jQ
public static native void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_foo();
// Hashed name: Java_J_N_MHuqnmXT
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_bar(Object sample);
// Hashed name: Java_J_N_MM5Xkwyy
public static native String org_chromium_example_jni_1generator_SampleForAnnotationProcessor_revString(String stringToReverse);
// Hashed name: Java_J_N_MAC2QhR9
public static native String[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_sendToNative(String[] strs);
// Hashed name: Java_J_N_MGhRh4Nd
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_sendSamplesToNative(Object[] strs);
// Hashed name: Java_J_N_MW0aEs4h
public static native boolean org_chromium_example_jni_1generator_SampleForAnnotationProcessor_hasPhalange();
// Hashed name: Java_J_N_MlVFI4RX
public static native int[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_testAllPrimitives(int zint, int[] ints, long zlong, long[] longs, short zshort, short[] shorts, char zchar, char[] chars, byte zbyte, byte[] bytes, double zdouble, double[] doubles, float zfloat, float[] floats, boolean zbool, boolean[] bools);
// Hashed name: Java_J_N_MqOnlud7
public static native void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_testSpecialTypes(Class clazz, Class[] classes, Throwable throwable, Throwable[] throwables, String string, String[] strings, Object tStruct, Object[] structs, Object obj, Object[] objects);
// Hashed name: Java_J_N_MuZc76Vt
public static native Throwable org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnThrowable();
// Hashed name: Java_J_N_MAD53J7V
public static native Throwable[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnThrowables();
// Hashed name: Java_J_N_M$ZgOi4g
public static native Class org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnClass();
// Hashed name: Java_J_N_M$hL1577
public static native Class[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnClasses();
// Hashed name: Java_J_N_M0k1OjBK
public static native String org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnString();
// Hashed name: Java_J_N_Mssfs54E
public static native String[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStrings();
// Hashed name: Java_J_N_MSzcel_H
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStruct();
// Hashed name: Java_J_N_MIBrQLK4
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStructs();
// Hashed name: Java_J_N_M$hPywjv
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObject();
// Hashed name: Java_J_N_MPpCU1l5
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObjects();
// Hashed name: Java_J_N_MaWxcVuD
public static native void org_chromium_example_jni_1generator_TinySample2_test();
public static void org_chromium_example_jni_1generator_TinySample_foo() {
throw new RuntimeException("Stub - not implemented!");
}
public static boolean org_chromium_example_jni_1generator_TinySample_bar(int a) {
throw new RuntimeException("Stub - not implemented!");
}
}

@ -0,0 +1,14 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.example.jni_generator;
import org.chromium.base.annotations.NativeMethods;
class TinySample2 {
@NativeMethods()
interface Natives {
void test();
}
}

@ -67,6 +67,8 @@ class JniRegistrationGeneratorOptions(object):
self.header_path = None
self.module_name = ''
self.package_prefix = None
self.remove_uncalled_methods = False
self.add_stubs_for_missing_native = False
class BaseTest(unittest.TestCase):
@ -82,21 +84,31 @@ class BaseTest(unittest.TestCase):
self.AssertGoldenTextEquals(contents, golden)
def _TestEndToEndRegistration(self,
input_java_src_files,
input_src_files,
options,
name_to_goldens,
src_files_for_asserts_and_stubs=None,
header_golden=None):
with tempfile.TemporaryDirectory() as tdir:
options.srcjar_path = os.path.join(tdir, 'srcjar.jar')
if header_golden:
options.header_path = os.path.join(tdir, 'header.h')
input_java_paths = [
input_java_paths = {
self._JoinScriptDir(os.path.join(_JAVA_SRC_DIR, f))
for f in input_java_src_files
]
for f in input_src_files
}
jni_registration_generator._Generate(options, input_java_paths)
if src_files_for_asserts_and_stubs:
asserts_and_stubs_java_paths = {
self._JoinScriptDir(os.path.join(_JAVA_SRC_DIR, f))
for f in src_files_for_asserts_and_stubs
}
else:
asserts_and_stubs_java_paths = input_java_paths
jni_registration_generator._Generate(options, input_java_paths,
asserts_and_stubs_java_paths)
with zipfile.ZipFile(options.srcjar_path, 'r') as srcjar:
for name in srcjar.namelist():
self.assertTrue(
@ -241,15 +253,29 @@ class Tests(BaseTest):
options.use_proxy_hash = True
options.module_name = 'module'
name_to_goldens = {
'org/chromium/base/natives/GEN_JNI.java':
'SampleForAnnotationProcessor_proxy_GenJni.java.golden',
'J/N.java': 'SampleForAnnotationProcessor_proxy_JN.java.golden',
'org/chromium/base/natives/module_GEN_JNI.java':
'SampleModuleGenJni.golden',
'J/module_N.java': 'SampleModuleJN.golden'
}
self._TestEndToEndRegistration(input_java_files, options, name_to_goldens)
def testStubRegistration(self):
input_java_files = ['SampleForAnnotationProcessor.java']
stubs_java_files = input_java_files + ['TinySample.java']
extra_input_java_files = ['TinySample2.java']
options = JniRegistrationGeneratorOptions()
options.add_stubs_for_missing_native = True
options.remove_uncalled_methods = True
name_to_goldens = {
'org/chromium/base/natives/GEN_JNI.java': 'StubGenJni.golden',
'J/N.java': 'HashedSampleForAnnotationProcessorGenJni.golden'
}
self._TestEndToEndRegistration(
input_java_files + extra_input_java_files,
options,
name_to_goldens,
src_files_for_asserts_and_stubs=stubs_java_files)
def testForTestingKept(self):
input_java_file = 'SampleProxyEdgeCases.java'
gen_options = JniGeneratorOptions()
@ -321,7 +347,10 @@ class Tests(BaseTest):
'SampleForAnnotationProcessor_package_prefix_manual_GenJni.java.golden',
}
self._TestEndToEndRegistration(
input_java_files, options, name_to_goldens,
input_java_files,
options,
name_to_goldens,
header_golden=
'SampleForAnnotationProcessor_package_prefix_manual.h.golden')
def testPackagePrefixWithProxyHash(self):
@ -350,7 +379,10 @@ class Tests(BaseTest):
'SampleForAnnotationProcessor_package_prefix_proxy_manual_JN.java.golden',
}
self._TestEndToEndRegistration(
input_java_files, options, name_to_goldens,
input_java_files,
options,
name_to_goldens,
header_golden=
'SampleForAnnotationProcessor_package_prefix_proxy_manual.h.golden')
def testMultiplexing(self):
@ -364,8 +396,10 @@ class Tests(BaseTest):
'J/N.java': 'SampleForAnnotationProcessor_multiplexing_JN.java.golden',
}
self._TestEndToEndRegistration(
input_java_files, options, name_to_goldens,
'SampleForAnnotationProcessor_multiplexing.h.golden')
input_java_files,
options,
name_to_goldens,
header_golden='SampleForAnnotationProcessor_multiplexing.h.golden')
def TouchStamp(stamp_path):

@ -36,7 +36,7 @@ MERGEABLE_KEYS = [
]
def _Generate(options, java_file_paths):
def _Generate(options, native_sources, java_sources):
"""Generates files required to perform JNI registration.
Generates a srcjar containing a single class, GEN_JNI, that contains all
@ -47,126 +47,209 @@ def _Generate(options, java_file_paths):
Args:
options: arguments from the command line
java_file_paths: A list of java file paths.
native_sources: A list of java file paths. The source of truth.
java_sources: A list of java file paths. Used to assert against
native_sources.
"""
# Without multiprocessing, script takes ~13 seconds for chrome_public_apk
# on a z620. With multiprocessing, takes ~2 seconds.
results = collections.defaultdict(list)
results = []
cached_results_for_stubs = {}
with multiprocessing.Pool() as pool:
for d in pool.imap_unordered(functools.partial(_DictForPath, options),
java_file_paths):
# The native-based sources are the "source of truth" - the Java based ones
# will be used later to generate stubs and make assertions.
for result in pool.imap_unordered(functools.partial(_DictForPath, options),
native_sources):
d, path, natives = result
if d:
results[d['MODULE_NAME']].append(d)
results.append(d)
cached_results_for_stubs[path] = natives
combined_dicts = collections.defaultdict(dict)
for module_name, module_results in results.items():
# Sort to make output deterministic.
module_results.sort(key=lambda d: d['FULL_CLASS_NAME'])
combined_dict = combined_dicts[module_name]
for key in MERGEABLE_KEYS:
combined_dict[key] = ''.join(d.get(key, '') for d in module_results)
used_sources = {d['FILE_PATH'] for d in results}
stubs_file_paths = _GenerateStubsAndAssert(options, used_sources,
java_sources,
cached_results_for_stubs)
# Sort to make output deterministic.
results.sort(key=lambda d: d['FULL_CLASS_NAME'])
# PROXY_NATIVE_SIGNATURES and PROXY_NATIVE_METHOD_ARRAY will have
# duplicates for JNI multiplexing since all native methods with similar
# signatures map to the same proxy. Similarly, there may be multiple switch
# case entries for the same proxy signatures.
if options.enable_jni_multiplexing:
proxy_signatures_list = sorted(
set(combined_dict['PROXY_NATIVE_SIGNATURES'].split('\n')))
combined_dict['PROXY_NATIVE_SIGNATURES'] = '\n'.join(
signature for signature in proxy_signatures_list)
combined_dict = {}
for key in MERGEABLE_KEYS:
combined_dict[key] = ''.join(d.get(key, '') for d in results)
proxy_native_array_list = sorted(
set(combined_dict['PROXY_NATIVE_METHOD_ARRAY'].split('},\n')))
combined_dict['PROXY_NATIVE_METHOD_ARRAY'] = '},\n'.join(
p for p in proxy_native_array_list if p != '') + '}'
# PROXY_NATIVE_SIGNATURES and PROXY_NATIVE_METHOD_ARRAY will have
# duplicates for JNI multiplexing since all native methods with similar
# signatures map to the same proxy. Similarly, there may be multiple switch
# case entries for the same proxy signatures.
if options.enable_jni_multiplexing:
proxy_signatures_list = sorted(
set(combined_dict['PROXY_NATIVE_SIGNATURES'].split('\n')))
combined_dict['PROXY_NATIVE_SIGNATURES'] = '\n'.join(
signature for signature in proxy_signatures_list)
signature_to_cases = collections.defaultdict(list)
for d in module_results:
for signature, cases in d['SIGNATURE_TO_CASES'].items():
signature_to_cases[signature].extend(cases)
combined_dict['FORWARDING_CALLS'] = _AddForwardingCalls(
signature_to_cases, module_name, options.package_prefix)
proxy_native_array_list = sorted(
set(combined_dict['PROXY_NATIVE_METHOD_ARRAY'].split('},\n')))
combined_dict['PROXY_NATIVE_METHOD_ARRAY'] = '},\n'.join(
p for p in proxy_native_array_list if p != '') + '}'
signature_to_cases = collections.defaultdict(list)
for d in results:
for signature, cases in d['SIGNATURE_TO_CASES'].items():
signature_to_cases[signature].extend(cases)
combined_dict['FORWARDING_CALLS'] = _AddForwardingCalls(
signature_to_cases, options.module_name, options.package_prefix)
if options.header_path:
assert len(
combined_dicts) == 1, 'Cannot output a header for multiple modules'
module_name = next(iter(combined_dicts))
combined_dict = combined_dicts[module_name]
header_guard = os.path.splitext(options.header_path)[0].upper() + '_'
header_guard = re.sub(r'[/.-]', '_', header_guard)
combined_dict['HEADER_GUARD'] = header_guard
combined_dict['NAMESPACE'] = options.namespace
header_content = CreateFromDict(options, module_name, combined_dict)
header_content = CreateFromDict(options, combined_dict)
with action_helpers.atomic_output(options.header_path, mode='w') as f:
f.write(header_content)
stub_methods = []
if stubs_file_paths:
for f in stubs_file_paths:
stub_dict = _DictForPath(
options,
f,
stub_only=True,
cached_results_for_stubs=cached_results_for_stubs)[0]
if stub_dict:
stub_methods.append(stub_dict['STUBS'])
stub_methods_string = ''.join(stub_methods)
with action_helpers.atomic_output(options.srcjar_path) as f:
with zipfile.ZipFile(f, 'w') as srcjar:
for module_name, combined_dict in combined_dicts.items():
if options.use_proxy_hash or options.enable_jni_multiplexing:
# J/N.java
zip_helpers.add_to_zip_hermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(
True, module_name, options.package_prefix),
data=CreateProxyJavaFromDict(options, module_name, combined_dict))
# org/chromium/base/natives/GEN_JNI.java
zip_helpers.add_to_zip_hermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(
False, module_name, options.package_prefix),
data=CreateProxyJavaFromDict(options,
module_name,
combined_dict,
forwarding=True))
else:
# org/chromium/base/natives/GEN_JNI.java
zip_helpers.add_to_zip_hermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(
False, module_name, options.package_prefix),
data=CreateProxyJavaFromDict(options, module_name, combined_dict))
if options.use_proxy_hash or options.enable_jni_multiplexing:
# J/N.java
zip_helpers.add_to_zip_hermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(
True, options.module_name, options.package_prefix),
data=CreateProxyJavaFromDict(options, combined_dict))
# org/chromium/base/natives/GEN_JNI.java
zip_helpers.add_to_zip_hermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(
False, options.module_name, options.package_prefix),
data=CreateProxyJavaFromDict(options,
combined_dict,
stub_methods=stub_methods_string,
forwarding=True))
else:
# org/chromium/base/natives/GEN_JNI.java
zip_helpers.add_to_zip_hermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(
False, options.module_name, options.package_prefix),
data=CreateProxyJavaFromDict(options,
combined_dict,
stub_methods=stub_methods_string))
def _DictForPath(options, path):
with open(path) as f:
contents = jni_generator.RemoveComments(f.read())
if '@JniIgnoreNatives' in contents:
return None
def _GenerateStubsAndAssert(options, native_sources, java_sources,
cached_results_for_stubs):
native_only = native_sources - java_sources
java_only = java_sources - native_sources
# Using stub_only because we just need this to do a boolean check to see if
# the files have JNI - we don't need any actual output.
java_only = {
f
for f in java_only
if _DictForPath(options,
f,
stub_only=True,
cached_results_for_stubs=cached_results_for_stubs)[0]
}
failed = False
if not options.add_stubs_for_missing_native and java_only:
failed = True
warning_message = '''Failed JNI assertion!
We reference Java files which use JNI, but our native library does not depend on
the corresponding generate_jni().
To bypass this check, you can add stubs to Java with add_stubs_for_missing_jni.
Excess Java files below:
'''
warning_message += str(java_only)
sys.stderr.write(warning_message)
if not options.remove_uncalled_methods and native_only:
failed = True
warning_message = '''Failed JNI assertion!
Our native library depends on generate_jnis which reference Java files that we
do not include in our final dex.
To bypass this check, delete these extra JNI methods with remove_uncalled_jni.
Unneeded Java files below:
'''
warning_message += str(native_only)
sys.stderr.write(warning_message)
if failed:
sys.exit(1)
return java_only
fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName(
path, contents)
if options.package_prefix:
fully_qualified_class = jni_generator.GetFullyQualifiedClassWithPackagePrefix(
fully_qualified_class, options.package_prefix)
def _DictForPath(options, path, stub_only=False, cached_results_for_stubs=None):
# The cached results are generated by the real runs, which happen first, so
# the cache is only for the stub checks after.
assert (cached_results_for_stubs is not None) == stub_only
natives = stub_only and cached_results_for_stubs.get(path)
if not natives:
with open(path) as f:
contents = jni_generator.RemoveComments(f.read())
if '@JniIgnoreNatives' in contents:
return None, path, None
natives, found_module_name = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
fully_qualified_class=fully_qualified_class,
contents=contents,
ptr_type='long',
include_test_only=options.include_test_only)
fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName(
path, contents)
if options.module_name and found_module_name != options.module_name:
# Ignoring any code from modules we aren't looking at.
return None
if options.package_prefix:
fully_qualified_class = jni_generator.GetFullyQualifiedClassWithPackagePrefix(
fully_qualified_class, options.package_prefix)
natives, found_module_name = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
fully_qualified_class=fully_qualified_class,
contents=contents,
ptr_type='long',
include_test_only=options.include_test_only)
if found_module_name != options.module_name:
# Ignoring any code from modules we aren't looking at.
return None, path, None
if not natives:
return None, path, None
if stub_only:
return {'STUBS': _GenerateStubs(natives)}, path, natives
natives += jni_generator.ExtractNatives(contents, 'long')
if len(natives) == 0:
return None
# The namespace for the content is separate from the namespace for the
# generated header file.
content_namespace = jni_generator.ExtractJNINamespace(contents)
jni_params = jni_generator.JniParams(fully_qualified_class)
jni_params.ExtractImportsAndInnerClasses(contents)
dict_generator = DictionaryGenerator(options, found_module_name,
content_namespace, fully_qualified_class,
natives, jni_params)
return dict_generator.Generate()
dict_generator = DictionaryGenerator(options, path, content_namespace,
fully_qualified_class, natives,
jni_params)
return dict_generator.Generate(), path, natives
def _GenerateStubs(natives):
final_string = ''
for native in natives:
template = string.Template("""
public static ${RETURN_TYPE} ${METHOD_NAME}(${PARAMS_WITH_TYPES}) {
throw new RuntimeException("Stub - not implemented!");
}""")
params_with_types = ', '.join('%s %s' % (p.datatype, p.name)
for p in native.params)
final_string += template.substitute({
'RETURN_TYPE': native.return_type,
'METHOD_NAME': native.proxy_name,
'PARAMS_WITH_TYPES': params_with_types,
})
return final_string
def _AddForwardingCalls(signature_to_cases, module_name, package_prefix):
@ -211,7 +294,7 @@ ${CLASS_NAME}_${PROXY_SIGNATURE} was called with an invalid switch number: "\
return ''.join(s for s in switch_statements)
def _SetProxyRegistrationFields(options, module_name, registration_dict):
def _SetProxyRegistrationFields(options, registration_dict):
registration_template = string.Template("""\
static const JNINativeMethod kMethods_${ESCAPED_PROXY_CLASS}[] = {
@ -272,16 +355,19 @@ ${REGISTER_NATIVES}
sub_dict = {
'ESCAPED_PROXY_CLASS':
jni_generator.EscapeClassName(
jni_generator.ProxyHelpers.GetQualifiedClass(short_name, module_name,
jni_generator.ProxyHelpers.GetQualifiedClass(short_name,
options.module_name,
options.package_prefix)),
'PROXY_CLASS':
jni_generator.ProxyHelpers.GetQualifiedClass(short_name, module_name,
jni_generator.ProxyHelpers.GetQualifiedClass(short_name,
options.module_name,
options.package_prefix),
'KMETHODS':
registration_dict['PROXY_NATIVE_METHOD_ARRAY'],
'REGISTRATION_NAME':
jni_generator.GetRegistrationFunctionName(
jni_generator.ProxyHelpers.GetQualifiedClass(short_name, module_name,
jni_generator.ProxyHelpers.GetQualifiedClass(short_name,
options.module_name,
options.package_prefix)),
}
@ -303,8 +389,8 @@ ${REGISTER_NATIVES}
def CreateProxyJavaFromDict(options,
module_name,
registration_dict,
stub_methods='',
forwarding=False):
template = string.Template("""\
// Copyright 2018 The Chromium Authors
@ -326,7 +412,7 @@ ${METHODS}
is_natives_class = not forwarding and (options.use_proxy_hash
or options.enable_jni_multiplexing)
class_name = jni_generator.ProxyHelpers.GetClass(is_natives_class,
module_name)
options.module_name)
package = jni_generator.ProxyHelpers.GetPackage(is_natives_class,
options.package_prefix)
@ -346,6 +432,7 @@ ${METHODS}
methods = registration_dict['FORWARDING_PROXY_METHODS']
else:
methods = registration_dict['PROXY_NATIVE_SIGNATURES']
methods += stub_methods
return template.substitute({
'CLASS_NAME': class_name,
@ -355,7 +442,7 @@ ${METHODS}
})
def CreateFromDict(options, module_name, registration_dict):
def CreateFromDict(options, registration_dict):
"""Returns the content of the header file."""
template = string.Template("""\
@ -389,7 +476,7 @@ ${FORWARDING_CALLS}
${MANUAL_REGISTRATION}
#endif // ${HEADER_GUARD}
""")
_SetProxyRegistrationFields(options, module_name, registration_dict)
_SetProxyRegistrationFields(options, registration_dict)
if not options.enable_jni_multiplexing:
registration_dict['FORWARDING_CALLS'] = ''
if len(registration_dict['FORWARD_DECLARATIONS']) == 0:
@ -419,10 +506,10 @@ def _GetJavaToNativeParamsList(params_list):
class DictionaryGenerator(object):
"""Generates an inline header file for JNI registration."""
def __init__(self, options, module_name, content_namespace,
def __init__(self, options, file_path, content_namespace,
fully_qualified_class, natives, jni_params):
self.options = options
self.module_name = module_name
self.file_path = file_path
self.content_namespace = content_namespace
self.natives = natives
self.proxy_natives = [n for n in natives if n.is_proxy]
@ -432,7 +519,7 @@ class DictionaryGenerator(object):
self.class_name = self.fully_qualified_class.split('/')[-1]
self.helper = jni_generator.HeaderFileGeneratorHelper(
self.class_name,
self.module_name,
options.module_name,
fully_qualified_class,
options.use_proxy_hash,
options.package_prefix,
@ -442,7 +529,7 @@ class DictionaryGenerator(object):
def Generate(self):
self.registration_dict = {
'FULL_CLASS_NAME': self.fully_qualified_class,
'MODULE_NAME': self.module_name
'FILE_PATH': self.file_path,
}
self._AddClassPathDeclarations()
self._AddForwardDeclaration()
@ -461,7 +548,7 @@ class DictionaryGenerator(object):
if self.options.use_proxy_hash or self.options.enable_jni_multiplexing:
self.registration_dict['FORWARDING_PROXY_METHODS'] = ('\n'.join(
_MakeForwardingProxy(self.options, self.module_name, native)
_MakeForwardingProxy(self.options, native)
for native in self.proxy_natives))
return self.registration_dict
@ -554,7 +641,7 @@ ${KMETHODS}
return_type, params_list = native.return_and_signature
class_name = jni_generator.EscapeClassName(
jni_generator.ProxyHelpers.GetQualifiedClass(
True, self.module_name, self.options.package_prefix))
True, self.options.module_name, self.options.package_prefix))
proxy_signature = jni_generator.EscapeClassName(
_GetMultiplexProxyName(return_type, params_list))
@ -592,7 +679,7 @@ ${KMETHODS}
for clazz, full_clazz in all_classes.items():
if clazz == jni_generator.ProxyHelpers.GetClass(
self.options.use_proxy_hash or self.options.enable_jni_multiplexing,
self.module_name):
self.options.module_name):
continue
kmethods = self._GetKMethodsString(clazz)
@ -744,7 +831,7 @@ def _GetMultiplexProxyName(return_type, params_list):
return 'resolve_for_' + return_type.replace('[]', '_array').lower() + params
def _MakeForwardingProxy(options, module_name, proxy_native):
def _MakeForwardingProxy(options, proxy_native):
template = string.Template("""
public static ${RETURN_TYPE} ${METHOD_NAME}(${PARAMS_WITH_TYPES}) {
${MAYBE_RETURN}${PROXY_CLASS}.${PROXY_METHOD_NAME}(${PARAM_NAMES});
@ -754,7 +841,7 @@ def _MakeForwardingProxy(options, module_name, proxy_native):
'%s %s' % (p.datatype, p.name) for p in proxy_native.params)
param_names = ', '.join(p.name for p in proxy_native.params)
proxy_class = jni_generator.ProxyHelpers.GetQualifiedClass(
True, module_name, options.package_prefix)
True, options.module_name, options.package_prefix)
if options.enable_jni_multiplexing:
if not param_names:
@ -824,16 +911,43 @@ def _MakeProxySignature(options, proxy_native):
})
def _GetFilesSetFromSources(sources_files, file_exclusions):
java_file_paths = set()
for f in sources_files:
# Skip generated files (ones starting with ..), since the GN targets do not
# declare any deps, so they may not be built at the time of this script
# running. Thus, we don't support JNI from generated files. Also skip Kotlin
# files as they are not supported by JNI generation.
java_file_paths.update(p for p in build_utils.ReadSourcesList(f)
if p.startswith('..') and p not in file_exclusions
and not p.endswith('.kt'))
return java_file_paths
def main(argv):
arg_parser = argparse.ArgumentParser()
action_helpers.add_depfile_arg(arg_parser)
arg_parser.add_argument('--native-sources-file',
help='A file which contains Java file paths, derived '
'from native deps onto generate_jni.')
arg_parser.add_argument('--java-sources-files',
required=True,
action='append',
help='A list of .sources files which contain Java '
'file paths, derived from our Java dependencies.')
arg_parser.add_argument(
'--sources-files',
required=True,
action='append',
help='A list of .sources files which contain Java '
'file paths.')
'--add-stubs-for-missing-native',
action='store_true',
help='Adds stub methods for any --java-sources-files which are missing '
'from --native-sources-files. If not passed, we will assert that none of '
'these exist.')
arg_parser.add_argument(
'--remove-uncalled-methods',
action='store_true',
help='Removes --native-sources-files which are not in '
'--java-sources-files. If not passed, we will assert that none of these '
'exist.')
arg_parser.add_argument(
'--header-path', help='Path to output header file (optional).')
arg_parser.add_argument(
@ -898,20 +1012,27 @@ def main(argv):
'Invalid arguments: --manual-jni-registration without --header-path. '
'Cannot manually register JNI if there is no output header file.')
sources_files = sorted(set(action_helpers.parse_gn_list(args.sources_files)))
java_sources_files = sorted(
set(action_helpers.parse_gn_list(args.java_sources_files)))
java_sources = _GetFilesSetFromSources(java_sources_files,
args.file_exclusions)
if args.native_sources_file:
native_sources = _GetFilesSetFromSources([args.native_sources_file],
args.file_exclusions)
else:
assert not args.add_stubs_for_missing_native
assert not args.remove_uncalled_methods
# Just treating it like we have perfect alignment between native and java
# when only looking at java.
native_sources = java_sources
java_file_paths = []
for f in sources_files:
# Skip generated files, since the GN targets do not declare any deps. Also
# skip Kotlin files as they are not supported by JNI generation.
java_file_paths.extend(
p for p in build_utils.ReadSourcesList(f) if p.startswith('..')
and p not in args.file_exclusions and not p.endswith('.kt'))
_Generate(args, java_file_paths)
_Generate(args, native_sources, java_sources=java_sources)
if args.depfile:
action_helpers.write_depfile(args.depfile, args.srcjar_path,
sources_files + java_file_paths)
all_inputs = java_sources_files + list(native_sources) + list(java_sources)
if args.native_sources_file:
all_inputs.append(args.native_sources_file)
action_helpers.write_depfile(args.depfile, args.srcjar_path, all_inputs)
if __name__ == '__main__':

@ -4261,6 +4261,20 @@ if (enable_java_templates) {
}
}
}
template("jni_sources_list") {
generated_file(target_name) {
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ])
outputs = [ invoker.output ]
data_keys = [ "jni_source_files" ]
rebase = root_build_dir
metadata = {
# This target is just collecting source files used - this is not a
# legitimate dependency.
shared_libraries_barrier = []
}
}
}
}
# Create a zip archive corresponding to an application bundle module.

@ -0,0 +1,110 @@
# Copyright 2023 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")
import("//build/partitioned_shared_library.gni")
# This is a wrapper around an underlying native target which inserts JNI
# registration.
#
# The registration is based on the closure of the native target's generate_jni
# transitive dependencies. Additionally, we use provided java_targets to assert
# that our native and Java sides line up.
#
# In order to depend on the JNI registration, use
# <native-target-name>__jni_registration.
template("_native_with_jni") {
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
_jni_registration_name = "${target_name}__jni_registration"
# DFMs only ever need to be defined in the default toolchain, since we never
# do cross-toolchain deps with DFMs.
_use_all_toolchains = !defined(invoker.module_name)
if (_use_all_toolchains || current_toolchain == default_toolchain) {
generate_jni_registration(_jni_registration_name) {
native_deps = invoker.deps
if (allow_jni_multiplexing) {
enable_jni_multiplexing = true
}
if (defined(invoker.testonly) && invoker.testonly) {
enable_native_mocks = true
add_stubs_for_missing_jni = true
remove_uncalled_jni = true
}
forward_variables_from(invoker,
[
"add_stubs_for_missing_jni",
"java_targets",
"manual_jni_registration",
"module_name",
"namespace",
"remove_uncalled_jni",
])
}
} else {
not_needed(invoker,
[
"add_stubs_for_missing_jni",
"java_targets",
"manual_jni_registration",
"module_name",
"namespace",
"remove_uncalled_jni",
])
}
target(invoker.target_type, target_name) {
deps = invoker.deps
_need_native_dep =
(defined(invoker.manual_jni_registration) &&
invoker.manual_jni_registration) || allow_jni_multiplexing
if (_need_native_dep) {
_jni_registration_dep = ":$_jni_registration_name"
if (!_use_all_toolchains) {
_jni_registration_dep += "($default_toolchain)"
}
deps += [ _jni_registration_dep ]
}
forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY + [ "deps" ])
}
}
# native_with_jni for shared libraries - see _native_with_jni for details.
template("shared_library_with_jni") {
_native_with_jni(target_name) {
forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
target_type = "shared_library"
}
}
set_defaults("shared_library_with_jni") {
configs = default_shared_library_configs
}
# native_with_jni for partitioned shared libraries - see _native_with_jni for
# details.
template("partitioned_shared_library_with_jni") {
_native_with_jni(target_name) {
forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
target_type = "partitioned_shared_library"
}
}
set_defaults("partitioned_shared_library_with_jni") {
configs = default_shared_library_configs
}
# native_with_jni for components - see _native_with_jni for details.
template("component_with_jni") {
_native_with_jni(target_name) {
forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
target_type = "component"
}
}
set_defaults("component_with_jni") {
configs = default_component_configs
}

@ -162,6 +162,7 @@ if (enable_java_templates) {
forward_variables_from(invoker,
TESTONLY_AND_VISIBILITY + [
"deps",
"metadata",
"public_deps",
])
if (!defined(public_deps)) {
@ -303,6 +304,9 @@ if (enable_java_templates) {
generate_jni_impl(target_name) {
forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
metadata = {
jni_source_files = sources
}
}
}
@ -366,9 +370,6 @@ if (enable_java_templates && is_android) {
# 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") {
@ -379,6 +380,16 @@ if (enable_java_templates && is_android) {
# ]
# }
template("generate_jni_registration") {
if (defined(invoker.native_deps)) {
_jni_sources_list = "$target_gen_dir/$target_name.jnisources"
_jni_sources_target = "${target_name}__jni_sources"
jni_sources_list(_jni_sources_target) {
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
deps = invoker.native_deps
output = _jni_sources_list
}
}
action_with_pydeps(target_name) {
forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
@ -395,7 +406,16 @@ if (enable_java_templates && is_android) {
"--depfile",
rebase_path(depfile, root_build_dir),
]
foreach(_target, invoker.targets) {
if (defined(_jni_sources_target)) {
inputs += [ _jni_sources_list ]
deps += [ ":$_jni_sources_target" ]
args += [
"--native-sources-file",
rebase_path(_jni_sources_list, root_build_dir),
]
}
foreach(_target, invoker.java_targets) {
deps += [ "${_target}$build_config_target_suffix($default_toolchain)" ]
_build_config =
get_label_info("${_target}($default_toolchain)", "target_gen_dir") +
@ -404,15 +424,12 @@ if (enable_java_templates && is_android) {
_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:target_sources_file)" ]
} else {
args += [
# This is a list of .sources files.
"--sources-files=@FileArg($_rebased_build_config:deps_info:jni_all_source)",
]
}
args += [
# This is a list of .sources files.
"--java-sources-files=@FileArg($_rebased_build_config:deps_info:jni_all_source)",
]
}
if (defined(invoker.include_testonly)) {
_include_testonly = invoker.include_testonly
} else {
@ -435,6 +452,14 @@ if (enable_java_templates && is_android) {
}
}
if (defined(invoker.remove_uncalled_jni) && invoker.remove_uncalled_jni) {
args += [ "--remove-uncalled-methods" ]
}
if (defined(invoker.add_stubs_for_missing_jni) &&
invoker.add_stubs_for_missing_jni) {
args += [ "--add-stubs-for-missing-native" ]
}
_manual_jni_registration = defined(invoker.manual_jni_registration) &&
invoker.manual_jni_registration
_enable_jni_multiplexing = defined(invoker.enable_jni_multiplexing) &&
@ -446,12 +471,7 @@ if (enable_java_templates && is_android) {
args += [ "--enable-jni-multiplexing" ]
}
if ((!defined(invoker.prevent_header_output) ||
!invoker.prevent_header_output) &&
(_manual_jni_registration || _enable_jni_multiplexing)) {
assert(current_toolchain == default_toolchain,
"We do not need >1 toolchain copies of the same header.")
if (_manual_jni_registration || _enable_jni_multiplexing) {
_subdir = rebase_path(target_gen_dir, root_gen_dir)
_jni_header_output =
"$jni_headers_dir/$_subdir/${target_name}_generated.h"
@ -1553,10 +1573,11 @@ if (enable_java_templates && is_android) {
if (_generate_final_jni) {
_jni_srcjar_target_name = "${target_name}__final_jni"
_outer_target_name = target_name
generate_jni_registration(_jni_srcjar_target_name) {
enable_native_mocks = true
require_native_mocks = !defined(invoker.shared_libraries)
targets = [ ":$_outer_target_name" ]
java_targets = [ ":$_outer_target_name" ]
}
if (defined(invoker.shared_libraries)) {
@ -1977,8 +1998,6 @@ if (enable_java_templates && is_android) {
# direct_deps_only: Do not recurse on deps (optional, defaults false).
# jar_excluded_patterns: List of globs for paths to exclude (optional).
# jar_included_patterns: List of globs for paths to include (optional).
# generate_final_jni: If defined an true, generate the final
# `GEN_JNI.java` and include it in the output `.aar` (optional)
#
# Example
# dist_aar("my_aar") {
@ -1993,24 +2012,6 @@ if (enable_java_templates && is_android) {
_deps = []
_generate_final_jni =
defined(invoker.generate_final_jni) && invoker.generate_final_jni
if (_generate_final_jni) {
_outer_target_name = target_name
_jni_srcjar_target = "${target_name}__final_jni"
generate_jni_registration(_jni_srcjar_target) {
targets = [ ":$_outer_target_name" ]
}
_jni_java_target = "${target_name}__final_jni_java"
java_library_impl(_jni_java_target) {
type = "java_library"
supports_android = true
requires_android = true
srcjar_deps = [ ":$_jni_srcjar_target" ]
}
_deps += [ ":$_jni_java_target" ]
}
if (defined(invoker.deps)) {
_deps += invoker.deps
}
@ -2377,14 +2378,10 @@ if (enable_java_templates && is_android) {
# 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.
# generate_native_libraries_java: If defined, whether NativeLibraries.java is
# generated is solely controlled by this flag. Otherwise, the default behavior
# is NativeLibraries.java will only be generated for the base module/apk when
# its `shared_libraries` is not empty.
# jni_file_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
@ -2434,9 +2431,6 @@ if (enable_java_templates && is_android) {
# 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
@ -2543,9 +2537,27 @@ if (enable_java_templates && is_android) {
_non_java_deps = filter_exclude(_invoker_deps, java_target_patterns)
_java_assetres_deps = [ ":${_java_target_name}__assetres" ]
_generate_buildconfig_java = !defined(invoker.apk_under_test) && !_omit_dex
if (defined(invoker.generate_buildconfig_java)) {
_generate_buildconfig_java = invoker.generate_buildconfig_java
}
_srcjar_deps = []
_generate_final_jni = _generate_buildconfig_java
if (defined(invoker.generate_final_jni)) {
_generate_final_jni = invoker.generate_final_jni
}
if (defined(invoker.srcjar_deps)) {
_srcjar_deps = invoker.srcjar_deps
# TODO(smaier) This is a temporary hack that we can remove as soon as
# we migrate all repos onto the 1 registration per .so paradigm.
foreach(_srcjar_dep, _srcjar_deps) {
if (string_replace(_srcjar_dep, "jni_registration", "") !=
_srcjar_dep) {
_generate_final_jni = false
}
}
}
_use_chromium_linker =
@ -2604,19 +2616,11 @@ if (enable_java_templates && is_android) {
_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) && !_omit_dex
if (defined(invoker.generate_buildconfig_java)) {
_generate_buildconfig_java = invoker.generate_buildconfig_java
}
_generate_productconfig_java =
defined(invoker.product_config_java_packages) && !_omit_dex
# 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
}
# TODO(smaier) - there were some remaining usages of this in angle. Once they are removed, remove this line.
not_needed(invoker, [ "generate_final_jni" ])
_proguard_enabled =
defined(invoker.proguard_enabled) && invoker.proguard_enabled
@ -3017,27 +3021,18 @@ if (enable_java_templates && is_android) {
}
}
# TODO(smaier) remove this once the other repo have removed all usages of this.
if (_generate_final_jni) {
generate_jni_registration("${_template_name}__final_jni") {
forward_variables_from(invoker,
[
"enable_jni_multiplexing",
"enable_native_mocks",
"require_native_mocks",
])
if (defined(invoker.bundle_target)) {
targets = [ invoker.bundle_target ]
java_targets = [ invoker.bundle_target ]
} else {
targets = [ ":$_template_name" ]
java_targets = [ ":$_template_name" ]
}
if (defined(invoker.jni_file_exclusions)) {
file_exclusions = invoker.jni_file_exclusions
}
prevent_header_output = true
}
_srcjar_deps += [ ":${_template_name}__final_jni" ]
} else {
not_needed(invoker, [ "enable_native_mocks" ])
not_needed(invoker, [ "bundle_target" ])
}
if (_is_bundle_module) {
@ -3580,6 +3575,7 @@ if (enable_java_templates && is_android) {
[
"aapt_locale_allowlist",
"additional_jar_files",
"allow_unused_jni_from_native",
"alternative_android_sdk_dep",
"android_manifest",
"android_manifest_dep",
@ -3600,7 +3596,6 @@ if (enable_java_templates && is_android) {
"enable_lint",
"enable_jni_multiplexing",
"enable_multidex",
"enable_native_mocks",
"enable_proguard_checks",
"enforce_resource_overlays_in_tests",
"expected_android_manifest",
@ -3616,7 +3611,7 @@ if (enable_java_templates && is_android) {
"input_jars_paths",
"jacoco_never_instrument",
"javac_args",
"jni_file_exclusions",
"jni_registrations",
"keystore_name",
"keystore_password",
"keystore_path",
@ -3693,8 +3688,6 @@ if (enable_java_templates && is_android) {
# 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
@ -3706,7 +3699,6 @@ if (enable_java_templates && is_android) {
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))
}
# android_app_bundle's write_build_config expects module targets to be named
@ -3733,6 +3725,7 @@ if (enable_java_templates && is_android) {
"add_view_trace_events",
"aapt_locale_allowlist",
"additional_jar_files",
"allow_unused_jni_from_native",
"alternative_android_sdk_dep",
"android_manifest",
"android_manifest_dep",
@ -3762,7 +3755,7 @@ if (enable_java_templates && is_android) {
"jacoco_never_instrument",
"jar_excluded_patterns",
"javac_args",
"jni_file_exclusions",
"jni_registrations",
"loadable_modules",
"product_config_java_packages",
"main_component_library",
@ -4030,8 +4023,6 @@ if (enable_java_templates && is_android) {
}
if (defined(invoker.apk_under_test)) {
data_deps += [ invoker.apk_under_test ]
} else {
enable_native_mocks = true
}
if (defined(invoker.apk_under_test)) {
@ -4181,7 +4172,6 @@ if (enable_java_templates && is_android) {
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.

@ -60,6 +60,11 @@ if (current_toolchain == default_toolchain) {
template("chrome_public_bundle") {
_is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
if (_is_monochrome) {
_module_descs = monochrome_module_descs
} else {
_module_descs = chrome_module_descs
}
_base_module_target_name = "${invoker.target_name}__base_bundle_module"
chrome_public_apk_or_module_tmpl(_base_module_target_name) {
@ -76,7 +81,13 @@ if (current_toolchain == default_toolchain) {
"resource_ids_provider_dep",
])
target_type = "android_app_bundle_module"
bundle_target = ":${invoker.target_name}"
srcjar_deps = []
foreach(_module_desc, _module_descs) {
if (defined(_module_desc.jni_registration)) {
srcjar_deps += [ _module_desc.jni_registration ]
}
}
if (defined(invoker.expected_android_manifest_template)) {
expected_android_manifest =
@ -108,11 +119,7 @@ if (current_toolchain == default_toolchain) {
])
base_module_target = ":$_base_module_target_name"
manifest_package = chrome_public_manifest_package
if (_is_monochrome) {
module_descs = monochrome_module_descs
} else {
module_descs = chrome_module_descs
}
module_descs = _module_descs
chrome_deps = [ ":delegate_public_impl_java" ]
}
}
@ -3500,6 +3507,7 @@ template("libchrome_impl") {
deps += [ "//chrome/browser/android/vr:module_factory" ]
}
java_targets = [ "//chrome/android:chrome_public_apk" ]
forward_variables_from(invoker, "*", [ "deps" ])
}
}
@ -3549,9 +3557,6 @@ chrome_common_shared_library("libchromefortest") {
if (enable_vr) {
deps += [ "//chrome/browser/android/vr:test_support" ]
}
if (allow_jni_multiplexing) {
enable_jni_multiplexing = true
}
# Make this a partitioned library, since some partitioned code is linked in
# (otherwise, the library will warn at build time that it contains multiple
@ -3559,6 +3564,19 @@ chrome_common_shared_library("libchromefortest") {
# required or packaged into the APK. This can be removed if LLD starts
# supporting a "no partitions" argument (https://crbug.com/1021108).
module_descs = []
java_targets = [
"//chrome/android:chrome_public_unit_test_apk__test_apk",
"//chrome/android:chrome_public_test_apk__test_apk",
"//chrome/test/android:chrome_java_test_pagecontroller_tests__test_apk",
"//chrome/test/android:chrome_java_test_wpr_tests__test_apk",
"//chrome/test/android:chrome_java_test_feed_test__test_apk",
"//chrome/test/android:chrome_webapk_integration_tests__test_apk",
"//chrome/test/android:chrome_java_test_pagecontroller_codelab__test_apk",
]
if (enable_vr) {
java_targets += [ "//chrome/android:chrome_public_test_vr_apk__test_apk" ]
}
}
# Monochrome equivalent of Chrome's APK or bundle library template.
@ -3583,6 +3601,11 @@ template("libmonochrome_apk_or_bundle_tmpl") {
if (allow_jni_multiplexing) {
enable_jni_multiplexing = true
}
if (android_64bit_target_cpu) {
java_targets = [ "//chrome/android:monochrome_64_public_bundle" ]
} else {
java_targets = [ "//chrome/android:monochrome_public_bundle" ]
}
if (enable_vr) {
deps += [ "//chrome/browser/android/vr:module_factory" ]

@ -6,10 +6,10 @@ import("//base/android/linker/config.gni")
import("//build/config/android/config.gni")
import("//build/config/android/create_unwind_table.gni")
import("//build/config/android/extract_unwind_tables.gni")
import("//build/config/android/jni.gni")
import("//build/config/android/linker_version_script.gni")
import("//build/config/chrome_build.gni")
import("//build/config/compiler/compiler.gni")
import("//build/partitioned_shared_library.gni")
import("//chrome/android/modules/buildflags.gni")
import("//device/vr/buildflags/buildflags.gni")
@ -72,9 +72,9 @@ template("chrome_common_shared_library") {
}
if (_generate_partitions) {
_target_type = "partitioned_shared_library"
_target_type = "partitioned_shared_library_with_jni"
} else {
_target_type = "shared_library"
_target_type = "shared_library_with_jni"
}
target(_target_type, target_name) {
@ -83,6 +83,10 @@ template("chrome_common_shared_library") {
"*",
TESTONLY_AND_VISIBILITY + [ "define_unwind_table_target" ])
if (!defined(deps)) {
deps = []
}
if (!_is_webview) {
deps += [ "//chrome:chrome_android_core" ]
}
@ -119,9 +123,6 @@ template("chrome_common_shared_library") {
sources += [ "../browser/android/vr/register_jni_monochrome.cc" ]
}
# We check this variable last, so sometimes it isn't used to decide which registration to use.
not_needed([ "enable_jni_multiplexing" ])
if (_generate_partitions) {
partitions = []
foreach(_module_desc, _module_descs) {

@ -551,32 +551,48 @@ template("chrome_common_apk_or_module_tmpl") {
shared_libraries += invoker.shared_libraries
} else if (_is_test) {
shared_libraries += [ "//chrome/android:libchromefortest" ]
} else if (_is_monochrome) {
srcjar_deps = [ "//chrome/android:libchromefortest__jni_registration($default_toolchain)" ]
} else if (_is_monochrome || _is_trichrome) {
# We are only doing the jni_registrations for Trichrome - the actual
# native libraries will end up in the Trichrome library.
if (android_64bit_target_cpu) {
# Build //android_webview:monochrome with the opposite bitness that
# Chrome runs in.
if (_is_64_bit_browser) {
shared_libraries += [ "//chrome/android:libmonochrome_64" ]
if (_include_32_bit_webview) {
secondary_abi_shared_libraries += [ "//android_webview:monochrome_64($android_secondary_abi_toolchain)" ]
}
if (build_hwasan_splits) {
shared_libraries +=
[ "//chrome/android:libmonochrome_64($_hwasan_toolchain)" ]
srcjar_deps = [ "//chrome/android:libmonochrome_64__jni_registration($default_toolchain)" ]
if (_is_monochrome) {
shared_libraries += [ "//chrome/android:libmonochrome_64" ]
if (_include_32_bit_webview) {
secondary_abi_shared_libraries += [ "//android_webview:monochrome_64($android_secondary_abi_toolchain)" ]
}
if (build_hwasan_splits) {
shared_libraries +=
[ "//chrome/android:libmonochrome_64($_hwasan_toolchain)" ]
}
}
} else {
if (_include_64_bit_webview) {
shared_libraries += [ "//android_webview:monochrome" ]
srcjar_deps = [ "//chrome/android:libmonochrome__jni_registration($android_secondary_abi_toolchain)" ]
if (_is_monochrome) {
if (_include_64_bit_webview) {
shared_libraries += [ "//android_webview:monochrome" ]
}
secondary_abi_shared_libraries += [ "//chrome/android:libmonochrome($android_secondary_abi_toolchain)" ]
}
secondary_abi_shared_libraries += [
"//chrome/android:libmonochrome($android_secondary_abi_toolchain)",
]
}
} else {
shared_libraries += [ "//chrome/android:libmonochrome" ]
srcjar_deps = [ "//chrome/android:libmonochrome__jni_registration($default_toolchain)" ]
if (_is_monochrome) {
shared_libraries += [ "//chrome/android:libmonochrome" ]
}
}
} else if (!_is_trichrome) {
shared_libraries += [ "//chrome/android:libchrome" ]
srcjar_deps =
[ "//chrome/android:libchrome__jni_registration($default_toolchain)" ]
}
if (defined(invoker.srcjar_deps)) {
srcjar_deps += invoker.srcjar_deps
}
if (enable_arcore) {
@ -725,6 +741,7 @@ template("chrome_common_apk_or_module_tmpl") {
"secondary_abi_loadable_modules",
"secondary_abi_shared_libraries",
"shared_libraries",
"srcjar_deps",
"version_code",
"version_name",
])

@ -4,6 +4,7 @@ cablev2_authenticator_module_desc = {
java_deps = [ "//chrome/android/modules/cablev2_authenticator/internal:java" ]
native_deps =
[ "//chrome/android/modules/cablev2_authenticator/internal:native" ]
jni_registration = "//chrome/android/modules/cablev2_authenticator/internal:cablev2_authenticator__jni_registration($default_toolchain)"
load_native_on_get_impl = true
uses_split = "chrome"
}

@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
import("//chrome/android/modules/buildflags.gni")
@ -22,10 +23,10 @@ group("native") {
deps = [ ":cablev2_authenticator" ]
}
component("cablev2_authenticator") {
component_with_jni("cablev2_authenticator") {
java_targets = [ ":java" ]
sources = [ "entrypoints.cc" ]
deps = [
":jni_registration($default_toolchain)",
"//base",
"//chrome/android/features/cablev2_authenticator:native",
]
@ -34,14 +35,7 @@ component("cablev2_authenticator") {
if (use_native_partitions) {
cflags = [ "-fsymbol-partition=cablev2_authenticator_partition" ]
}
}
if (current_toolchain == default_toolchain) {
generate_jni_registration("jni_registration") {
no_transitive_deps = true
targets = [ "//chrome/android/features/cablev2_authenticator:java" ]
manual_jni_registration = true
namespace = "cablev2_authenticator"
module_name = "cablev2_authenticator"
}
manual_jni_registration = true
namespace = "cablev2_authenticator"
module_name = "cablev2_authenticator"
}

@ -4,7 +4,7 @@
#include "base/android/jni_generator/jni_generator_helper.h"
#include "base/android/jni_utils.h"
#include "chrome/android/modules/cablev2_authenticator/internal/jni_registration_generated.h"
#include "chrome/android/modules/cablev2_authenticator/internal/cablev2_authenticator__jni_registration_generated.h"
extern "C" {
// This JNI registration method is found and called by module framework code.

@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
import("//chrome/android/modules/buildflags.gni")
@ -19,16 +20,6 @@ generate_jni("jni_headers") {
sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContentsImpl.java" ]
}
if (current_toolchain == default_toolchain) {
generate_jni_registration("jni_registration") {
targets = [ ":java" ]
manual_jni_registration = true
namespace = "stack_unwinder"
module_name = "stack_unwinder"
no_transitive_deps = true
}
}
# This group is effectively an alias representing the module's native code,
# allowing it to be named "native" for clarity in module descriptors. The
# component target must be named according to the feature, so that the component
@ -37,14 +28,14 @@ group("native") {
deps = [ ":stack_unwinder" ]
}
component("stack_unwinder") {
component_with_jni("stack_unwinder") {
java_targets = [ ":java" ]
sources = [
"entrypoints.cc",
"stack_unwinder_module_contents_impl.cc",
]
deps = [
":jni_headers",
":jni_registration($default_toolchain)",
"//base",
"//base:native_unwinder_android",
"//chrome/android/features/stack_unwinder/public:native",
@ -54,6 +45,9 @@ component("stack_unwinder") {
if (use_native_partitions) {
cflags = [ "-fsymbol-partition=stack_unwinder_partition" ]
}
manual_jni_registration = true
namespace = "stack_unwinder"
module_name = "stack_unwinder"
}
# Since loading of a partitioned library is not supported in an APK, a separate

@ -4,7 +4,7 @@
#include "base/android/jni_generator/jni_generator_helper.h"
#include "base/android/jni_utils.h"
#include "chrome/android/modules/stack_unwinder/internal/jni_registration_generated.h"
#include "chrome/android/modules/stack_unwinder/internal/stack_unwinder__jni_registration_generated.h"
extern "C" {
// This JNI registration method is found and called by module framework

@ -18,6 +18,7 @@ stack_unwinder_module_desc = {
android_manifest = "//chrome/android/modules/stack_unwinder/internal/java/AndroidManifest.xml"
java_deps = [ "//chrome/android/modules/stack_unwinder/internal:java" ]
native_deps = [ "//chrome/android/modules/stack_unwinder/internal:native" ]
jni_registration = "//chrome/android/modules/stack_unwinder/internal:stack_unwinder__jni_registration($default_toolchain)"
load_native_on_get_impl = false
include_unwind_assets = add_unwind_tables_in_chrome_32bit_apk
}

@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
import("//chrome/android/modules/buildflags.gni")
@ -22,10 +23,10 @@ group("native") {
deps = [ ":test_dummy" ]
}
component("test_dummy") {
component_with_jni("test_dummy") {
java_targets = [ ":java" ]
sources = [ "entrypoints.cc" ]
deps = [
":jni_registration($default_toolchain)",
"//base",
"//chrome/browser/test_dummy/internal:native",
]
@ -34,17 +35,7 @@ component("test_dummy") {
if (use_native_partitions) {
cflags = [ "-fsymbol-partition=test_dummy_partition" ]
}
}
if (current_toolchain == default_toolchain) {
generate_jni_registration("jni_registration") {
no_transitive_deps = true
targets = [ "//chrome/browser/test_dummy/internal:java" ]
manual_jni_registration = true
namespace = "test_dummy"
module_name = "test_dummy"
if (allow_jni_multiplexing) {
enable_jni_multiplexing = true
}
}
manual_jni_registration = true
namespace = "test_dummy"
module_name = "test_dummy"
}

@ -4,7 +4,7 @@
#include "base/android/jni_generator/jni_generator_helper.h"
#include "base/android/jni_utils.h"
#include "chrome/android/modules/test_dummy/internal/jni_registration_generated.h"
#include "chrome/android/modules/test_dummy/internal/test_dummy__jni_registration_generated.h"
extern "C" {
// This JNI registration method is found and called by module framework code.

@ -16,6 +16,7 @@ test_dummy_module_desc = {
"//chrome/android/modules/test_dummy/internal:native",
"//chrome/browser/test_dummy/internal:native",
]
jni_registration = "//chrome/android/modules/test_dummy/internal:test_dummy__jni_registration($default_toolchain)"
paks = [ "$root_gen_dir/chrome/test_dummy_resources.pak" ]
pak_deps = [ "//chrome/browser/test_dummy/internal:resources_native" ]
load_native_on_get_impl = true

@ -49,7 +49,7 @@ generate_jni("cronet_jni_headers") {
}
generate_jni_registration("cronet_jni_registration") {
targets = [ ":cronet_impl_native_base_java" ]
java_targets = [ ":cronet_impl_native_base_java" ]
manual_jni_registration = true
# JNI generated is used for test and non-test apks.
@ -1177,6 +1177,10 @@ instrumentation_test_apk("cronet_test_instrumentation_apk") {
"test/proguard.cfg",
]
}
srcjar_deps = [
":cronet_jni_registration",
":cronet_tests_jni_registration",
]
}
android_resources("cronet_smoketests_platform_only_apk_resources") {
@ -1219,6 +1223,10 @@ instrumentation_test_apk(
"test/proguard.cfg",
]
}
# There is no native in this apk. However, since we depend on //base, we
# need something that provides a GEN_JNI, as //base uses GEN_JNI.
srcjar_deps = [ ":cronet_jni_registration" ]
}
instrumentation_test_apk(
@ -1254,6 +1262,10 @@ instrumentation_test_apk(
"test/proguard.cfg",
]
}
# There is no native in this apk. However, since we depend on //base, we
# need something that provides a GEN_JNI, as //base uses GEN_JNI.
srcjar_deps = [ ":cronet_jni_registration" ]
}
android_apk("cronet_perf_test_apk") {
@ -1292,6 +1304,10 @@ android_apk("cronet_perf_test_apk") {
]
enable_proguard_checks = false
}
srcjar_deps = [
":cronet_jni_registration",
":cronet_tests_jni_registration",
]
}
test("cronet_unittests_android") {
@ -1376,7 +1392,7 @@ android_java_prebuilt("repackage_test_jars_without_jni_java") {
# ...then, generate the final, merged GEN_JNI class...
generate_jni_registration("cronet_tests_jni_registration") {
targets = _test_deps
java_targets = _test_deps
manual_jni_registration = true
testonly = true
module_name = "cronet_tests"

@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/android/config.gni")
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
import("//third_party/icu/config.gni")
@ -18,7 +19,7 @@ generate_jni("content_shell_jni_headers") {
]
}
shared_library("libcontent_shell_content_view") {
shared_library_with_jni("libcontent_shell_content_view") {
testonly = true
deps = [
":content_shell_jni_headers",
@ -41,9 +42,10 @@ shared_library("libcontent_shell_content_view") {
sources = [ "shell_library_loader.cc" ]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
java_targets = [ ":content_shell_apk" ]
}
shared_library("libcontent_native_test") {
shared_library_with_jni("libcontent_native_test") {
testonly = true
deps = [
"//base",
@ -56,6 +58,7 @@ shared_library("libcontent_native_test") {
sources = [ "shell_test_library_loader.cc" ]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
java_targets = [ ":content_shell_test_apk__test_apk" ]
}
android_resources("content_shell_java_resources") {
@ -212,6 +215,7 @@ content_shell_apk_tmpl("content_shell_apk") {
android_manifest = content_shell_manifest
android_manifest_dep = ":content_shell_manifest"
shared_libraries = [ ":libcontent_shell_content_view" ]
srcjar_deps = [ ":libcontent_shell_content_view__jni_registration" ]
command_line_flags_file = "content-shell-command-line"
}
@ -221,6 +225,7 @@ content_shell_apk_tmpl("content_shell_test_apk") {
android_manifest = content_shell_test_manifest
android_manifest_dep = ":content_shell_test_manifest"
shared_libraries = [ ":libcontent_native_test" ]
srcjar_deps = [ ":libcontent_native_test__jni_registration" ]
deps = [
"//base:base_java_test_support",
"//base:base_javatests",

@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
group("system") {
@ -136,7 +137,7 @@ android_library("mojo_javatests") {
data = [ "//mojo/public/interfaces/bindings/tests/data/validation/" ]
}
shared_library("mojo_java_unittests") {
shared_library_with_jni("mojo_java_unittests") {
testonly = true
sources = [
@ -158,6 +159,7 @@ shared_library("mojo_java_unittests") {
defines = [ "UNIT_TEST" ]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
java_targets = [ ":mojo_test_apk__test_apk" ]
}
instrumentation_test_apk("mojo_test_apk") {
@ -170,4 +172,5 @@ instrumentation_test_apk("mojo_test_apk") {
"//mojo/public/java:bindings_java",
]
shared_libraries = [ ":mojo_java_unittests" ]
srcjar_deps = [ ":mojo_java_unittests__jni_registration" ]
}

@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/android/config.gni")
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
android_library("net_java") {
@ -126,7 +127,7 @@ source_set("java_test_native_support") {
public_deps = [ "//net:net_test_jni_headers" ]
}
shared_library("net_java_test_native_support") {
shared_library_with_jni("net_java_test_native_support") {
testonly = true
deps = [
":java_test_native_support",
@ -135,6 +136,7 @@ shared_library("net_java_test_native_support") {
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
java_targets = [ ":net_test_support_apk" ]
}
android_apk("net_test_support_apk") {
@ -155,6 +157,7 @@ android_apk("net_test_support_apk") {
android_manifest = "../test/android/javatests/AndroidManifest.xml"
apk_name = "ChromiumNetTestSupport"
shared_libraries = [ ":net_java_test_native_support" ]
srcjar_deps = [ ":net_java_test_native_support__jni_registration" ]
}
android_resources("net_unittests_apk_resources") {

@ -37,6 +37,7 @@ if (is_android) {
import("//build/config/android/config.gni")
import("//build/config/android/create_unwind_table.gni")
import("//build/config/android/extract_unwind_tables.gni")
import("//build/config/android/jni.gni")
import("//build/config/android/rules.gni")
import("//build/config/sanitizers/sanitizers.gni")
} else if (is_fuchsia) {
@ -381,7 +382,8 @@ template("test") {
}
mixed_test(_library_target_name) {
target_type = "shared_library"
target_type = "shared_library_with_jni"
java_targets = [ ":$_apk_target_name" ]
# Configs will always be defined since we set_defaults in
# BUILDCONFIG.gn.
@ -423,6 +425,7 @@ template("test") {
unittest_apk(_apk_target_name) {
forward_variables_from(invoker, _apk_specific_vars)
shared_library = ":$_library_target_name"
srcjar_deps = [ "${shared_library}__jni_registration" ]
apk_name = invoker.target_name
if (defined(invoker.output_name)) {
apk_name = invoker.output_name