[Sampling profiler] Reland "Provide DFM function pointers through Java"

Replaces the manual loading of the dynamic feature module native library
with use of the Java DFM interfaces. Supplies the function pointers for
the native functionality esposed by the module via JNI.

This is a reland of 36645f496db0502f8437a5c9ce8502be7c333dd9 with the
changes to the native_libs_and_assets.expected files reverted.

TBR=agrieve@chromium.org

Bug: 1055945
Change-Id: I374611579cf42e7cb96f48d191c2f3edd5f6a996
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2190741
Reviewed-by: Mike Wittman <wittman@chromium.org>
Reviewed-by: Samuel Huang <huangs@chromium.org>
Commit-Queue: Mike Wittman <wittman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#766947}
diff --git a/chrome/android/modules/stack_unwinder/internal/BUILD.gn b/chrome/android/modules/stack_unwinder/internal/BUILD.gn
index 3d89b365..23ae81de 100644
--- a/chrome/android/modules/stack_unwinder/internal/BUILD.gn
+++ b/chrome/android/modules/stack_unwinder/internal/BUILD.gn
@@ -6,13 +6,26 @@
 import("//chrome/android/modules/buildflags.gni")
 
 android_library("java") {
-  sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyImpl.java" ]
+  sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContentsImpl.java" ]
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   deps = [
     "//base:base_java",
+    "//base:jni_java",
     "//chrome/android/modules/stack_unwinder/public:java",
   ]
 }
 
+generate_jni("jni_headers") {
+  sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContentsImpl.java" ]
+}
+
+generate_jni_registration("jni_registration") {
+  targets = [ ":java" ]
+  header_output = "$target_gen_dir/jni_registration.h"
+  namespace = "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
@@ -22,8 +35,13 @@
 }
 
 component("stack_unwinder") {
-  sources = [ "entrypoints.cc" ]
+  sources = [
+    "entrypoints.cc",
+    "stack_unwinder_module_contents_impl.cc",
+  ]
   deps = [
+    ":jni_headers",
+    ":jni_registration",
     "//base",
     "//chrome/android/features/stack_unwinder/public:memory_regions_map",
   ]
diff --git a/chrome/android/modules/stack_unwinder/internal/entrypoints.cc b/chrome/android/modules/stack_unwinder/internal/entrypoints.cc
index e9d4eddd..aaa6861 100644
--- a/chrome/android/modules/stack_unwinder/internal/entrypoints.cc
+++ b/chrome/android/modules/stack_unwinder/internal/entrypoints.cc
@@ -4,34 +4,19 @@
 
 #include "base/android/jni_generator/jni_generator_helper.h"
 #include "base/android/jni_utils.h"
-#include "base/profiler/unwinder.h"
-#include "chrome/android/features/stack_unwinder/public/memory_regions_map.h"
+#include "chrome/android/modules/stack_unwinder/internal/jni_registration.h"
 
 extern "C" {
 // This JNI registration method is found and called by module framework
-// code. Empty because we have no JNI items to register within the module code.
+// code.
 JNI_GENERATOR_EXPORT bool JNI_OnLoad_stack_unwinder(JNIEnv* env) {
+  if (!base::android::IsSelectiveJniRegistrationEnabled(env) &&
+      !stack_unwinder::RegisterNonMainDexNatives(env)) {
+    return false;
+  }
+  if (!stack_unwinder::RegisterMainDexNatives(env)) {
+    return false;
+  }
   return true;
 }
-
-// Native entry point functions.
-
-// Creates a new memory regions map. The caller takes ownership of the returned
-// object. We can't use std::unique_ptr here because this function has C
-// linkage.
-__attribute__((visibility("default"))) stack_unwinder::MemoryRegionsMap*
-CreateMemoryRegionsMap() {
-  // TODO(etiennep): Implement.
-  return nullptr;
-}
-
-// Creates a new native unwinder. The caller takes ownership of the returned
-// object. We can't use std::unique_ptr here because this function has C
-// linkage.
-__attribute__((visibility("default"))) base::Unwinder* CreateNativeUnwinder(
-    stack_unwinder::MemoryRegionsMap* memory_regions_map) {
-  // TODO(etiennep): Implement.
-  return nullptr;
-}
-
 }  // extern "C"
diff --git a/chrome/android/modules/stack_unwinder/internal/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyImpl.java b/chrome/android/modules/stack_unwinder/internal/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyImpl.java
deleted file mode 100644
index c372201..0000000
--- a/chrome/android/modules/stack_unwinder/internal/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyImpl.java
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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.modules.stack_unwinder;
-
-import org.chromium.base.annotations.UsedByReflection;
-
-/**
- * Provides the required Java implementation for the dynamic feature module, which is intended to
- * implement the module functionality. This class is empty since we access the module contents
- * strictly via native code.
- */
-@UsedByReflection("StackUnwinderModule")
-public class StackUnwinderDummyImpl implements StackUnwinderDummyInterface {}
diff --git a/chrome/android/modules/stack_unwinder/internal/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContentsImpl.java b/chrome/android/modules/stack_unwinder/internal/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContentsImpl.java
new file mode 100644
index 0000000..7da33eb5
--- /dev/null
+++ b/chrome/android/modules/stack_unwinder/internal/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContentsImpl.java
@@ -0,0 +1,40 @@
+// Copyright 2020 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.modules.stack_unwinder;
+
+import org.chromium.base.annotations.MainDex;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.base.annotations.UsedByReflection;
+
+/**
+ * Provides access to the stack unwinder native code functions within the dynamic feature module.
+ */
+@UsedByReflection("StackUnwinderModule")
+@MainDex
+public class StackUnwinderModuleContentsImpl implements StackUnwinderModuleContents {
+    /**
+     * Returns the pointer to the CreateMemoryRegionsMap native function within the module, encoded
+     * as a long.
+     */
+    @Override
+    public long getCreateMemoryRegionsMapFunction() {
+        return StackUnwinderModuleContentsImplJni.get().getCreateMemoryRegionsMapFunction();
+    }
+
+    /**
+     * Returns the pointer to the CreateNativeUnwinder native function within the module, encoded as
+     * a long.
+     */
+    @Override
+    public long getCreateNativeUnwinderFunction() {
+        return StackUnwinderModuleContentsImplJni.get().getCreateNativeUnwinderFunction();
+    }
+
+    @NativeMethods
+    interface Natives {
+        long getCreateMemoryRegionsMapFunction();
+        long getCreateNativeUnwinderFunction();
+    }
+}
diff --git a/chrome/android/modules/stack_unwinder/internal/stack_unwinder_module_contents_impl.cc b/chrome/android/modules/stack_unwinder/internal/stack_unwinder_module_contents_impl.cc
new file mode 100644
index 0000000..0175c3c
--- /dev/null
+++ b/chrome/android/modules/stack_unwinder/internal/stack_unwinder_module_contents_impl.cc
@@ -0,0 +1,32 @@
+// Copyright 2020 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 <memory>
+
+#include "base/profiler/unwinder.h"
+#include "chrome/android/features/stack_unwinder/public/memory_regions_map.h"
+#include "chrome/android/modules/stack_unwinder/internal/jni_headers/StackUnwinderModuleContentsImpl_jni.h"
+
+std::unique_ptr<stack_unwinder::MemoryRegionsMap> CreateMemoryRegionsMap() {
+  // TODO(etiennep): Implement.
+  return nullptr;
+}
+
+std::unique_ptr<base::Unwinder> CreateNativeUnwinder(
+    stack_unwinder::MemoryRegionsMap* memory_regions_map) {
+  // TODO(etiennep): Implement.
+  return nullptr;
+}
+
+static jlong
+JNI_StackUnwinderModuleContentsImpl_GetCreateMemoryRegionsMapFunction(
+    JNIEnv* env) {
+  return reinterpret_cast<jlong>(&CreateMemoryRegionsMap);
+}
+
+static jlong
+JNI_StackUnwinderModuleContentsImpl_GetCreateNativeUnwinderFunction(
+    JNIEnv* env) {
+  return reinterpret_cast<jlong>(&CreateNativeUnwinder);
+}
diff --git a/chrome/android/modules/stack_unwinder/provider/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleProvider.java b/chrome/android/modules/stack_unwinder/provider/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleProvider.java
index 35911296..044c145 100644
--- a/chrome/android/modules/stack_unwinder/provider/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleProvider.java
+++ b/chrome/android/modules/stack_unwinder/provider/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleProvider.java
@@ -23,4 +23,31 @@
     public static void installModule() {
         StackUnwinderModule.install((boolean success) -> {});
     }
+
+    /**
+     * Ensure the module's native contents are loaded and JNI is set up. Must be invoked after the
+     * module is installed and before using the functions below.
+     */
+    @CalledByNative
+    public static void ensureNativeLoaded() {
+        StackUnwinderModule.ensureNativeLoaded();
+    }
+
+    /**
+     * Returns the pointer to the CreateMemoryRegionsMap native function within the module, encoded
+     * as a long. Can be called only if the module is installed.
+     */
+    @CalledByNative
+    public static long getCreateMemoryRegionsMapFunction() {
+        return StackUnwinderModule.getImpl().getCreateMemoryRegionsMapFunction();
+    }
+
+    /**
+     * Returns the pointer to the CreateNativeUnwinder native function within the module, encoded as
+     * a long. Can be called only if the module is installed.
+     */
+    @CalledByNative
+    public static long getCreateNativeUnwinderFunction() {
+        return StackUnwinderModule.getImpl().getCreateNativeUnwinderFunction();
+    }
 }
diff --git a/chrome/android/modules/stack_unwinder/public/BUILD.gn b/chrome/android/modules/stack_unwinder/public/BUILD.gn
index 546491ba..0ea5726 100644
--- a/chrome/android/modules/stack_unwinder/public/BUILD.gn
+++ b/chrome/android/modules/stack_unwinder/public/BUILD.gn
@@ -5,7 +5,7 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyInterface.java" ]
+  sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContents.java" ]
   deps = [
     "//base:base_java",
     "//components/module_installer/android:module_installer_java",
diff --git a/chrome/android/modules/stack_unwinder/public/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyInterface.java b/chrome/android/modules/stack_unwinder/public/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyInterface.java
deleted file mode 100644
index f6b0f41..0000000
--- a/chrome/android/modules/stack_unwinder/public/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderDummyInterface.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.modules.stack_unwinder;
-
-import org.chromium.components.module_installer.builder.ModuleInterface;
-
-/**
- * Provides the required Java interface for the dynamic feature module, which is intended to
- * provide access the module functionality. We access the module contents strictly via native code
- * so don't use this interface.
- */
-@ModuleInterface(module = "stack_unwinder",
-        impl = "org.chromium.chrome.modules.stack_unwinder.StackUnwinderDummyImpl")
-public interface StackUnwinderDummyInterface {}
diff --git a/chrome/android/modules/stack_unwinder/public/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContents.java b/chrome/android/modules/stack_unwinder/public/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContents.java
new file mode 100644
index 0000000..d66d3209
--- /dev/null
+++ b/chrome/android/modules/stack_unwinder/public/java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleContents.java
@@ -0,0 +1,26 @@
+// Copyright 2020 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.modules.stack_unwinder;
+
+import org.chromium.components.module_installer.builder.ModuleInterface;
+
+/**
+ * Provides access to the stack unwinder native code functions within the dynamic feature module.
+ */
+@ModuleInterface(module = "stack_unwinder",
+        impl = "org.chromium.chrome.modules.stack_unwinder.StackUnwinderModuleContentsImpl")
+public interface StackUnwinderModuleContents {
+    /**
+     * Returns the pointer to the CreateMemoryRegionsMap native function within the module, encoded
+     * as a long.
+     */
+    long getCreateMemoryRegionsMapFunction();
+
+    /**
+     * Returns the pointer to the CreateNativeUnwinder native function within the module, encoded as
+     * a long.
+     */
+    long getCreateNativeUnwinderFunction();
+}
diff --git a/chrome/android/modules/stack_unwinder/public/module.cc b/chrome/android/modules/stack_unwinder/public/module.cc
index 55542f6..4c93aaf8 100644
--- a/chrome/android/modules/stack_unwinder/public/module.cc
+++ b/chrome/android/modules/stack_unwinder/public/module.cc
@@ -4,37 +4,12 @@
 
 #include "chrome/android/modules/stack_unwinder/public/module.h"
 
-#include <dlfcn.h>
-
-#include "base/android/bundle_utils.h"
 #include "base/android/jni_android.h"
 #include "base/memory/ptr_util.h"
-#include "base/strings/strcat.h"
 #include "chrome/android/modules/stack_unwinder/provider/jni_headers/StackUnwinderModuleProvider_jni.h"
 
 namespace stack_unwinder {
 
-namespace {
-
-void* TryLoadModule() {
-  const char* chrome_target_possibilities[] = {
-      "monochrome",
-      "chrome",
-  };
-
-  const char partition_name[] = "stack_unwinder_partition";
-  for (const char* target : chrome_target_possibilities) {
-    void* module = base::android::BundleUtils::DlOpenModuleLibraryPartition(
-        base::StrCat({target, "_", partition_name}), partition_name);
-    if (module)
-      return module;
-  }
-
-  return nullptr;
-}
-
-}  // namespace
-
 // static
 bool Module::IsInstalled() {
   JNIEnv* env = base::android::AttachCurrentThread();
@@ -48,37 +23,41 @@
 }
 
 // static
-std::unique_ptr<Module> Module::TryLoad() {
-  void* module = TryLoadModule();
-  if (!module)
-    return nullptr;
+std::unique_ptr<Module> Module::Load() {
+  CHECK(IsInstalled());
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_StackUnwinderModuleProvider_ensureNativeLoaded(env);
 
   CreateMemoryRegionsMapFunction create_memory_regions_map =
       reinterpret_cast<CreateMemoryRegionsMapFunction>(
-          dlsym(module, "CreateMemoryRegionsMap"));
-  CHECK(create_memory_regions_map);
+          Java_StackUnwinderModuleProvider_getCreateMemoryRegionsMapFunction(
+              env));
 
   CreateNativeUnwinderFunction create_native_unwinder =
       reinterpret_cast<CreateNativeUnwinderFunction>(
-          dlsym(module, "CreateNativeUnwinder"));
-  CHECK(create_native_unwinder);
+          Java_StackUnwinderModuleProvider_getCreateNativeUnwinderFunction(
+              env));
 
   return base::WrapUnique(
       new Module(create_memory_regions_map, create_native_unwinder));
 }
 
 std::unique_ptr<MemoryRegionsMap> Module::CreateMemoryRegionsMap() {
-  return base::WrapUnique(create_memory_regions_map_());
+  return create_memory_regions_map_();
 }
 
 std::unique_ptr<base::Unwinder> Module::CreateNativeUnwinder(
     MemoryRegionsMap* memory_regions_map) {
-  return base::WrapUnique(create_native_unwinder_(memory_regions_map));
+  return create_native_unwinder_(memory_regions_map);
 }
 
 Module::Module(CreateMemoryRegionsMapFunction create_memory_regions_map,
                CreateNativeUnwinderFunction create_native_unwinder)
     : create_memory_regions_map_(create_memory_regions_map),
-      create_native_unwinder_(create_native_unwinder) {}
+      create_native_unwinder_(create_native_unwinder) {
+  DCHECK(create_memory_regions_map);
+  DCHECK(create_native_unwinder);
+}
 
 }  // namespace stack_unwinder
diff --git a/chrome/android/modules/stack_unwinder/public/module.h b/chrome/android/modules/stack_unwinder/public/module.h
index 4f5650cc..038aeef 100644
--- a/chrome/android/modules/stack_unwinder/public/module.h
+++ b/chrome/android/modules/stack_unwinder/public/module.h
@@ -25,8 +25,8 @@
   // module is already installed.
   static void RequestInstallation();
 
-  // Attempts to load the module. Returns non-null if IsInstalled().
-  static std::unique_ptr<Module> TryLoad();
+  // Attempts to load the module. May be invoked only if IsInstalled().
+  static std::unique_ptr<Module> Load();
 
   // Returns a map representing the current memory regions (modules, stacks,
   // etc.).
@@ -37,8 +37,10 @@
       MemoryRegionsMap* memory_regions_map);
 
  private:
-  using CreateMemoryRegionsMapFunction = MemoryRegionsMap* (*)();
-  using CreateNativeUnwinderFunction = base::Unwinder* (*)(MemoryRegionsMap*);
+  using CreateMemoryRegionsMapFunction =
+      std::unique_ptr<MemoryRegionsMap> (*)();
+  using CreateNativeUnwinderFunction =
+      std::unique_ptr<base::Unwinder> (*)(MemoryRegionsMap*);
 
   Module(CreateMemoryRegionsMapFunction create_memory_regions_map,
          CreateNativeUnwinderFunction create_native_unwinder);