From f679891bd6a6b695cccadfa823a2af89809c4307 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Mon, 6 Sep 2021 05:40:48 -0700 Subject: [PATCH] Pass RuntimeScheduler to Binding Summary: changelog: [internal] Reviewed By: ShikaSD Differential Revision: D30487037 fbshipit-source-id: 3956606891a313577fd013ae5c2a9f1f90ac5903 --- .../facebook/react/ReactInstanceManager.java | 4 +++ .../react/bridge/CatalystInstance.java | 4 +++ .../react/bridge/CatalystInstanceImpl.java | 4 +++ .../react/bridge/RuntimeScheduler.java | 21 +++++++++++++ .../com/facebook/react/fabric/Binding.java | 5 ++++ .../react/fabric/FabricJSIModuleProvider.java | 1 + .../com/facebook/react/fabric/jni/Android.mk | 3 +- .../com/facebook/react/fabric/jni/Binding.cpp | 12 ++++++++ .../com/facebook/react/fabric/jni/Binding.h | 2 ++ .../src/main/jni/react/jni/Android.mk | 5 ++-- ReactAndroid/src/main/jni/react/jni/BUCK | 2 ++ .../jni/react/jni/CatalystInstanceImpl.cpp | 27 +++++++++++++++++ .../main/jni/react/jni/CatalystInstanceImpl.h | 4 +++ .../main/jni/react/jni/JRuntimeScheduler.cpp | 22 ++++++++++++++ .../main/jni/react/jni/JRuntimeScheduler.h | 30 +++++++++++++++++++ 15 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java create mode 100644 ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp create mode 100644 ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 4c8a8f97977..6df4dd1bd97 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -1360,6 +1360,10 @@ public class ReactInstanceManager { } } + if (ReactFeatureFlags.enableRuntimeScheduler) { + catalystInstance.installRuntimeScheduler(); + } + if (mJSIModulePackage != null) { catalystInstance.addJSIModules( mJSIModulePackage.getJSIModules( diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java index 1a5067b7edb..09eb2c70183 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java @@ -111,6 +111,10 @@ public interface CatalystInstance RuntimeExecutor getRuntimeExecutor(); + RuntimeScheduler getRuntimeScheduler(); + + void installRuntimeScheduler(); + void addJSIModules(List jsiModules); /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index baffa40aabb..d5a9b97571b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -558,6 +558,10 @@ public class CatalystInstanceImpl implements CatalystInstance { public native RuntimeExecutor getRuntimeExecutor(); + public native RuntimeScheduler getRuntimeScheduler(); + + public native void installRuntimeScheduler(); + @Override public void addJSIModules(List jsiModules) { mJSIModuleRegistry.registerModules(jsiModules); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java new file mode 100644 index 00000000000..7270c65c6bf --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.bridge; + +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; + +/** A Java holder for a C++ RuntimeScheduler. */ +public class RuntimeScheduler { + + @DoNotStrip private HybridData mHybridData; + + public RuntimeScheduler(HybridData hybridData) { + mHybridData = hybridData; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java index 6449ef07579..e02f4188f5d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java @@ -9,11 +9,13 @@ package com.facebook.react.fabric; import android.annotation.SuppressLint; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.RuntimeExecutor; +import com.facebook.react.bridge.RuntimeScheduler; import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.fabric.events.EventBeatManager; import com.facebook.react.fabric.events.EventEmitterWrapper; @@ -37,6 +39,7 @@ public class Binding { private native void installFabricUIManager( RuntimeExecutor runtimeExecutor, + RuntimeScheduler runtimeScheduler, Object uiManager, EventBeatManager eventBeatManager, MessageQueueThread jsMessageQueueThread, @@ -83,6 +86,7 @@ public class Binding { public void register( @NonNull RuntimeExecutor runtimeExecutor, + @Nullable RuntimeScheduler runtimeScheduler, @NonNull FabricUIManager fabricUIManager, @NonNull EventBeatManager eventBeatManager, @NonNull MessageQueueThread jsMessageQueueThread, @@ -91,6 +95,7 @@ public class Binding { fabricUIManager.setBinding(this); installFabricUIManager( runtimeExecutor, + runtimeScheduler, fabricUIManager, eventBeatManager, jsMessageQueueThread, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java index 84bea4d85f6..c4a6fbfb5c7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java @@ -55,6 +55,7 @@ public class FabricJSIModuleProvider implements JSIModuleProvider { binding.register( mReactApplicationContext.getCatalystInstance().getRuntimeExecutor(), + mReactApplicationContext.getCatalystInstance().getRuntimeScheduler(), uiManager, eventBeatManager, jsMessageQueueThread, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk index 2ad53b97cc2..1c2bde705d6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk @@ -11,7 +11,7 @@ LOCAL_MODULE := fabricjni LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) -LOCAL_SHARED_LIBRARIES := libjsi libreactconfig librrc_slider librrc_progressbar librrc_switch librrc_modal libyoga libglog libfb libfbjni libglog_init libfolly_json libfolly_futures libreact_render_mounting libreactnativeutilsjni libreact_utils libreact_render_debug libreact_render_graphics libreact_render_core react_render_componentregistry librrc_view librrc_unimplementedview librrc_root librrc_scrollview libbetter libreact_render_attributedstring libreact_render_uimanager libreact_render_templateprocessor libreact_render_scheduler libreact_render_animations libreact_render_imagemanager libreact_render_textlayoutmanager libreact_codegen_rncore rrc_text librrc_image librrc_textinput libreact_debug libreact_render_mapbuffer libmapbufferjni libreact_render_telemetry +LOCAL_SHARED_LIBRARIES := libjsi libreactconfig librrc_slider librrc_progressbar librrc_switch librrc_modal libyoga libglog libfb libfbjni libglog_init libfolly_json libfolly_futures libreact_render_mounting libreactnativeutilsjni libreact_utils libreact_render_debug libreact_render_graphics libreact_render_core react_render_componentregistry librrc_view librrc_unimplementedview librrc_root librrc_scrollview libbetter libreact_render_attributedstring libreact_render_uimanager libreact_render_templateprocessor libreact_render_scheduler libreact_render_animations libreact_render_imagemanager libreact_render_textlayoutmanager libreact_codegen_rncore rrc_text librrc_image librrc_textinput libreact_debug libreact_render_mapbuffer libmapbufferjni libreact_render_telemetry libreact_render_runtimescheduler LOCAL_STATIC_LIBRARIES := @@ -56,6 +56,7 @@ $(call import-module,react/renderer/graphics) $(call import-module,react/renderer/imagemanager) $(call import-module,react/renderer/mapbuffer) $(call import-module,react/renderer/mounting) +$(call import-module,react/renderer/runtimescheduler) $(call import-module,react/renderer/scheduler) $(call import-module,react/renderer/templateprocessor) $(call import-module,react/renderer/textlayoutmanager) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index d7fb074d31c..be1f8c0aa35 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -493,6 +493,7 @@ bool isMapBufferSerializationEnabled() { void Binding::installFabricUIManager( jni::alias_ref runtimeExecutorHolder, + jni::alias_ref runtimeSchedulerHolder, jni::alias_ref javaUIManager, EventBeatManager *eventBeatManager, jni::alias_ref jsMessageQueueThread, @@ -527,6 +528,17 @@ void Binding::installFabricUIManager( std::make_shared(jsMessageQueueThread); auto runtimeExecutor = runtimeExecutorHolder->cthis()->get(); + if (runtimeSchedulerHolder) { + auto runtimeScheduler = runtimeSchedulerHolder->cthis()->get(); + if (runtimeScheduler) { + runtimeExecutor = + [runtimeScheduler]( + std::function &&callback) { + runtimeScheduler->scheduleWork(std::move(callback)); + }; + } + } + // TODO: T31905686 Create synchronous Event Beat jni::global_ref localJavaUIManager = javaUIManager_; EventBeat::Factory synchronousBeatFactory = diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h index d3045b0e1b1..5ae4f0189e2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,7 @@ class Binding : public jni::HybridClass, void installFabricUIManager( jni::alias_ref runtimeExecutorHolder, + jni::alias_ref runtimeSchedulerHolder, jni::alias_ref javaUIManager, EventBeatManager *eventBeatManager, jni::alias_ref jsMessageQueueThread, diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index 82445d00ec0..af2077b5a66 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -27,7 +27,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -Wno-unused-lambda-capture LOCAL_LDLIBS += -landroid # The dynamic libraries (.so files) that this module depends on. -LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libglog_init libyoga +LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libglog_init libyoga libreact_render_runtimescheduler # The static libraries (.a files) that this module depends on. LOCAL_STATIC_LIBRARIES := libreactnative libcallinvokerholder libruntimeexecutor @@ -77,7 +77,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -Wno-unused-lambda-capture LOCAL_LDLIBS += -landroid # The dynamic libraries (.so files) that this module depends on. -LOCAL_SHARED_LIBRARIES := libreactnativeutilsjni libfolly_json libfb libfbjni libglog_init libyoga logger +LOCAL_SHARED_LIBRARIES := libreactnativeutilsjni libfolly_json libfb libfbjni libglog_init libyoga logger libreact_render_runtimescheduler # The static libraries (.a files) that this module depends on. LOCAL_STATIC_LIBRARIES := libreactnative libruntimeexecutor libcallinvokerholder @@ -129,6 +129,7 @@ $(call import-module,callinvoker) $(call import-module,reactperflogger) $(call import-module,hermes) $(call import-module,runtimeexecutor) +$(call import-module,react/renderer/runtimescheduler) $(call import-module,react/nativemodule/core) include $(REACT_SRC_DIR)/reactperflogger/jni/Android.mk diff --git a/ReactAndroid/src/main/jni/react/jni/BUCK b/ReactAndroid/src/main/jni/react/jni/BUCK index dc88910cf42..99160d55a3c 100644 --- a/ReactAndroid/src/main/jni/react/jni/BUCK +++ b/ReactAndroid/src/main/jni/react/jni/BUCK @@ -20,6 +20,7 @@ EXPORTED_HEADERS = [ "ReadableNativeArray.h", "ReadableNativeMap.h", "JRuntimeExecutor.h", + "JRuntimeScheduler.h", "WritableNativeArray.h", "WritableNativeMap.h", ] @@ -67,6 +68,7 @@ rn_xplat_cxx_library( react_native_xplat_target("cxxreact:module"), react_native_xplat_target("jsinspector:jsinspector"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"), + react_native_xplat_target("react/renderer/runtimescheduler:runtimescheduler"), react_native_xplat_target("logger:logger"), react_native_xplat_dep("jsi:jsi"), FBJNI_TARGET, diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 6b1f09f2720..e5b36b30dd1 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include @@ -136,6 +138,11 @@ void CatalystInstanceImpl::registerNatives() { CatalystInstanceImpl::handleMemoryPressure), makeNativeMethod( "getRuntimeExecutor", CatalystInstanceImpl::getRuntimeExecutor), + makeNativeMethod( + "getRuntimeScheduler", CatalystInstanceImpl::getRuntimeScheduler), + makeNativeMethod( + "installRuntimeScheduler", + CatalystInstanceImpl::installRuntimeScheduler), makeNativeMethod( "warnOnLegacyNativeModuleSystemUse", CatalystInstanceImpl::warnOnLegacyNativeModuleSystemUse), @@ -388,5 +395,25 @@ CatalystInstanceImpl::getRuntimeExecutor() { return runtimeExecutor_; } +jni::alias_ref +CatalystInstanceImpl::getRuntimeScheduler() { + return runtimeScheduler_; +} + +void CatalystInstanceImpl::installRuntimeScheduler() { + if (!runtimeScheduler_) { + auto runtimeExecutor = instance_->getRuntimeExecutor(); + auto runtimeScheduler = std::make_shared(runtimeExecutor); + + runtimeScheduler_ = + jni::make_global(JRuntimeScheduler::newObjectCxxArgs(runtimeScheduler)); + + runtimeExecutor([runtimeScheduler](jsi::Runtime &runtime) { + RuntimeSchedulerBinding::createAndInstallIfNeeded( + runtime, runtimeScheduler); + }); + } +} + } // namespace react } // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index cc4006b26b0..66daec3e34b 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h @@ -15,6 +15,7 @@ #include "CxxModuleWrapper.h" #include "JMessageQueueThread.h" #include "JRuntimeExecutor.h" +#include "JRuntimeScheduler.h" #include "JSLoader.h" #include "JavaModuleWrapper.h" #include "ModuleRegistryBuilder.h" @@ -98,6 +99,8 @@ class CatalystInstanceImpl : public jni::HybridClass { jni::alias_ref getJSCallInvokerHolder(); jni::alias_ref getNativeCallInvokerHolder(); jni::alias_ref getRuntimeExecutor(); + jni::alias_ref getRuntimeScheduler(); + void installRuntimeScheduler(); void setGlobalVariable(std::string propName, std::string &&jsonValue); jlong getJavaScriptContext(); void handleMemoryPressure(int pressureLevel); @@ -110,6 +113,7 @@ class CatalystInstanceImpl : public jni::HybridClass { jni::global_ref jsCallInvokerHolder_; jni::global_ref nativeCallInvokerHolder_; jni::global_ref runtimeExecutor_; + jni::global_ref runtimeScheduler_; }; } // namespace react diff --git a/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp new file mode 100644 index 00000000000..3b059ec89c1 --- /dev/null +++ b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "JRuntimeScheduler.h" + +namespace facebook { +namespace react { + +JRuntimeScheduler::JRuntimeScheduler( + std::shared_ptr const &runtimeScheduler) + : runtimeScheduler_(runtimeScheduler) {} + +std::shared_ptr JRuntimeScheduler::get() { + return runtimeScheduler_; +} + +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h new file mode 100644 index 00000000000..fb58c7ef777 --- /dev/null +++ b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +class JRuntimeScheduler : public jni::HybridClass { + public: + static auto constexpr kJavaDescriptor = + "Lcom/facebook/react/bridge/RuntimeScheduler;"; + + std::shared_ptr get(); + + private: + friend HybridBase; + JRuntimeScheduler(std::shared_ptr const &runtimeScheduler); + std::shared_ptr runtimeScheduler_; +}; + +} // namespace react +} // namespace facebook