diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index c9e5e731a7b8..ee53e7efa48f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -280,6 +280,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun useOptimisedViewPreallocationOnAndroid(): Boolean = accessor.useOptimisedViewPreallocationOnAndroid() + /** + * Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback. + */ + @JvmStatic + public fun useOptimizedEventBatchingOnAndroid(): Boolean = accessor.useOptimizedEventBatchingOnAndroid() + /** * When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index e00a8b171176..9ef2ffa78f39 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<47dbdb6ffcd04bb7b2d2d01c4c1e7ace>> */ /** @@ -62,6 +62,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useNewReactImageViewBackgroundDrawingCache: Boolean? = null private var useOptimisedViewPreallocationOnAndroidCache: Boolean? = null + private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateOnLayoutCache: Boolean? = null private var useStateAlignmentMechanismCache: Boolean? = null @@ -445,6 +446,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun useOptimizedEventBatchingOnAndroid(): Boolean { + var cached = useOptimizedEventBatchingOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.useOptimizedEventBatchingOnAndroid() + useOptimizedEventBatchingOnAndroidCache = cached + } + return cached + } + override fun useRuntimeShadowNodeReferenceUpdate(): Boolean { var cached = useRuntimeShadowNodeReferenceUpdateCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index d221e1420b82..949027d48977 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<580db8acae42a65aeb678d2d6ef4630c>> + * @generated SignedSource<<93ce8e0026e125192af1ad86730941c0>> */ /** @@ -112,6 +112,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun useOptimisedViewPreallocationOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun useOptimizedEventBatchingOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun useRuntimeShadowNodeReferenceUpdate(): Boolean @DoNotStrip @JvmStatic public external fun useRuntimeShadowNodeReferenceUpdateOnLayout(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index f537181cd654..a1c8ff270e48 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<00aae631e9d9b146fae9be838e04e165>> + * @generated SignedSource<> */ /** @@ -107,6 +107,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun useOptimisedViewPreallocationOnAndroid(): Boolean = false + override fun useOptimizedEventBatchingOnAndroid(): Boolean = false + override fun useRuntimeShadowNodeReferenceUpdate(): Boolean = false override fun useRuntimeShadowNodeReferenceUpdateOnLayout(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 4f41507f1b11..65b3dc38c756 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<7727737ae31a239d6b68397fafadbfea>> */ /** @@ -66,6 +66,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useNewReactImageViewBackgroundDrawingCache: Boolean? = null private var useOptimisedViewPreallocationOnAndroidCache: Boolean? = null + private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateOnLayoutCache: Boolean? = null private var useStateAlignmentMechanismCache: Boolean? = null @@ -491,6 +492,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun useOptimizedEventBatchingOnAndroid(): Boolean { + var cached = useOptimizedEventBatchingOnAndroidCache + if (cached == null) { + cached = currentProvider.useOptimizedEventBatchingOnAndroid() + accessedFeatureFlags.add("useOptimizedEventBatchingOnAndroid") + useOptimizedEventBatchingOnAndroidCache = cached + } + return cached + } + override fun useRuntimeShadowNodeReferenceUpdate(): Boolean { var cached = useRuntimeShadowNodeReferenceUpdateCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 2226963318ce..b6bfbc6cf98f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2c8c28515aa6929b975ef7193c8bf72e>> + * @generated SignedSource<> */ /** @@ -107,6 +107,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun useOptimisedViewPreallocationOnAndroid(): Boolean + @DoNotStrip public fun useOptimizedEventBatchingOnAndroid(): Boolean + @DoNotStrip public fun useRuntimeShadowNodeReferenceUpdate(): Boolean @DoNotStrip public fun useRuntimeShadowNodeReferenceUpdateOnLayout(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java index ce8520ebcaac..b7675134bd1b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java @@ -7,6 +7,7 @@ package com.facebook.react.uimanager.events; +import android.os.Handler; import android.view.Choreographer; import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.LifecycleEventListener; @@ -15,6 +16,7 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.common.UIManagerType; @@ -27,6 +29,8 @@ */ @Nullsafe(Nullsafe.Mode.LOCAL) public class FabricEventDispatcher implements EventDispatcher, LifecycleEventListener { + private static final Handler uiThreadHandler = UiThreadUtil.getUiThreadHandler(); + private final ReactEventEmitter mReactEventEmitter; private final ReactApplicationContext mReactContext; private final CopyOnWriteArrayList mListeners = @@ -36,6 +40,25 @@ public class FabricEventDispatcher implements EventDispatcher, LifecycleEventLis private final FabricEventDispatcher.ScheduleDispatchFrameCallback mCurrentFrameCallback = new FabricEventDispatcher.ScheduleDispatchFrameCallback(); + private boolean mIsDispatchScheduled = false; + private final Runnable mDispatchEventsRunnable = + new Runnable() { + @Override + public void run() { + mIsDispatchScheduled = false; + + Systrace.beginSection( + Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "BatchEventDispatchedListeners"); + try { + for (BatchEventDispatchedListener listener : mPostEventDispatchListeners) { + listener.onBatchEventDispatched(); + } + } finally { + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + } + } + }; + public FabricEventDispatcher(ReactApplicationContext reactContext) { mReactContext = reactContext; mReactContext.addLifecycleEventListener(this); @@ -54,7 +77,7 @@ public void dispatchEvent(Event event) { } event.dispose(); - maybePostFrameCallbackFromNonUI(); + scheduleDispatchOfBatchedEvents(); } private void dispatchSynchronous(Event event) { @@ -85,19 +108,17 @@ private void dispatchSynchronous(Event event) { } public void dispatchAllEvents() { - maybePostFrameCallbackFromNonUI(); + scheduleDispatchOfBatchedEvents(); } - private void maybePostFrameCallbackFromNonUI() { - if (mReactEventEmitter != null) { - // If the host activity is paused, the frame callback may not be currently - // posted. Ensure that it is so that this event gets delivered promptly. - mCurrentFrameCallback.maybePostFromNonUI(); + private void scheduleDispatchOfBatchedEvents() { + if (ReactNativeFeatureFlags.useOptimizedEventBatchingOnAndroid()) { + if (!mIsDispatchScheduled) { + mIsDispatchScheduled = true; + uiThreadHandler.postAtFrontOfQueue(mDispatchEventsRunnable); + } } else { - // No JS application has started yet, or resumed. This can happen when a ReactRootView is - // added to view hierarchy, but ReactContext creation has not completed yet. In this case, any - // touch event dispatch will hit this codepath, and we simply queue them so that they - // are dispatched once ReactContext creation completes and JS app is running. + mCurrentFrameCallback.maybeScheduleDispatchOfBatchedEvents(); } } @@ -121,17 +142,17 @@ public void removeBatchEventDispatchedListener(BatchEventDispatchedListener list @Override public void onHostResume() { - maybePostFrameCallbackFromNonUI(); + scheduleDispatchOfBatchedEvents(); } @Override public void onHostPause() { - stopFrameCallback(); + cancelDispatchOfBatchedEvents(); } @Override public void onHostDestroy() { - stopFrameCallback(); + cancelDispatchOfBatchedEvents(); } public void onCatalystInstanceDestroyed() { @@ -139,14 +160,19 @@ public void onCatalystInstanceDestroyed() { new Runnable() { @Override public void run() { - stopFrameCallback(); + cancelDispatchOfBatchedEvents(); } }); } - private void stopFrameCallback() { + private void cancelDispatchOfBatchedEvents() { UiThreadUtil.assertOnUiThread(); - mCurrentFrameCallback.stop(); + if (ReactNativeFeatureFlags.useOptimizedEventBatchingOnAndroid()) { + mIsDispatchScheduled = false; + uiThreadHandler.removeCallbacks(mDispatchEventsRunnable); + } else { + mCurrentFrameCallback.stop(); + } } public void registerEventEmitter(@UIManagerType int uiManagerType, RCTEventEmitter eventEmitter) { @@ -163,7 +189,7 @@ public void unregisterEventEmitter(@UIManagerType int uiManagerType) { } private class ScheduleDispatchFrameCallback implements Choreographer.FrameCallback { - private volatile boolean mIsPosted = false; + private volatile boolean mIsDispatchScheduled = false; private boolean mShouldStop = false; @Override @@ -171,9 +197,9 @@ public void doFrame(long frameTimeNanos) { UiThreadUtil.assertOnUiThread(); if (mShouldStop) { - mIsPosted = false; + mIsDispatchScheduled = false; } else { - post(); + dispatchBatchedEvents(); } Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "BatchEventDispatchedListeners"); @@ -190,32 +216,32 @@ public void stop() { mShouldStop = true; } - public void maybePost() { - if (!mIsPosted) { - mIsPosted = true; - post(); + public void maybeDispatchBatchedEvents() { + if (!mIsDispatchScheduled) { + mIsDispatchScheduled = true; + dispatchBatchedEvents(); } } - private void post() { + private void dispatchBatchedEvents() { ReactChoreographer.getInstance() .postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, mCurrentFrameCallback); } - public void maybePostFromNonUI() { - if (mIsPosted) { + public void maybeScheduleDispatchOfBatchedEvents() { + if (mIsDispatchScheduled) { return; } // We should only hit this slow path when we receive events while the host activity is paused. if (mReactContext.isOnUiQueueThread()) { - maybePost(); + maybeDispatchBatchedEvents(); } else { mReactContext.runOnUiQueueThread( new Runnable() { @Override public void run() { - maybePost(); + maybeDispatchBatchedEvents(); } }); } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index aff927743127..b4b62e99d11c 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<35f5003b77104e68e32741e4626e2ba6>> + * @generated SignedSource<> */ /** @@ -291,6 +291,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool useOptimizedEventBatchingOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useOptimizedEventBatchingOnAndroid"); + return method(javaProvider_); + } + bool useRuntimeShadowNodeReferenceUpdate() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useRuntimeShadowNodeReferenceUpdate"); @@ -529,6 +535,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useOptimisedViewPreallocationOnAndroid( return ReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid(); } +bool JReactNativeFeatureFlagsCxxInterop::useOptimizedEventBatchingOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::useRuntimeShadowNodeReferenceUpdate( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate(); @@ -692,6 +703,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "useOptimisedViewPreallocationOnAndroid", JReactNativeFeatureFlagsCxxInterop::useOptimisedViewPreallocationOnAndroid), + makeNativeMethod( + "useOptimizedEventBatchingOnAndroid", + JReactNativeFeatureFlagsCxxInterop::useOptimizedEventBatchingOnAndroid), makeNativeMethod( "useRuntimeShadowNodeReferenceUpdate", JReactNativeFeatureFlagsCxxInterop::useRuntimeShadowNodeReferenceUpdate), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 760d549343c2..133f5786b652 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<0e82efb1fac0a62802f5f09e96de31d0>> */ /** @@ -156,6 +156,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool useOptimisedViewPreallocationOnAndroid( facebook::jni::alias_ref); + static bool useOptimizedEventBatchingOnAndroid( + facebook::jni::alias_ref); + static bool useRuntimeShadowNodeReferenceUpdate( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index a336b0da56a8..5d603e20a93e 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<31c0fac0172a6d3f9ab84a77d4967f5e>> */ /** @@ -189,6 +189,10 @@ bool ReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid() { return getAccessor().useOptimisedViewPreallocationOnAndroid(); } +bool ReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid() { + return getAccessor().useOptimizedEventBatchingOnAndroid(); +} + bool ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate() { return getAccessor().useRuntimeShadowNodeReferenceUpdate(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 63271e91427b..d371a4736180 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<748622d87b1051bbb1cd79fb479ab0e2>> + * @generated SignedSource<<56c3d93945f6c320e268c9ba32cbde0f>> */ /** @@ -247,6 +247,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool useOptimisedViewPreallocationOnAndroid(); + /** + * Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback. + */ + RN_EXPORT static bool useOptimizedEventBatchingOnAndroid(); + /** * When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 312b2e36eb03..4356721714c3 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<90f05e6a6a414704176234724ca1fc04>> + * @generated SignedSource<<73c8cf1d23aa58b4b60e4018c0ddc12e>> */ /** @@ -785,6 +785,24 @@ bool ReactNativeFeatureFlagsAccessor::useOptimisedViewPreallocationOnAndroid() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { + auto flagValue = useOptimizedEventBatchingOnAndroid_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(42, "useOptimizedEventBatchingOnAndroid"); + + flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); + useOptimizedEventBatchingOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { auto flagValue = useRuntimeShadowNodeReferenceUpdate_.load(); @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(43, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(44, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "useStateAlignmentMechanism"); + markFlagAsAccessed(45, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "useTurboModuleInterop"); + markFlagAsAccessed(46, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 45b9d9bbc04b..e0c66cd1d72a 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<94a2acd88ff16cfe528e0ec9baf6a383>> */ /** @@ -73,6 +73,7 @@ class ReactNativeFeatureFlagsAccessor { bool useNativeViewConfigsInBridgelessMode(); bool useNewReactImageViewBackgroundDrawing(); bool useOptimisedViewPreallocationOnAndroid(); + bool useOptimizedEventBatchingOnAndroid(); bool useRuntimeShadowNodeReferenceUpdate(); bool useRuntimeShadowNodeReferenceUpdateOnLayout(); bool useStateAlignmentMechanism(); @@ -87,7 +88,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 46> accessedFeatureFlags_; + std::array, 47> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowRecursiveCommitsWithSynchronousMountOnAndroid_; @@ -131,6 +132,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> useNativeViewConfigsInBridgelessMode_; std::atomic> useNewReactImageViewBackgroundDrawing_; std::atomic> useOptimisedViewPreallocationOnAndroid_; + std::atomic> useOptimizedEventBatchingOnAndroid_; std::atomic> useRuntimeShadowNodeReferenceUpdate_; std::atomic> useRuntimeShadowNodeReferenceUpdateOnLayout_; std::atomic> useStateAlignmentMechanism_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 90513ef62287..f999b7c36e98 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<602c539c5cf438a04a1fb4b6ce05cd3a>> */ /** @@ -195,6 +195,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool useOptimizedEventBatchingOnAndroid() override { + return false; + } + bool useRuntimeShadowNodeReferenceUpdate() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 8bf060efdcc5..e68a77bb4af7 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6bfd567b419f4dbb1a72470265fae271>> + * @generated SignedSource<> */ /** @@ -67,6 +67,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool useNativeViewConfigsInBridgelessMode() = 0; virtual bool useNewReactImageViewBackgroundDrawing() = 0; virtual bool useOptimisedViewPreallocationOnAndroid() = 0; + virtual bool useOptimizedEventBatchingOnAndroid() = 0; virtual bool useRuntimeShadowNodeReferenceUpdate() = 0; virtual bool useRuntimeShadowNodeReferenceUpdateOnLayout() = 0; virtual bool useStateAlignmentMechanism() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index f33a4a9be696..4015c22847d0 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<903710df33dd5666f8f2ddce79f66660>> + * @generated SignedSource<<1461fc4acff2a28056df4faa4d622a16>> */ /** @@ -247,6 +247,11 @@ bool NativeReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid( return ReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid(); } +bool NativeReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid(); +} + bool NativeReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 166b4071f135..225467de77f8 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6d1f1233f646704d1403f984dabbb2e4>> + * @generated SignedSource<<9f06e832566c4c1271eaf9bb5cfdf886>> */ /** @@ -119,6 +119,8 @@ class NativeReactNativeFeatureFlags bool useOptimisedViewPreallocationOnAndroid(jsi::Runtime& runtime); + bool useOptimizedEventBatchingOnAndroid(jsi::Runtime& runtime); + bool useRuntimeShadowNodeReferenceUpdate(jsi::Runtime& runtime); bool useRuntimeShadowNodeReferenceUpdateOnLayout(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 09b3f412d4a0..e4f1b270a4d5 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -240,6 +240,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Moves more of the work in view preallocation to the main thread to free up JS thread.', }, + useOptimizedEventBatchingOnAndroid: { + defaultValue: false, + description: + 'Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback.', + }, useRuntimeShadowNodeReferenceUpdate: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index b6e642d9b100..4eef09446f33 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<1f82c87c0c011c0bf2e76a6e46bb1d3e>> * @flow strict-local */ @@ -88,6 +88,7 @@ export type ReactNativeFeatureFlags = { useNativeViewConfigsInBridgelessMode: Getter, useNewReactImageViewBackgroundDrawing: Getter, useOptimisedViewPreallocationOnAndroid: Getter, + useOptimizedEventBatchingOnAndroid: Getter, useRuntimeShadowNodeReferenceUpdate: Getter, useRuntimeShadowNodeReferenceUpdateOnLayout: Getter, useStateAlignmentMechanism: Getter, @@ -332,6 +333,10 @@ export const useNewReactImageViewBackgroundDrawing: Getter = createNati * Moves more of the work in view preallocation to the main thread to free up JS thread. */ export const useOptimisedViewPreallocationOnAndroid: Getter = createNativeFlagGetter('useOptimisedViewPreallocationOnAndroid', false); +/** + * Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback. + */ +export const useOptimizedEventBatchingOnAndroid: Getter = createNativeFlagGetter('useOptimizedEventBatchingOnAndroid', false); /** * When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 98c7d4b774b6..8db23a6537e1 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<0f11ba941f22bed8f3b43d1332dc4557>> + * @generated SignedSource<<8370ce5bfcfa27bfdaab6549ae54b6d4>> * @flow strict-local */ @@ -65,6 +65,7 @@ export interface Spec extends TurboModule { +useNativeViewConfigsInBridgelessMode?: () => boolean; +useNewReactImageViewBackgroundDrawing?: () => boolean; +useOptimisedViewPreallocationOnAndroid?: () => boolean; + +useOptimizedEventBatchingOnAndroid?: () => boolean; +useRuntimeShadowNodeReferenceUpdate?: () => boolean; +useRuntimeShadowNodeReferenceUpdateOnLayout?: () => boolean; +useStateAlignmentMechanism?: () => boolean;