Commit 1cb1d038 authored by Christopher Grant's avatar Christopher Grant Committed by Commit Bot

Revert "Modules: Introduce a generic DFM native library loading system"

This reverts commit 7ca339e3.

Reason for revert: Broke test targets in some builds.
https://build.chromium.org/p/chromium.android/builders/Android%20arm64%20Builder%20%28dbg%29/builds/39819

Original change's description:
> Modules: Introduce a generic DFM native library loading system
> 
> DFMs that include both Java and native code will probably use JNI. This
> change introduces a reusable mechanism to load the native library and
> register its JNI methods.
> 
> Key points:
> 
> - There are 3 build variants supported:
>   1. Production builds with lld-generated partitions.
>   2. Component build (with feature code in a component).
>   3. Fallback release build (feature code in the main library)
> 
> - For consistency, explicit JNI registration is done in both
>   ChromeModern and Monochrome.
> 
> - The Test Dummy module is moved over to use this new system. VR will
>   join the fun in a follow-on change.
> 
> - Currently, modules must supply an explicit JNI registration method.
>   Common code will locate this method and call it, at the appropriate
>   time, on behalf of the module.
> 
> Bug: 870055
> Change-Id: Id400ff00b4be65f71536a4acffdfcf93cc3bea58
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1822846
> Commit-Queue: Christopher Grant <cjgrant@chromium.org>
> Reviewed-by: Tibor Goldschwendt <tiborg@chromium.org>
> Reviewed-by: Andrew Grieve <agrieve@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#700276}

TBR=cjgrant@chromium.org,agrieve@chromium.org,tiborg@chromium.org

Change-Id: Ia5f504c0da25c85805a8521991c6eed8eac15267
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 870055
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1827245Reviewed-by: default avatarChristopher Grant <cjgrant@chromium.org>
Commit-Queue: Christopher Grant <cjgrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700358}
parent e444fcaf
......@@ -62,6 +62,12 @@ bool BundleUtils::IsBundle() {
return Java_BundleUtils_isBundle(base::android::AttachCurrentThread());
}
// static
void* BundleUtils::DlOpenModuleLibrary(const std::string& library_name) {
std::string library_path = ResolveLibraryPath(library_name);
return dlopen(library_path.c_str(), RTLD_LOCAL);
}
// static
void* BundleUtils::DlOpenModuleLibraryPartition(
const std::string& library_name) {
......
......@@ -18,6 +18,9 @@ class BASE_EXPORT BundleUtils {
// Returns true if the current build is a bundle.
static bool IsBundle();
// dlopen wrapper that works for native libraries in dynamic feature modules.
static void* DlOpenModuleLibrary(const std::string& libary_name);
// dlopen wrapper that works for partitioned native libraries in dynamic
// feature modules. This routine looks up the partition's address space in a
// table of main library symbols, and uses it when loading the feature
......
......@@ -42,10 +42,6 @@ def main():
dest='whitelists',
help='Path to an input file containing a whitelist of extra symbols to '
'export, one symbol per line. Multiple files may be specified.')
parser.add_argument(
'--export-feature-registrations',
action='store_true',
help='Export JNI_OnLoad_* methods')
options = parser.parse_args()
# JNI_OnLoad is always exported.
......@@ -56,9 +52,6 @@ def main():
if options.export_java_symbols:
symbol_list.append('Java_*')
if options.export_feature_registrations:
symbol_list.append('JNI_OnLoad_*')
for whitelist in options.whitelists:
with open(whitelist, 'rt') as f:
for line in f:
......
......@@ -27,11 +27,6 @@ template("generate_linker_version_script") {
args += [ "--export-java-symbols" ]
}
if (defined(invoker.export_feature_registrations) &&
invoker.export_feature_registrations) {
args += [ "--export-feature-registrations" ]
}
if (defined(invoker.export_symbol_whitelist_files)) {
foreach(file_, invoker.export_symbol_whitelist_files) {
inputs += [ file_ ]
......
......@@ -1195,6 +1195,7 @@ chrome_common_shared_library("libchrome") {
if (enable_vr) {
deps += [ "//chrome/browser/android/vr:module_factory" ]
}
deps += [ "//chrome/android/features/test_dummy/internal:base_module_native" ]
allow_partitions = true
module_descs = chrome_modern_module_descs
......@@ -1211,6 +1212,7 @@ chrome_common_shared_library("libchromefortest") {
":chrome_jni_for_test_registration($default_toolchain)",
"//base/test:test_support",
"//chrome:chrome_android_core",
"//chrome/android/features/test_dummy/internal:base_module_native",
"//chrome/browser/android/metrics:ukm_utils_for_test",
"//components/autofill_assistant/browser:test_support",
"//components/crash/android:crash_android",
......@@ -1224,10 +1226,6 @@ chrome_common_shared_library("libchromefortest") {
if (enable_vr) {
deps += [ "//chrome/browser/android/vr:test_support" ]
}
# TODO(http://crbug.com/1008123): Include module native code by enumerating
# module descriptors.
deps += [ "//chrome/android/modules/test_dummy/internal:native" ]
}
# Ensure that .pak files are built only once (build them in the default
......@@ -1463,6 +1461,8 @@ template("libmonochrome_apk_or_bundle_tmpl") {
if (enable_vr) {
deps += [ "//chrome/browser/android/vr:module_factory" ]
}
deps +=
[ "//chrome/android/features/test_dummy/internal:base_module_native" ]
is_monochrome = true
allow_partitions = true
......
......@@ -40,9 +40,8 @@ template("chrome_common_shared_library") {
# Create a partitioned libraries if the build config supports it, and the
# invoker wants partitions.
_allow_partitions =
defined(invoker.allow_partitions) && invoker.allow_partitions
_generate_partitions = _allow_partitions && use_native_modules
_generate_partitions = defined(invoker.allow_partitions) &&
invoker.allow_partitions && use_native_modules
if (_generate_partitions) {
assert(defined(invoker.module_descs))
} else {
......@@ -56,7 +55,6 @@ template("chrome_common_shared_library") {
linker_script = _linker_script
export_java_symbols = _export_java_symbols
if (_generate_partitions) {
export_feature_registrations = true
export_symbol_whitelist_files = []
foreach(_module_desc, invoker.module_descs) {
if (defined(_module_desc.native_entrypoints)) {
......@@ -107,7 +105,7 @@ template("chrome_common_shared_library") {
}
}
if (_allow_partitions) {
if (_generate_partitions) {
partitions = []
foreach(_module_desc, invoker.module_descs) {
if (defined(_module_desc.native_deps)) {
......
......@@ -22,19 +22,16 @@ android_library("java") {
]
java_files =
[ "java/src/org/chromium/chrome/features/test_dummy/TestDummyImpl.java" ]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
deps += [ "//base:jni_java" ]
}
source_set("native") {
sources = [
"test_dummy_impl.cc",
"test_dummy.cc",
]
deps = [
":jni_headers",
"//base",
"//chrome/android/features/test_dummy/public:native",
]
}
......@@ -51,11 +48,33 @@ android_library("base_module_java") {
]
java_files = [
"java/src/org/chromium/chrome/features/test_dummy/TestDummyActivity.java",
"java/src/org/chromium/chrome/features/test_dummy/TestDummySupport.java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
deps += [ "//base:jni_java" ]
}
buildflag_header("buildflags") {
header = "buildflags.h"
flags = [ "USE_NATIVE_MODULES=$use_native_modules" ]
}
source_set("base_module_native") {
sources = [
"test_dummy_client.cc",
]
deps = [
":test_dummy_jni_headers",
"//base",
]
public_deps = [
":buildflags",
]
}
generate_jni("jni_headers") {
generate_jni("test_dummy_jni_headers") {
sources = [
"java/src/org/chromium/chrome/features/test_dummy/TestDummyImpl.java",
"java/src/org/chromium/chrome/features/test_dummy/TestDummySupport.java",
]
}
......@@ -11,7 +11,6 @@ import android.support.v7.app.AlertDialog;
import androidx.annotation.IntDef;
import org.chromium.base.Log;
import org.chromium.base.annotations.NativeMethods;
import java.io.IOException;
import java.io.InputStream;
......@@ -50,11 +49,6 @@ public class TestDummyImpl implements TestDummy {
}
}
@NativeMethods
interface Natives {
int execute();
}
private void showDoneDialog(Activity activity, @TestCase int testCase, boolean pass) {
String message = "Test Case %d: " + (pass ? "pass" : "fail");
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
......@@ -69,9 +63,8 @@ public class TestDummyImpl implements TestDummy {
}
private void executeNative(Activity activity) {
int value = TestDummyImplJni.get().execute();
boolean pass = (value == 123);
showDoneDialog(activity, TestCase.EXECUTE_NATIVE, pass);
boolean result = TestDummySupport.openAndVerifyNativeLibrary();
showDoneDialog(activity, TestCase.EXECUTE_NATIVE, result);
}
private void loadJavaResource(Activity activity) {
......
// Copyright 2019 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 org.chromium.chrome.features.test_dummy;
import org.chromium.base.annotations.NativeMethods;
/** Support class to proxy JNI calls from module Java to module native. */
//@MainDex
public class TestDummySupport {
/** JNI calls for exercising native parts of the DFM. */
@NativeMethods
public interface Natives {
boolean openAndVerifyNativeLibrary();
}
public static boolean openAndVerifyNativeLibrary() {
return TestDummySupportJni.get().openAndVerifyNativeLibrary();
}
}
......@@ -2,10 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/android/features/test_dummy/public/test_dummy.h"
#include "base/logging.h"
#include "chrome/android/features/test_dummy/internal/jni_headers/TestDummyImpl_jni.h"
static int JNI_TestDummyImpl_Execute(JNIEnv* env) {
LOG(INFO) << "Running test dummy native library";
namespace test_dummy {
int TestDummy() {
// Log something to utilize base library code. This is necessary to ensure
// that calls to base code are linked properly.
LOG(WARNING) << "Running test dummy native library.";
return 123;
}
} // namespace test_dummy
// Copyright 2019 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.
#include <android/dlext.h>
#include <dlfcn.h>
#include "base/android/bundle_utils.h"
#include "base/logging.h"
#include "chrome/android/features/test_dummy/internal/buildflags.h"
#include "chrome/android/features/test_dummy/internal/test_dummy_jni_headers/TestDummySupport_jni.h"
static jboolean JNI_TestDummySupport_OpenAndVerifyNativeLibrary(JNIEnv* env) {
#if BUILDFLAG(USE_NATIVE_MODULES)
// Note that the library opened here is not closed. dlclosing() libraries has
// proven to be problematic. See https://crbug.com/994029.
void* handle =
base::android::BundleUtils::DlOpenModuleLibraryPartition("test_dummy");
if (handle == nullptr) {
LOG(ERROR) << "Cannot open test library: " << dlerror();
return false;
}
void* symbol = dlsym(handle, "TestDummyEntrypoint");
if (symbol == nullptr) {
LOG(ERROR) << "Cannot find test library symbol";
return false;
}
typedef int TestFunction();
TestFunction* test_function = reinterpret_cast<TestFunction*>(symbol);
if (test_function() != 123) {
LOG(ERROR) << "Unexpected value from test library";
return false;
}
#endif
return true;
}
......@@ -8,3 +8,9 @@ android_library("java") {
java_files =
[ "java/src/org/chromium/chrome/features/test_dummy/TestDummy.java" ]
}
source_set("native") {
sources = [
"test_dummy.h",
]
}
// Copyright 2019 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.
#ifndef CHROME_ANDROID_FEATURES_TEST_DUMMY_PUBLIC_TEST_DUMMY_H_
#define CHROME_ANDROID_FEATURES_TEST_DUMMY_PUBLIC_TEST_DUMMY_H_
namespace test_dummy {
// The test_dummy feature's token native entrypoint.
int TestDummy();
} // namespace test_dummy
#endif // CHROME_ANDROID_FEATURES_TEST_DUMMY_PUBLIC_TEST_DUMMY_H_
......@@ -162,7 +162,6 @@ import org.chromium.chrome.browser.widget.textbubble.TextBubble;
import org.chromium.components.bookmarks.BookmarkId;
import org.chromium.components.feature_engagement.EventConstants;
import org.chromium.components.feature_engagement.Tracker;
import org.chromium.components.module_installer.Module;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.SelectionPopupController;
import org.chromium.content_public.browser.WebContents;
......@@ -1392,9 +1391,6 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
maybeRemoveWindowBackground();
DownloadManagerService.getDownloadManagerService().onActivityLaunched();
// TODO(https://crbug.com/1008162): Have the Module system register its own observer.
Module.doDeferredNativeRegistrations();
VrModuleProvider.maybeInit();
VrModuleProvider.getDelegate().onNativeLibraryAvailable();
ArDelegate arDelegate = ArDelegateProvider.getDelegate();
......
......@@ -65,8 +65,7 @@ template("chrome_feature_module") {
_loadable_modules_64_bit += _module_desc.loadable_modules_64_bit
}
if (use_native_modules && defined(_module_desc.native_deps) &&
_module_desc.native_deps != []) {
if (defined(_module_desc.native_deps) && _module_desc.native_deps != []) {
_arch = ""
_toolchain = ""
_root_out_dir = root_out_dir
......
......@@ -3,7 +3,6 @@
# found in the LICENSE file.
import("//build/config/android/rules.gni")
import("//chrome/android/modules/buildflags.gni")
android_library("java") {
java_files = [ "java/src/org/chromium/chrome/modules/test_dummy/TestDummyProviderImpl.java" ]
......@@ -15,66 +14,15 @@ android_library("java") {
]
}
# This group is effectively 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
# build's .cr.co library is named properly (ie. libtest_dummy.cr.so).
group("native") {
deps = [
":test_dummy",
]
}
component("test_dummy") {
source_set("native") {
sources = [
"entrypoints.cc",
]
deps = [
"//base",
"//chrome/android/features/test_dummy/internal:native",
"//chrome/android/features/test_dummy/public:native",
]
# Test dummy native entrypoints belong in the partition.
if (use_native_modules) {
cflags = [ "-fsymbol-partition=libtest_dummy.so" ]
}
if (current_toolchain != default_toolchain) {
deps += [ ":jni_registration_secondary($default_toolchain)" ]
} else {
deps += [ ":jni_registration($default_toolchain)" ]
}
}
# TODO(https://crbug.com/1008109): Adapt JNI registration to point at a Java
# target, instead of an APK/module target. This JNI registration target
# points at ChromeModern's module, but it's used by Monochrome as well, since
# both variants do explicit JNI registration in DFMs (for consistency).
#
# Alternatively, move to lazy JNI init for DFMs in Monochrome, by conditionally
# including a registration stub, as Chrome's base library does. That requires
# two sets of registration targets, so that the feature module template can
# selectively pull in the real version or a stub.
if (current_toolchain == default_toolchain) {
generate_jni_registration("jni_registration") {
target =
"//chrome/android:chrome_modern_public_bundle__test_dummy_bundle_module"
header_output = "$target_gen_dir/jni_registration.h"
namespace = "test_dummy"
}
# Note also: We cannot currently build JNI registration on secondary ABI
# toolchain (dependency issues). Therefore, for Monochrome's 32-bit library,
# we need to use the 64-bit side registration header that ChromeModern uses.
# However, it's in the 64-bit output directory. We need to also generate a copy
# for the 32-bit directory.
if (android_64bit_target_cpu) {
generate_jni_registration("jni_registration_secondary") {
target = "//chrome/android:chrome_modern_public_bundle__test_dummy_bundle_module"
header_output =
get_label_info(":native($android_secondary_abi_toolchain)",
"target_gen_dir") + "/jni_registration.h"
namespace = "test_dummy"
}
}
cflags = [ "-fsymbol-partition=libtest_dummy.so" ]
}
......@@ -2,21 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/jni_utils.h"
#include "chrome/android/modules/test_dummy/internal/jni_registration.h"
#include "chrome/android/features/test_dummy/public/test_dummy.h"
extern "C" {
// This JNI registration method is found and called by module framework code.
// Ideally, this code would be generated by the build.
__attribute__((visibility("default"))) bool JNI_OnLoad_test_dummy(JNIEnv* env) {
if (!base::android::IsSelectiveJniRegistrationEnabled(env) &&
!test_dummy::RegisterNonMainDexNatives(env)) {
return false;
}
if (!test_dummy::RegisterMainDexNatives(env)) {
return false;
}
return true;
__attribute__((visibility("default"))) int TestDummyEntrypoint() {
return test_dummy::TestDummy();
}
} // extern "C"
......@@ -13,8 +13,12 @@ test_dummy_module_desc = {
"//chrome/android/modules/test_dummy/internal:java",
]
native_deps = [
"//chrome/android/features/test_dummy/internal:native",
"//chrome/android/modules/test_dummy/internal:native",
]
if (use_native_modules) {
native_deps = [
"//chrome/android/features/test_dummy/internal:native",
"//chrome/android/modules/test_dummy/internal:native",
]
native_entrypoints =
"//chrome/android/modules/test_dummy/internal/entrypoints.lst"
}
}
......@@ -2911,7 +2911,6 @@ jumbo_split_static_library("browser") {
"//components/feed:feature_list",
"//components/invalidation/impl:feature_list",
"//components/language/android:language_bridge",
"//components/module_installer/android:native",
"//components/omnibox/browser",
"//components/page_load_metrics/browser",
"//components/payments/content/android",
......
......@@ -3,7 +3,6 @@
# found in the LICENSE file.
import("//build/config/android/rules.gni")
import("//chrome/android/modules/buildflags.gni")
android_library("module_installer_java") {
java_files = [
......@@ -23,7 +22,6 @@ android_library("module_installer_java") {
deps = [
"//base:base_java",
"//base:jni_java",
"//components/crash/android:java",
"//third_party/google_android_play_core:com_google_android_play_core_java",
]
......@@ -31,8 +29,6 @@ android_library("module_installer_java") {
srcjar_deps = [ ":module_installer_build_config" ]
jar_excluded_patterns = [ "*/ModuleInstallerConfig.class" ]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
android_library("module_installer_test_java") {
......@@ -98,29 +94,3 @@ java_cpp_template("module_installer_apk_build_config") {
]
defines = [ "IS_APK_BUILD" ]
}
source_set("native") {
sources = [
"module.cc",
]
deps = [
":jni_headers",
"//base",
]
# The method used to load and register JNI for native libraries depends
# heavily on build type.
if (use_native_modules) {
defines = [ "LOAD_FROM_PARTITIONS" ]
} else if (is_component_build) {
defines = [ "LOAD_FROM_COMPONENTS" ]
} else {
defines = [ "LOAD_FROM_BASE_LIBRARY" ]
}
}
generate_jni("jni_headers") {
sources = [
"java/src/org/chromium/components/module_installer/Module.java",
]
}
......@@ -6,8 +6,6 @@ package org.chromium.components.module_installer;
import org.chromium.base.StrictModeContext;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import java.util.HashSet;
import java.util.Set;
......@@ -19,12 +17,9 @@ import java.util.Set;
*
* @param <T> The interface of the module/
*/
@JNINamespace("module_installer")
public class Module<T> {
private static final Set<String> sInstantiatedModuleNames = new HashSet<>();
private static final Set<String> sModulesUninstalledForTesting = new HashSet<>();
private static final Set<String> sPendingNativeRegistrations = new HashSet<>();
private static boolean sNativeInitialized;
private final String mName;
private final Class<T> mInterfaceClass;
private final String mImplClassName;
......@@ -39,31 +34,13 @@ public class Module<T> {
sModulesUninstalledForTesting.add(moduleName);
}
@NativeMethods
interface Natives {
void loadNativeLibrary(String name);
}
/**
* To be called after the main native library has been loaded. Any module instances
* created before the native library is loaded have their native component queued
* for loading and registration. Calling this methed completes that process.
**/
public static void doDeferredNativeRegistrations() {
for (String name : sPendingNativeRegistrations) {
loadNativeLibrary(name);
}
sPendingNativeRegistrations.clear();
sNativeInitialized = true;
}
/**
* Instantiates a module.
*
* @param name The module's name as used with {@link ModuleInstaller}.
* @param interfaceClass {@link Class} object of the module interface.
* @param implClassName fully qualified class name of the implementation of the module's
* interface.
*interface.
**/
public Module(String name, Class<T> interfaceClass, String implClassName) {
mName = name;
......@@ -120,24 +97,8 @@ public class Module<T> {
| IllegalArgumentException e) {
throw new RuntimeException(e);
}
// Load the module's native library if there's one present, and the Chrome native
// library itself has been loaded.
if (sNativeInitialized) {
loadNativeLibrary(mName);
} else {
sPendingNativeRegistrations.add(mName);
}
}
return mImpl;
}
}
private static void loadNativeLibrary(String name) {
// TODO(https://crbug.com/870055): Whitelist modules, until each module explicitly indicates
// its need for library loading through this system.
if (!"test_dummy".equals(name)) return;
ModuleJni.get().loadNativeLibrary(name);
}
}
// Copyright 2019 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.
#include <dlfcn.h>
#include "base/android/bundle_utils.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "components/module_installer/android/jni_headers/Module_jni.h"
using base::android::BundleUtils;
#if defined(LOAD_FROM_BASE_LIBRARY)
extern "C" {
// These methods are forward-declared here for the build case where
// partitioned libraries are disabled, and module code is pulled into the main
// library. In that case, there is no current way of dlsym()'ing for this
// JNI registration method, and hence it's referred to directly.
// This list could be auto-generated in the future.
extern bool JNI_OnLoad_test_dummy(JNIEnv* env);
} // extern "C"
#endif // LOAD_FROM_BASE_LIBRARY
namespace module_installer {
typedef bool JniRegistrationFunction(JNIEnv* env);
static void JNI_Module_LoadNativeLibrary(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& jtext) {
std::string library_name;
base::android::ConvertJavaStringToUTF8(env, jtext, &library_name);
JniRegistrationFunction* registration_function = nullptr;
#if defined(LOAD_FROM_PARTITIONS) || defined(LOAD_FROM_COMPONENTS)
#if defined(LOAD_FROM_PARTITIONS)
// The partition library must be opened via native code (using
// android_dlopen_ext() under the hood). There is no need to repeat the
// operation on the Java side, because JNI registration is done explicitly
// (hence there is no reason for the Java ClassLoader to be aware of the
// library, for lazy JNI registration).
void* library_handle =
BundleUtils::DlOpenModuleLibraryPartition(library_name);
#else // defined(LOAD_FROM_PARTITIONS)
const std::string lib_name = "lib" + library_name + ".cr.so";
void* library_handle = dlopen(lib_name.c_str(), RTLD_LOCAL);
#endif // defined(LOAD_FROM_PARTITIONS)
CHECK(library_handle != nullptr)
<< "Could not open feature library:" << dlerror();
const std::string registration_name = "JNI_OnLoad_" + library_name;
// Find the module's JNI registration method from the feature library.
void* symbol = dlsym(library_handle, registration_name.c_str());
CHECK(symbol != nullptr) << "Could not find JNI registration method: "
<< dlerror();
registration_function = reinterpret_cast<JniRegistrationFunction*>(symbol);
#else // defined(LOAD_FROM_PARTITIONS) || defined(LOAD_FROM_COMPONENTS)
// TODO(https://crbug.com/870055): Similar to the declarations above, this map
// could be auto-generated.
const std::map<std::string, JniRegistrationFunction*> modules = {
{"test_dummy", JNI_OnLoad_test_dummy}};
registration_function = modules.at(library_name);
#endif // defined(LOAD_FROM_PARTITIONS) || defined(LOAD_FROM_COMPONENTS)
CHECK(registration_function(env))
<< "JNI registration failed: " << library_name;
}
} // namespace module_installer
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment