diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp new file mode 100644 index 0000000000..1d9b2dd27f --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp @@ -0,0 +1,69 @@ +/* + * 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 +#include +#include + +#include "AsyncEventBeatV2.h" + +namespace facebook::react { + +AsyncEventBeatV2::AsyncEventBeatV2( + EventBeat::SharedOwnerBox const &ownerBox, + EventBeatManager *eventBeatManager, + RuntimeExecutor runtimeExecutor, + jni::global_ref javaUIManager) + : EventBeat(ownerBox), + eventBeatManager_(eventBeatManager), + runtimeExecutor_(runtimeExecutor), + javaUIManager_(javaUIManager) { + eventBeatManager->addObserver(*this); +} + +AsyncEventBeatV2::~AsyncEventBeatV2() { + eventBeatManager_->removeObserver(*this); +} + +void AsyncEventBeatV2::tick() const { + if (!isRequested_ || isBeatCallbackScheduled_) { + return; + } + + isRequested_ = false; + isBeatCallbackScheduled_ = true; + + runtimeExecutor_([this, ownerBox = ownerBox_](jsi::Runtime &runtime) { + isBeatCallbackScheduled_ = false; + auto owner = ownerBox->owner.lock(); + if (!owner) { + return; + } + + if (beatCallback_) { + beatCallback_(runtime); + } + }); +} + +void AsyncEventBeatV2::induce() const { + tick(); +} + +void AsyncEventBeatV2::request() const { + bool alreadyRequested = isRequested_; + EventBeat::request(); + if (!alreadyRequested) { + // Notifies java side that an event will be dispatched (e.g. LayoutEvent) + static auto onRequestEventBeat = + jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") + ->getMethod("onRequestEventBeat"); + onRequestEventBeat(javaUIManager_); + } +} + +} // namespace facebook::react diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h new file mode 100644 index 0000000000..acd682f4cd --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h @@ -0,0 +1,40 @@ +/* + * 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 "EventBeatManager.h" + +namespace facebook::react { + +class AsyncEventBeatV2 final : public EventBeat, + public EventBeatManagerObserver { + public: + AsyncEventBeatV2( + EventBeat::SharedOwnerBox const &ownerBox, + EventBeatManager *eventBeatManager, + RuntimeExecutor runtimeExecutor, + jni::global_ref javaUIManager); + + ~AsyncEventBeatV2() override; + + void tick() const override; + + void induce() const override; + + void request() const override; + + private: + EventBeatManager *eventBeatManager_; + RuntimeExecutor runtimeExecutor_; + jni::global_ref javaUIManager_; + mutable std::atomic isBeatCallbackScheduled_{false}; +}; + +} // namespace facebook::react 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 aee8446f07..1a4bf7b58b 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 @@ -7,6 +7,7 @@ #include "Binding.h" #include "AsyncEventBeat.h" +#include "AsyncEventBeatV2.h" #include "EventEmitterWrapper.h" #include "ReactNativeConfigHolder.h" #include "StateWrapperImpl.h" @@ -541,22 +542,39 @@ void Binding::installFabricUIManager( } } + auto enableV2AsynchronousEventBeat = + config->getBool("react_fabric:enable_asynchronous_event_beat_v2_android"); + // TODO: T31905686 Create synchronous Event Beat jni::global_ref localJavaUIManager = javaUIManager_; EventBeat::Factory synchronousBeatFactory = - [eventBeatManager, runtimeExecutor, localJavaUIManager]( - EventBeat::SharedOwnerBox const &ownerBox) + [eventBeatManager, + runtimeExecutor, + localJavaUIManager, + enableV2AsynchronousEventBeat](EventBeat::SharedOwnerBox const &ownerBox) -> std::unique_ptr { - return std::make_unique( - ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); + if (enableV2AsynchronousEventBeat) { + return std::make_unique( + ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); + } else { + return std::make_unique( + ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); + } }; EventBeat::Factory asynchronousBeatFactory = - [eventBeatManager, runtimeExecutor, localJavaUIManager]( - EventBeat::SharedOwnerBox const &ownerBox) + [eventBeatManager, + runtimeExecutor, + localJavaUIManager, + enableV2AsynchronousEventBeat](EventBeat::SharedOwnerBox const &ownerBox) -> std::unique_ptr { - return std::make_unique( - ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); + if (enableV2AsynchronousEventBeat) { + return std::make_unique( + ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); + } else { + return std::make_unique( + ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager); + } }; contextContainer->insert("ReactNativeConfig", config);