From 0e0a3e5083c2b62ac585ec81a1fb16c043ed85e2 Mon Sep 17 00:00:00 2001 From: mugtaba <49446523+mugtaba-subahi@users.noreply.github.com> Date: Mon, 7 Sep 2026 11:18:58 +0100 Subject: [PATCH 1/2] Stop re-arming the idle DISPATCH_UI choreographer callback on Android DispatchUIFrameCallback.doFrameGuarded re-schedules itself unconditionally in its finally block, running at vsync rate while no mount items are pending. Behind disableIdleMountItemFrameCallbackRearmAndroid (default off): the finally re-schedules only while items remain pending, and MountItemDispatcher notifies its listener when items are queued (any thread) so FabricUIManager can re-arm the callback - covering off-UI-thread view commands that previously relied on the always-armed pump. --- .../react/fabric/FabricUIManager.java | 20 +- .../fabric/mounting/MountItemDispatcher.kt | 20 +- .../featureflags/ReactNativeFeatureFlags.kt | 8 +- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +- ...agsOverrides_RNOSS_Experimental_Android.kt | 4 +- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 +- .../ReactNativeFeatureFlagsAccessor.cpp | 182 ++++++++++-------- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 11 +- ...tiveFeatureFlagsOverridesOSSExperimental.h | 6 +- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 11 ++ .../featureflags/ReactNativeFeatureFlags.js | 7 +- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 24 files changed, 263 insertions(+), 106 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 1ba1a11fabd2..e27137bf4d11 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -1547,6 +1547,15 @@ public void didDispatchMountItems() { listener.didDispatchMountItems(FabricUIManager.this); } } + + @Override + public void onItemsQueued() { + // Items may be queued from any thread while the DISPATCH_UI frame callback is disarmed at + // idle; re-arm it. schedule() is idempotent and UI-confined, so hop through the UI queue + // when called off the UI thread (with the flag off this is never invoked and the callback + // stays armed via doFrameGuarded's re-schedule). + UiThreadUtil.runOnUiThread(() -> mDispatchUIFrameCallback.schedule()); + } } /** @@ -1585,7 +1594,7 @@ private DispatchUIFrameCallback(ReactContext reactContext) { @UiThread @ThreadConfined(UI) - private void schedule() { + void schedule() { if (!mIsScheduled && mShouldSchedule) { mIsScheduled = true; ReactChoreographer.getInstance() @@ -1663,7 +1672,14 @@ public void doFrameGuarded(long frameTimeNanos) { mIsMountingEnabled = false; throw ex; } finally { - schedule(); + if (!ReactNativeFeatureFlags.disableIdleMountItemFrameCallbackRearmAndroid() + || mMountItemDispatcher.hasPendingItems()) { + // Keep the Choreographer armed only while items remain pending; queueing new items + // re-arms it via MountItemDispatcher.onItemsQueued (covering items queued from + // non-UI threads, e.g. view commands). An unconditional re-schedule here kept the + // Choreographer running at vsync rate while idle. + schedule(); + } } if (ReactNativeFeatureFlags.useSharedAnimatedBackend() && mBinding != null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.kt index 72257c165077..5d2d86378009 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.kt @@ -34,6 +34,18 @@ internal class MountItemDispatcher( private val mountItems: Queue = ConcurrentLinkedQueue() private val preMountItems: Queue = ConcurrentLinkedQueue() + /** @return true if any mount items, pre-mount items or view commands are still pending */ + fun hasPendingItems(): Boolean = + !viewCommandMountItems.isEmpty() || !mountItems.isEmpty() || !preMountItems.isEmpty() + + // Items can be queued from any thread while the DISPATCH_UI frame callback is disarmed at + // idle (see FabricUIManager's doFrameGuarded); the listener re-arms it. + private fun notifyItemsQueued() { + if (ReactNativeFeatureFlags.disableIdleMountItemFrameCallbackRearmAndroid()) { + itemDispatchListener.onItemsQueued() + } + } + private var inDispatch: Boolean = false var batchedExecutionTime: Long = 0L private set @@ -49,19 +61,22 @@ internal class MountItemDispatcher( } else { mountItems.add(mountItem) } + notifyItemsQueued() } fun addMountItem(mountItem: MountItem) { mountItems.add(mountItem) + notifyItemsQueued() } fun addPreAllocateMountItem(mountItem: MountItem) { // We do this check only for PreAllocateViewMountItem - and not DispatchMountItem or regular - // MountItem - because PreAllocateViewMountItems are not batched, and is relatively more + // MountItem - because PreAllocateViewMountItem are not batched, and is relatively more // expensive // both to queue, to drain, and to execute. if (!mountingManager.surfaceIsStopped(mountItem.getSurfaceId())) { preMountItems.add(mountItem) + notifyItemsQueued() } else if (FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT) { FLog.e( TAG, @@ -399,6 +414,9 @@ internal class MountItemDispatcher( fun didMountItems(mountItems: List?) fun didDispatchMountItems() + + /** Called (from any thread) whenever new items are queued into the dispatcher. */ + fun onItemsQueued() } private companion object { 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 8a3a0f464bf9..b0eb20aa3088 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<> */ /** @@ -60,6 +60,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun disableEarlyViewCommandExecution(): Boolean = accessor.disableEarlyViewCommandExecution() + /** + * Stop re-arming the DISPATCH_UI Choreographer frame callback at vsync rate while no mount items are pending on Android; queueing new items re-arms it + */ + @JvmStatic + public fun disableIdleMountItemFrameCallbackRearmAndroid(): Boolean = accessor.disableIdleMountItemFrameCallbackRearmAndroid() + /** * Force disable view preallocation for images triggered from createNode off the main thread on Android */ 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 eeef92fa9bdb..e54e20e5ed82 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<<68aefd0293540d56f57e8badc0de04c8>> + * @generated SignedSource<> */ /** @@ -25,6 +25,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var cxxNativeAnimatedEnabledCache: Boolean? = null private var defaultTextToOverflowHiddenCache: Boolean? = null private var disableEarlyViewCommandExecutionCache: Boolean? = null + private var disableIdleMountItemFrameCallbackRearmAndroidCache: Boolean? = null private var disableImageViewPreallocationAndroidCache: Boolean? = null private var disableMountItemReorderingAndroidCache: Boolean? = null private var disableSubviewClippingAndroidCache: Boolean? = null @@ -152,6 +153,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun disableIdleMountItemFrameCallbackRearmAndroid(): Boolean { + var cached = disableIdleMountItemFrameCallbackRearmAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.disableIdleMountItemFrameCallbackRearmAndroid() + disableIdleMountItemFrameCallbackRearmAndroidCache = cached + } + return cached + } + override fun disableImageViewPreallocationAndroid(): Boolean { var cached = disableImageViewPreallocationAndroidCache 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 5858d3e1cf1b..6e1bcc235019 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<<247f721796621af8615014477518bcd9>> + * @generated SignedSource<> */ /** @@ -38,6 +38,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun disableEarlyViewCommandExecution(): Boolean + @DoNotStrip @JvmStatic public external fun disableIdleMountItemFrameCallbackRearmAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun disableImageViewPreallocationAndroid(): Boolean @DoNotStrip @JvmStatic public external fun disableMountItemReorderingAndroid(): 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 cbddf085960a..db84f0ae29d8 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<<33071257f9c96a8664c9af429e387061>> + * @generated SignedSource<<206dc97d7da91fe44b2020d4edadfab0>> */ /** @@ -33,6 +33,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun disableEarlyViewCommandExecution(): Boolean = false + override fun disableIdleMountItemFrameCallbackRearmAndroid(): Boolean = false + override fun disableImageViewPreallocationAndroid(): Boolean = false override fun disableMountItemReorderingAndroid(): 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 2c4b30b0e025..e01ef8e0c029 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<<4e5e4e50f9ae7b6b2b2e3fa2b3391bb9>> */ /** @@ -29,6 +29,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var cxxNativeAnimatedEnabledCache: Boolean? = null private var defaultTextToOverflowHiddenCache: Boolean? = null private var disableEarlyViewCommandExecutionCache: Boolean? = null + private var disableIdleMountItemFrameCallbackRearmAndroidCache: Boolean? = null private var disableImageViewPreallocationAndroidCache: Boolean? = null private var disableMountItemReorderingAndroidCache: Boolean? = null private var disableSubviewClippingAndroidCache: Boolean? = null @@ -161,6 +162,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun disableIdleMountItemFrameCallbackRearmAndroid(): Boolean { + var cached = disableIdleMountItemFrameCallbackRearmAndroidCache + if (cached == null) { + cached = currentProvider.disableIdleMountItemFrameCallbackRearmAndroid() + accessedFeatureFlags.add("disableIdleMountItemFrameCallbackRearmAndroid") + disableIdleMountItemFrameCallbackRearmAndroidCache = cached + } + return cached + } + override fun disableImageViewPreallocationAndroid(): Boolean { var cached = disableImageViewPreallocationAndroidCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt index 5dc39a4a1163..e49de8265907 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.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<<9a51a403bfc02cd33bbe47c1f0fe6fd6>> */ /** @@ -23,6 +23,8 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android : // We could use JNI to get the defaults from C++, // but that is more expensive than just duplicating the defaults here. + override fun disableIdleMountItemFrameCallbackRearmAndroid(): Boolean = true + override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = true override fun preventShadowTreeCommitExhaustion(): Boolean = true 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 d7d75f50493b..3d4d5da455b7 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<<915bf918212b9898319de61d4cadaa13>> + * @generated SignedSource<<63d4e817b93d97c76150bc83026d6891>> */ /** @@ -33,6 +33,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun disableEarlyViewCommandExecution(): Boolean + @DoNotStrip public fun disableIdleMountItemFrameCallbackRearmAndroid(): Boolean + @DoNotStrip public fun disableImageViewPreallocationAndroid(): Boolean @DoNotStrip public fun disableMountItemReorderingAndroid(): Boolean 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 baa669d6b96b..e65a4cc42a27 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<<177c5cc7f6e970a2d4454c32d7f777ef>> + * @generated SignedSource<<4f2e184213f7daace97362ea973b13f0>> */ /** @@ -69,6 +69,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool disableIdleMountItemFrameCallbackRearmAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("disableIdleMountItemFrameCallbackRearmAndroid"); + return method(javaProvider_); + } + bool disableImageViewPreallocationAndroid() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("disableImageViewPreallocationAndroid"); @@ -584,6 +590,11 @@ bool JReactNativeFeatureFlagsCxxInterop::disableEarlyViewCommandExecution( return ReactNativeFeatureFlags::disableEarlyViewCommandExecution(); } +bool JReactNativeFeatureFlagsCxxInterop::disableIdleMountItemFrameCallbackRearmAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::disableIdleMountItemFrameCallbackRearmAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::disableImageViewPreallocationAndroid( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::disableImageViewPreallocationAndroid(); @@ -1035,6 +1046,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "disableEarlyViewCommandExecution", JReactNativeFeatureFlagsCxxInterop::disableEarlyViewCommandExecution), + makeNativeMethod( + "disableIdleMountItemFrameCallbackRearmAndroid", + JReactNativeFeatureFlagsCxxInterop::disableIdleMountItemFrameCallbackRearmAndroid), makeNativeMethod( "disableImageViewPreallocationAndroid", JReactNativeFeatureFlagsCxxInterop::disableImageViewPreallocationAndroid), 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 73a8b8bfe5c3..1e24111df1b0 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<> */ /** @@ -45,6 +45,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool disableEarlyViewCommandExecution( facebook::jni::alias_ref); + static bool disableIdleMountItemFrameCallbackRearmAndroid( + facebook::jni::alias_ref); + static bool disableImageViewPreallocationAndroid( 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 e2adeca46391..b41bd106ddec 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<<7b726d7483bb35062b79e582323f0d7e>> + * @generated SignedSource<> */ /** @@ -46,6 +46,10 @@ bool ReactNativeFeatureFlags::disableEarlyViewCommandExecution() { return getAccessor().disableEarlyViewCommandExecution(); } +bool ReactNativeFeatureFlags::disableIdleMountItemFrameCallbackRearmAndroid() { + return getAccessor().disableIdleMountItemFrameCallbackRearmAndroid(); +} + bool ReactNativeFeatureFlags::disableImageViewPreallocationAndroid() { return getAccessor().disableImageViewPreallocationAndroid(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 49079da65ebf..8c20f0034996 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<<1e9009301b79f977132c4fa5599aebdd>> + * @generated SignedSource<> */ /** @@ -66,6 +66,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool disableEarlyViewCommandExecution(); + /** + * Stop re-arming the DISPATCH_UI Choreographer frame callback at vsync rate while no mount items are pending on Android; queueing new items re-arms it + */ + RN_EXPORT static bool disableIdleMountItemFrameCallbackRearmAndroid(); + /** * Force disable view preallocation for images triggered from createNode off the main thread on Android */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 24db6caafcd3..ebbdbc619181 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<<7b2f18c94d995b2108f91248fdfecb0c>> + * @generated SignedSource<<8465d3e8d9aad03680cc9ec9d18d12c0>> */ /** @@ -119,6 +119,24 @@ bool ReactNativeFeatureFlagsAccessor::disableEarlyViewCommandExecution() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::disableIdleMountItemFrameCallbackRearmAndroid() { + auto flagValue = disableIdleMountItemFrameCallbackRearmAndroid_.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(5, "disableIdleMountItemFrameCallbackRearmAndroid"); + + flagValue = currentProvider_->disableIdleMountItemFrameCallbackRearmAndroid(); + disableIdleMountItemFrameCallbackRearmAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::disableImageViewPreallocationAndroid() { auto flagValue = disableImageViewPreallocationAndroid_.load(); @@ -128,7 +146,7 @@ bool ReactNativeFeatureFlagsAccessor::disableImageViewPreallocationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(5, "disableImageViewPreallocationAndroid"); + markFlagAsAccessed(6, "disableImageViewPreallocationAndroid"); flagValue = currentProvider_->disableImageViewPreallocationAndroid(); disableImageViewPreallocationAndroid_ = flagValue; @@ -146,7 +164,7 @@ bool ReactNativeFeatureFlagsAccessor::disableMountItemReorderingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(6, "disableMountItemReorderingAndroid"); + markFlagAsAccessed(7, "disableMountItemReorderingAndroid"); flagValue = currentProvider_->disableMountItemReorderingAndroid(); disableMountItemReorderingAndroid_ = flagValue; @@ -164,7 +182,7 @@ bool ReactNativeFeatureFlagsAccessor::disableSubviewClippingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(7, "disableSubviewClippingAndroid"); + markFlagAsAccessed(8, "disableSubviewClippingAndroid"); flagValue = currentProvider_->disableSubviewClippingAndroid(); disableSubviewClippingAndroid_ = flagValue; @@ -182,7 +200,7 @@ bool ReactNativeFeatureFlagsAccessor::disableTextLayoutManagerCacheAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(8, "disableTextLayoutManagerCacheAndroid"); + markFlagAsAccessed(9, "disableTextLayoutManagerCacheAndroid"); flagValue = currentProvider_->disableTextLayoutManagerCacheAndroid(); disableTextLayoutManagerCacheAndroid_ = flagValue; @@ -200,7 +218,7 @@ bool ReactNativeFeatureFlagsAccessor::disableViewPreallocationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(9, "disableViewPreallocationAndroid"); + markFlagAsAccessed(10, "disableViewPreallocationAndroid"); flagValue = currentProvider_->disableViewPreallocationAndroid(); disableViewPreallocationAndroid_ = flagValue; @@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccessibilityOrder() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "enableAccessibilityOrder"); + markFlagAsAccessed(11, "enableAccessibilityOrder"); flagValue = currentProvider_->enableAccessibilityOrder(); enableAccessibilityOrder_ = flagValue; @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccumulatedUpdatesInRawPropsAndroid( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "enableAccumulatedUpdatesInRawPropsAndroid"); + markFlagAsAccessed(12, "enableAccumulatedUpdatesInRawPropsAndroid"); flagValue = currentProvider_->enableAccumulatedUpdatesInRawPropsAndroid(); enableAccumulatedUpdatesInRawPropsAndroid_ = flagValue; @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAndroidTextMeasurementOptimizations( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "enableAndroidTextMeasurementOptimizations"); + markFlagAsAccessed(13, "enableAndroidTextMeasurementOptimizations"); flagValue = currentProvider_->enableAndroidTextMeasurementOptimizations(); enableAndroidTextMeasurementOptimizations_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::enableBridgelessArchitecture() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "enableBridgelessArchitecture"); + markFlagAsAccessed(14, "enableBridgelessArchitecture"); flagValue = currentProvider_->enableBridgelessArchitecture(); enableBridgelessArchitecture_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::enableBufferedCallInvoker() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "enableBufferedCallInvoker"); + markFlagAsAccessed(15, "enableBufferedCallInvoker"); flagValue = currentProvider_->enableBufferedCallInvoker(); enableBufferedCallInvoker_ = flagValue; @@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCppPropsIteratorSetter() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(15, "enableCppPropsIteratorSetter"); + markFlagAsAccessed(16, "enableCppPropsIteratorSetter"); flagValue = currentProvider_->enableCppPropsIteratorSetter(); enableCppPropsIteratorSetter_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCustomFocusSearchOnClippedElementsAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "enableCustomFocusSearchOnClippedElementsAndroid"); + markFlagAsAccessed(17, "enableCustomFocusSearchOnClippedElementsAndroid"); flagValue = currentProvider_->enableCustomFocusSearchOnClippedElementsAndroid(); enableCustomFocusSearchOnClippedElementsAndroid_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDestroyShadowTreeRevisionAsync() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "enableDestroyShadowTreeRevisionAsync"); + markFlagAsAccessed(18, "enableDestroyShadowTreeRevisionAsync"); flagValue = currentProvider_->enableDestroyShadowTreeRevisionAsync(); enableDestroyShadowTreeRevisionAsync_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDoubleMeasurementFixAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "enableDoubleMeasurementFixAndroid"); + markFlagAsAccessed(19, "enableDoubleMeasurementFixAndroid"); flagValue = currentProvider_->enableDoubleMeasurementFixAndroid(); enableDoubleMeasurementFixAndroid_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerRootViewAttachment() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "enableEagerRootViewAttachment"); + markFlagAsAccessed(20, "enableEagerRootViewAttachment"); flagValue = currentProvider_->enableEagerRootViewAttachment(); enableEagerRootViewAttachment_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableExclusivePropsUpdateAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "enableExclusivePropsUpdateAndroid"); + markFlagAsAccessed(21, "enableExclusivePropsUpdateAndroid"); flagValue = currentProvider_->enableExclusivePropsUpdateAndroid(); enableExclusivePropsUpdateAndroid_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricCommitBranching() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "enableFabricCommitBranching"); + markFlagAsAccessed(22, "enableFabricCommitBranching"); flagValue = currentProvider_->enableFabricCommitBranching(); enableFabricCommitBranching_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "enableFabricLogs"); + markFlagAsAccessed(23, "enableFabricLogs"); flagValue = currentProvider_->enableFabricLogs(); enableFabricLogs_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFlexboxAutoMinSizeInStrictMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "enableFlexboxAutoMinSizeInStrictMode"); + markFlagAsAccessed(24, "enableFlexboxAutoMinSizeInStrictMode"); flagValue = currentProvider_->enableFlexboxAutoMinSizeInStrictMode(); enableFlexboxAutoMinSizeInStrictMode_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableFontScaleChangesUpdatingLayout"); + markFlagAsAccessed(25, "enableFontScaleChangesUpdatingLayout"); flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout(); enableFontScaleChangesUpdatingLayout_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSCompressedTextFrameAdjustment() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableIOSCompressedTextFrameAdjustment"); + markFlagAsAccessed(26, "enableIOSCompressedTextFrameAdjustment"); flagValue = currentProvider_->enableIOSCompressedTextFrameAdjustment(); enableIOSCompressedTextFrameAdjustment_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSTextBaselineOffsetPerLine() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "enableIOSTextBaselineOffsetPerLine"); + markFlagAsAccessed(27, "enableIOSTextBaselineOffsetPerLine"); flagValue = currentProvider_->enableIOSTextBaselineOffsetPerLine(); enableIOSTextBaselineOffsetPerLine_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSViewClipToPaddingBox() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "enableIOSViewClipToPaddingBox"); + markFlagAsAccessed(28, "enableIOSViewClipToPaddingBox"); flagValue = currentProvider_->enableIOSViewClipToPaddingBox(); enableIOSViewClipToPaddingBox_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImagePrefetchingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "enableImagePrefetchingAndroid"); + markFlagAsAccessed(29, "enableImagePrefetchingAndroid"); flagValue = currentProvider_->enableImagePrefetchingAndroid(); enableImagePrefetchingAndroid_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImageTransparentTintColor() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "enableImageTransparentTintColor"); + markFlagAsAccessed(30, "enableImageTransparentTintColor"); flagValue = currentProvider_->enableImageTransparentTintColor(); enableImageTransparentTintColor_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImmediateUpdateModeForContentOffsetC // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "enableImmediateUpdateModeForContentOffsetChanges"); + markFlagAsAccessed(31, "enableImmediateUpdateModeForContentOffsetChanges"); flagValue = currentProvider_->enableImmediateUpdateModeForContentOffsetChanges(); enableImmediateUpdateModeForContentOffsetChanges_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImperativeFocus() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "enableImperativeFocus"); + markFlagAsAccessed(32, "enableImperativeFocus"); flagValue = currentProvider_->enableImperativeFocus(); enableImperativeFocus_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::enableInteropViewManagerClassLookUpOptimiz // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "enableInteropViewManagerClassLookUpOptimizationIOS"); + markFlagAsAccessed(33, "enableInteropViewManagerClassLookUpOptimizationIOS"); flagValue = currentProvider_->enableInteropViewManagerClassLookUpOptimizationIOS(); enableInteropViewManagerClassLookUpOptimizationIOS_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIntersectionObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "enableIntersectionObserverByDefault"); + markFlagAsAccessed(34, "enableIntersectionObserverByDefault"); flagValue = currentProvider_->enableIntersectionObserverByDefault(); enableIntersectionObserverByDefault_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::enableKeyEvents() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "enableKeyEvents"); + markFlagAsAccessed(35, "enableKeyEvents"); flagValue = currentProvider_->enableKeyEvents(); enableKeyEvents_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "enableLayoutAnimationsOnAndroid"); + markFlagAsAccessed(36, "enableLayoutAnimationsOnAndroid"); flagValue = currentProvider_->enableLayoutAnimationsOnAndroid(); enableLayoutAnimationsOnAndroid_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "enableLayoutAnimationsOnIOS"); + markFlagAsAccessed(37, "enableLayoutAnimationsOnIOS"); flagValue = currentProvider_->enableLayoutAnimationsOnIOS(); enableLayoutAnimationsOnIOS_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "enableModuleArgumentNSNullConversionIOS"); + markFlagAsAccessed(38, "enableModuleArgumentNSNullConversionIOS"); flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS(); enableModuleArgumentNSNullConversionIOS_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMountingCoordinatorPullModelAndroid( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "enableMountingCoordinatorPullModelAndroid"); + markFlagAsAccessed(39, "enableMountingCoordinatorPullModelAndroid"); flagValue = currentProvider_->enableMountingCoordinatorPullModelAndroid(); enableMountingCoordinatorPullModelAndroid_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMutationObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "enableMutationObserverByDefault"); + markFlagAsAccessed(40, "enableMutationObserverByDefault"); flagValue = currentProvider_->enableMutationObserverByDefault(); enableMutationObserverByDefault_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "enableNativeCSSParsing"); + markFlagAsAccessed(41, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "enablePreparedTextLayout"); + markFlagAsAccessed(42, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(43, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResizeObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "enableResizeObserverByDefault"); + markFlagAsAccessed(44, "enableResizeObserverByDefault"); flagValue = currentProvider_->enableResizeObserverByDefault(); enableResizeObserverByDefault_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSwiftUIBasedFilters() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "enableSwiftUIBasedFilters"); + markFlagAsAccessed(45, "enableSwiftUIBasedFilters"); flagValue = currentProvider_->enableSwiftUIBasedFilters(); enableSwiftUIBasedFilters_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "enableViewCulling"); + markFlagAsAccessed(46, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "enableViewRecycling"); + markFlagAsAccessed(47, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForImage() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(47, "enableViewRecyclingForImage"); + markFlagAsAccessed(48, "enableViewRecyclingForImage"); flagValue = currentProvider_->enableViewRecyclingForImage(); enableViewRecyclingForImage_ = flagValue; @@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(48, "enableViewRecyclingForScrollView"); + markFlagAsAccessed(49, "enableViewRecyclingForScrollView"); flagValue = currentProvider_->enableViewRecyclingForScrollView(); enableViewRecyclingForScrollView_ = flagValue; @@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(49, "enableViewRecyclingForText"); + markFlagAsAccessed(50, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(50, "enableViewRecyclingForView"); + markFlagAsAccessed(51, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewContainerStateExperimenta // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(51, "enableVirtualViewContainerStateExperimental"); + markFlagAsAccessed(52, "enableVirtualViewContainerStateExperimental"); flagValue = currentProvider_->enableVirtualViewContainerStateExperimental(); enableVirtualViewContainerStateExperimental_ = flagValue; @@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::fixDifferentiatorParentTagForUnflattenCase // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(52, "fixDifferentiatorParentTagForUnflattenCase"); + markFlagAsAccessed(53, "fixDifferentiatorParentTagForUnflattenCase"); flagValue = currentProvider_->fixDifferentiatorParentTagForUnflattenCase(); fixDifferentiatorParentTagForUnflattenCase_ = flagValue; @@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(53, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(54, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::fixYogaFlexBasisFitContentInMainAxis() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(54, "fixYogaFlexBasisFitContentInMainAxis"); + markFlagAsAccessed(55, "fixYogaFlexBasisFitContentInMainAxis"); flagValue = currentProvider_->fixYogaFlexBasisFitContentInMainAxis(); fixYogaFlexBasisFitContentInMainAxis_ = flagValue; @@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxAssertSingleHostState() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(55, "fuseboxAssertSingleHostState"); + markFlagAsAccessed(56, "fuseboxAssertSingleHostState"); flagValue = currentProvider_->fuseboxAssertSingleHostState(); fuseboxAssertSingleHostState_ = flagValue; @@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(56, "fuseboxEnabledRelease"); + markFlagAsAccessed(57, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxFrameRecordingEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(57, "fuseboxFrameRecordingEnabled"); + markFlagAsAccessed(58, "fuseboxFrameRecordingEnabled"); flagValue = currentProvider_->fuseboxFrameRecordingEnabled(); fuseboxFrameRecordingEnabled_ = flagValue; @@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxScreenshotCaptureEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(58, "fuseboxScreenshotCaptureEnabled"); + markFlagAsAccessed(59, "fuseboxScreenshotCaptureEnabled"); flagValue = currentProvider_->fuseboxScreenshotCaptureEnabled(); fuseboxScreenshotCaptureEnabled_ = flagValue; @@ -1100,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxWebSocketEventsEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(59, "fuseboxWebSocketEventsEnabled"); + markFlagAsAccessed(60, "fuseboxWebSocketEventsEnabled"); flagValue = currentProvider_->fuseboxWebSocketEventsEnabled(); fuseboxWebSocketEventsEnabled_ = flagValue; @@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::optimizedAnimatedPropUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(60, "optimizedAnimatedPropUpdates"); + markFlagAsAccessed(61, "optimizedAnimatedPropUpdates"); flagValue = currentProvider_->optimizedAnimatedPropUpdates(); optimizedAnimatedPropUpdates_ = flagValue; @@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(61, "overrideBySynchronousMountPropsAtMountingAndroid"); + markFlagAsAccessed(62, "overrideBySynchronousMountPropsAtMountingAndroid"); flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid(); overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue; @@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::perfIssuesEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(62, "perfIssuesEnabled"); + markFlagAsAccessed(63, "perfIssuesEnabled"); flagValue = currentProvider_->perfIssuesEnabled(); perfIssuesEnabled_ = flagValue; @@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(63, "perfMonitorV2Enabled"); + markFlagAsAccessed(64, "perfMonitorV2Enabled"); flagValue = currentProvider_->perfMonitorV2Enabled(); perfMonitorV2Enabled_ = flagValue; @@ -1190,7 +1208,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(64, "preparedTextCacheSize"); + markFlagAsAccessed(65, "preparedTextCacheSize"); flagValue = currentProvider_->preparedTextCacheSize(); preparedTextCacheSize_ = flagValue; @@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(65, "preventShadowTreeCommitExhaustion"); + markFlagAsAccessed(66, "preventShadowTreeCommitExhaustion"); flagValue = currentProvider_->preventShadowTreeCommitExhaustion(); preventShadowTreeCommitExhaustion_ = flagValue; @@ -1226,7 +1244,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2Android() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(66, "redBoxV2Android"); + markFlagAsAccessed(67, "redBoxV2Android"); flagValue = currentProvider_->redBoxV2Android(); redBoxV2Android_ = flagValue; @@ -1244,7 +1262,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2IOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(67, "redBoxV2IOS"); + markFlagAsAccessed(68, "redBoxV2IOS"); flagValue = currentProvider_->redBoxV2IOS(); redBoxV2IOS_ = flagValue; @@ -1262,7 +1280,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(68, "shouldPressibilityUseW3CPointerEventsForHover"); + markFlagAsAccessed(69, "shouldPressibilityUseW3CPointerEventsForHover"); flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover(); shouldPressibilityUseW3CPointerEventsForHover_ = flagValue; @@ -1280,7 +1298,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldTriggerResponderTransferOnScrollAndr // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(69, "shouldTriggerResponderTransferOnScrollAndroid"); + markFlagAsAccessed(70, "shouldTriggerResponderTransferOnScrollAndroid"); flagValue = currentProvider_->shouldTriggerResponderTransferOnScrollAndroid(); shouldTriggerResponderTransferOnScrollAndroid_ = flagValue; @@ -1298,7 +1316,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(70, "skipActivityIdentityAssertionOnHostPause"); + markFlagAsAccessed(71, "skipActivityIdentityAssertionOnHostPause"); flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause(); skipActivityIdentityAssertionOnHostPause_ = flagValue; @@ -1316,7 +1334,7 @@ bool ReactNativeFeatureFlagsAccessor::syncAndroidClipBoundsWithOverflow() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(71, "syncAndroidClipBoundsWithOverflow"); + markFlagAsAccessed(72, "syncAndroidClipBoundsWithOverflow"); flagValue = currentProvider_->syncAndroidClipBoundsWithOverflow(); syncAndroidClipBoundsWithOverflow_ = flagValue; @@ -1334,7 +1352,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(72, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(73, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -1352,7 +1370,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(73, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(74, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -1370,7 +1388,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommitT // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(74, "updateRuntimeShadowNodeReferencesOnCommitThread"); + markFlagAsAccessed(75, "updateRuntimeShadowNodeReferencesOnCommitThread"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommitThread(); updateRuntimeShadowNodeReferencesOnCommitThread_ = flagValue; @@ -1388,7 +1406,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(75, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(76, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -1406,7 +1424,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(76, "useFabricInterop"); + markFlagAsAccessed(77, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -1424,7 +1442,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(77, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(78, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -1442,7 +1460,7 @@ bool ReactNativeFeatureFlagsAccessor::useNestedScrollViewAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(78, "useNestedScrollViewAndroid"); + markFlagAsAccessed(79, "useNestedScrollViewAndroid"); flagValue = currentProvider_->useNestedScrollViewAndroid(); useNestedScrollViewAndroid_ = flagValue; @@ -1460,7 +1478,7 @@ bool ReactNativeFeatureFlagsAccessor::useSharedAnimatedBackend() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(79, "useSharedAnimatedBackend"); + markFlagAsAccessed(80, "useSharedAnimatedBackend"); flagValue = currentProvider_->useSharedAnimatedBackend(); useSharedAnimatedBackend_ = flagValue; @@ -1478,7 +1496,7 @@ bool ReactNativeFeatureFlagsAccessor::useTraitHiddenOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(80, "useTraitHiddenOnAndroid"); + markFlagAsAccessed(81, "useTraitHiddenOnAndroid"); flagValue = currentProvider_->useTraitHiddenOnAndroid(); useTraitHiddenOnAndroid_ = flagValue; @@ -1496,7 +1514,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(81, "useTurboModuleInterop"); + markFlagAsAccessed(82, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -1514,7 +1532,7 @@ double ReactNativeFeatureFlagsAccessor::viewCullingOutsetRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(82, "viewCullingOutsetRatio"); + markFlagAsAccessed(83, "viewCullingOutsetRatio"); flagValue = currentProvider_->viewCullingOutsetRatio(); viewCullingOutsetRatio_ = flagValue; @@ -1532,7 +1550,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(83, "viewTransitionEnabled"); + markFlagAsAccessed(84, "viewTransitionEnabled"); flagValue = currentProvider_->viewTransitionEnabled(); viewTransitionEnabled_ = flagValue; @@ -1550,7 +1568,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionUseHardwareBitmapAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(84, "viewTransitionUseHardwareBitmapAndroid"); + markFlagAsAccessed(85, "viewTransitionUseHardwareBitmapAndroid"); flagValue = currentProvider_->viewTransitionUseHardwareBitmapAndroid(); viewTransitionUseHardwareBitmapAndroid_ = flagValue; @@ -1568,7 +1586,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(85, "virtualViewPrerenderRatio"); + markFlagAsAccessed(86, "virtualViewPrerenderRatio"); flagValue = currentProvider_->virtualViewPrerenderRatio(); virtualViewPrerenderRatio_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index c0716136aeb7..627b0cc31287 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<<3c605578c56e35c6ca97115a63654ae5>> */ /** @@ -39,6 +39,7 @@ class ReactNativeFeatureFlagsAccessor { bool cxxNativeAnimatedEnabled(); bool defaultTextToOverflowHidden(); bool disableEarlyViewCommandExecution(); + bool disableIdleMountItemFrameCallbackRearmAndroid(); bool disableImageViewPreallocationAndroid(); bool disableMountItemReorderingAndroid(); bool disableSubviewClippingAndroid(); @@ -131,13 +132,14 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 86> accessedFeatureFlags_; + std::array, 87> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; std::atomic> cxxNativeAnimatedEnabled_; std::atomic> defaultTextToOverflowHidden_; std::atomic> disableEarlyViewCommandExecution_; + std::atomic> disableIdleMountItemFrameCallbackRearmAndroid_; std::atomic> disableImageViewPreallocationAndroid_; std::atomic> disableMountItemReorderingAndroid_; std::atomic> disableSubviewClippingAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 0b167dc52b96..64b0cbf95a24 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<<2a5f641d6506566cc26cb76f62300bbb>> + * @generated SignedSource<<848612e02e89438bc9b6a1a02742d29f>> */ /** @@ -49,6 +49,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool disableIdleMountItemFrameCallbackRearmAndroid() override { + return false; + } + bool disableImageViewPreallocationAndroid() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index a296d81dd673..e5000b874a76 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.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<<570eb4a5cab112e5f8ea0b4fb1fa205c>> + * @generated SignedSource<<0c553a09c2799b15b9c84ebc0a3a42be>> */ /** @@ -92,6 +92,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::disableEarlyViewCommandExecution(); } + bool disableIdleMountItemFrameCallbackRearmAndroid() override { + auto value = values_["disableIdleMountItemFrameCallbackRearmAndroid"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::disableIdleMountItemFrameCallbackRearmAndroid(); + } + bool disableImageViewPreallocationAndroid() override { auto value = values_["disableImageViewPreallocationAndroid"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h index b19cab84e7d8..38960c99d4cc 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.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<<5c7271fe5fcdd90f61a5a07772b820e5>> + * @generated SignedSource<> */ /** @@ -29,6 +29,10 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur public: ReactNativeFeatureFlagsOverridesOSSExperimental() = default; + bool disableIdleMountItemFrameCallbackRearmAndroid() override { + return true; + } + bool enableFlexboxAutoMinSizeInStrictMode() override { return true; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 1fe8ae4c5de5..ee830190890a 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<<0bbf1352906bbe1642cab3d2b92173e6>> + * @generated SignedSource<<8bac433e0ff001c940653c35ac74c2c5>> */ /** @@ -32,6 +32,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool cxxNativeAnimatedEnabled() = 0; virtual bool defaultTextToOverflowHidden() = 0; virtual bool disableEarlyViewCommandExecution() = 0; + virtual bool disableIdleMountItemFrameCallbackRearmAndroid() = 0; virtual bool disableImageViewPreallocationAndroid() = 0; virtual bool disableMountItemReorderingAndroid() = 0; virtual bool disableSubviewClippingAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index fe848aff41dc..05201c8a53f8 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<<7505981b27be5298787edef4d80527e8>> + * @generated SignedSource<> */ /** @@ -69,6 +69,11 @@ bool NativeReactNativeFeatureFlags::disableEarlyViewCommandExecution( return ReactNativeFeatureFlags::disableEarlyViewCommandExecution(); } +bool NativeReactNativeFeatureFlags::disableIdleMountItemFrameCallbackRearmAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::disableIdleMountItemFrameCallbackRearmAndroid(); +} + bool NativeReactNativeFeatureFlags::disableImageViewPreallocationAndroid( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::disableImageViewPreallocationAndroid(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 33154de77629..c6f72062bfb0 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<> + * @generated SignedSource<<4c7ed91c9a32e11aa40b058dc3867d74>> */ /** @@ -48,6 +48,8 @@ class NativeReactNativeFeatureFlags bool disableEarlyViewCommandExecution(jsi::Runtime& runtime); + bool disableIdleMountItemFrameCallbackRearmAndroid(jsi::Runtime& runtime); + bool disableImageViewPreallocationAndroid(jsi::Runtime& runtime); bool disableMountItemReorderingAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 2166f296602a..82f65928c9c5 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -103,6 +103,17 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + disableIdleMountItemFrameCallbackRearmAndroid: { + defaultValue: false, + metadata: { + dateAdded: '2026-09-07', + description: + 'Stop re-arming the DISPATCH_UI Choreographer frame callback at vsync rate while no mount items are pending on Android; queueing new items re-arms it', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + ossReleaseStage: 'experimental', + }, disableImageViewPreallocationAndroid: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index e9e97cc712a9..119470306a46 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<<16f03db3d1321473d733c3ef6c90fbbe>> * @flow strict * @noformat */ @@ -54,6 +54,7 @@ export type ReactNativeFeatureFlags = Readonly<{ cxxNativeAnimatedEnabled: Getter, defaultTextToOverflowHidden: Getter, disableEarlyViewCommandExecution: Getter, + disableIdleMountItemFrameCallbackRearmAndroid: Getter, disableImageViewPreallocationAndroid: Getter, disableMountItemReorderingAndroid: Getter, disableSubviewClippingAndroid: Getter, @@ -231,6 +232,10 @@ export const defaultTextToOverflowHidden: Getter = createNativeFlagGett * Dispatch view commands in mount item order. */ export const disableEarlyViewCommandExecution: Getter = createNativeFlagGetter('disableEarlyViewCommandExecution', false); +/** + * Stop re-arming the DISPATCH_UI Choreographer frame callback at vsync rate while no mount items are pending on Android; queueing new items re-arms it + */ +export const disableIdleMountItemFrameCallbackRearmAndroid: Getter = createNativeFlagGetter('disableIdleMountItemFrameCallbackRearmAndroid', false); /** * Force disable view preallocation for images triggered from createNode off the main thread on Android */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 32be0cf9d394..08bee608d5cd 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<> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -30,6 +30,7 @@ export interface Spec extends TurboModule { readonly cxxNativeAnimatedEnabled?: () => boolean; readonly defaultTextToOverflowHidden?: () => boolean; readonly disableEarlyViewCommandExecution?: () => boolean; + readonly disableIdleMountItemFrameCallbackRearmAndroid?: () => boolean; readonly disableImageViewPreallocationAndroid?: () => boolean; readonly disableMountItemReorderingAndroid?: () => boolean; readonly disableSubviewClippingAndroid?: () => boolean; From d45be0e65a61611fa550aae26a1dc65a71b94dc6 Mon Sep 17 00:00:00 2001 From: mugtaba <49446523+mugtaba-subahi@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:17:15 +0100 Subject: [PATCH 2/2] Keep the idle DISPATCH_UI callback armed for C++ animation sessions Follow-up to the demand-gated re-arm. DispatchUIFrameCallback also drives C++ animation work every frame: driveCxxAnimations (armed by onAnimationStarted from Binding.cpp, e.g. LayoutAnimations), the shared animation backend behind useSharedAnimatedBackend, and cxxNativeAnimatedEnabled. The previous condition could disarm the callback while an animation session was active but no mount items were pending, starving the session of ticks. The re-arm condition now also keeps the callback armed while mDriveCxxAnimations is set or either C++ animation flag is enabled, and onAnimationStarted re-arms the callback so a session that begins at idle gets its first tick. This mirrors the hasMountItems() || mDriveCxxAnimations condition the old enableOnDemandReactChoreographer experiment used before its removal in #43044. --- .../react/fabric/FabricUIManager.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index e27137bf4d11..7afa8fdb007f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -1462,6 +1462,12 @@ public String resolveCustomDirectEventName(@Nullable String eventName) { @AnyThread public void onAnimationStarted() { mDriveCxxAnimations = true; + if (ReactNativeFeatureFlags.disableIdleMountItemFrameCallbackRearmAndroid()) { + // A C++ animation session may begin while the DISPATCH_UI frame callback is disarmed at + // idle and no mount items are pending yet; re-arm it for the first tick. schedule is + // UI-confined and idempotent. + UiThreadUtil.runOnUiThread(() -> mDispatchUIFrameCallback.schedule()); + } } // Called from Binding.cpp @@ -1672,12 +1678,17 @@ public void doFrameGuarded(long frameTimeNanos) { mIsMountingEnabled = false; throw ex; } finally { + // Keep the Choreographer armed while items remain pending or a C++ animation driver + // needs per-frame ticks from this callback (driveCxxAnimations and + // driveAnimationBackend run here). Queueing new items re-arms it via + // MountItemDispatcher.onItemsQueued, and onAnimationStarted re-arms it when the C++ + // side begins an animation session. The two flags below drive animations from this + // callback unconditionally, so they disable the idle optimization entirely. if (!ReactNativeFeatureFlags.disableIdleMountItemFrameCallbackRearmAndroid() - || mMountItemDispatcher.hasPendingItems()) { - // Keep the Choreographer armed only while items remain pending; queueing new items - // re-arms it via MountItemDispatcher.onItemsQueued (covering items queued from - // non-UI threads, e.g. view commands). An unconditional re-schedule here kept the - // Choreographer running at vsync rate while idle. + || mMountItemDispatcher.hasPendingItems() + || mDriveCxxAnimations + || ReactNativeFeatureFlags.cxxNativeAnimatedEnabled() + || ReactNativeFeatureFlags.useSharedAnimatedBackend()) { schedule(); } }