Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.facebook.react.bridge.ScrollEndedListener
import com.facebook.react.bridge.UIManager
import com.facebook.react.bridge.UIManagerListener
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.module.annotations.ReactModule
Expand Down Expand Up @@ -249,16 +250,28 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
private fun addOperation(operation: UIThreadOperation) {
operation.batchNumber = currentBatchNumber
operations.add(operation)
armFrameCallbackForQueuedOperations()
}

private fun addUnbatchedOperation(operation: UIThreadOperation) {
operation.batchNumber = -1
operations.add(operation)
armFrameCallbackForQueuedOperations()
}

private fun addPreOperation(operation: UIThreadOperation) {
operation.batchNumber = currentBatchNumber
preOperations.add(operation)
armFrameCallbackForQueuedOperations()
}

// With demand-gated re-arm, operations queued from the native module thread must re-arm the
// frame callback themselves: they normally execute (and re-arm it) in didDispatchMountItems,
// but imperative JS animation calls can arrive when no mount items are pending at all.
private fun armFrameCallbackForQueuedOperations() {
if (ReactNativeFeatureFlags.disableIdleNativeAnimatedFrameCallbackRearmAndroid()) {
enqueueFrameCallback()
}
}

// For FabricUIManager only
Expand Down Expand Up @@ -299,6 +312,13 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :

preOperations.executeBatch(batchNumber, nodesManager)
operations.executeBatch(batchNumber, nodesManager)

if (ReactNativeFeatureFlags.disableIdleNativeAnimatedFrameCallbackRearmAndroid()) {
// Operations executed above may have started animations (e.g. startAnimatingNode); the
// frame callback disarms itself when no animations are active, so re-arm it here.
// didDispatchMountItems is UI-confined, like enqueueFrameCallback.
enqueueFrameCallback()
}
}

// For non-FabricUIManager only (no-op since Fabric is the only supported UIManager)
Expand Down Expand Up @@ -339,7 +359,7 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
nodesManagerRef.set(nodesManager)
}

private var enqueuedAnimationOnFrame = false
@Volatile private var enqueuedAnimationOnFrame = false
private val animatedFrameCallback =
object : GuardedFrameCallback(reactContext) {
override fun doFrameGuarded(frameTimeNanos: Long) {
Expand All @@ -348,9 +368,12 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
val nodesManager = nodesManager ?: return
if (nodesManager.hasActiveAnimations()) {
nodesManager.runUpdates(frameTimeNanos)
enqueueFrameCallback()
} else if (!ReactNativeFeatureFlags.disableIdleNativeAnimatedFrameCallbackRearmAndroid()) {
// Only keep the Choreographer armed while animations are actually running; the
// re-arm points above cover operations that may start new animations.
enqueueFrameCallback()
}

enqueueFrameCallback()
} catch (ex: Exception) {
throw RuntimeException(ex)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<b7ef80c2c39c734ae511fe6457b89ce7>>
* @generated SignedSource<<c409cd400d47962a7fc708b7b95540c6>>
*/

/**
Expand Down Expand Up @@ -60,6 +60,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun disableEarlyViewCommandExecution(): Boolean = accessor.disableEarlyViewCommandExecution()

/**
* Stop re-arming the NATIVE_ANIMATED_MODULE Choreographer frame callback at vsync rate while no animations are active on Android
*/
@JvmStatic
public fun disableIdleNativeAnimatedFrameCallbackRearmAndroid(): Boolean = accessor.disableIdleNativeAnimatedFrameCallbackRearmAndroid()

/**
* Force disable view preallocation for images triggered from createNode off the main thread on Android
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<0d7c4d24c294b03b8e0b2d16e7f58ccc>>
*/

/**
Expand All @@ -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 disableIdleNativeAnimatedFrameCallbackRearmAndroidCache: Boolean? = null
private var disableImageViewPreallocationAndroidCache: Boolean? = null
private var disableMountItemReorderingAndroidCache: Boolean? = null
private var disableSubviewClippingAndroidCache: Boolean? = null
Expand Down Expand Up @@ -152,6 +153,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}

override fun disableIdleNativeAnimatedFrameCallbackRearmAndroid(): Boolean {
var cached = disableIdleNativeAnimatedFrameCallbackRearmAndroidCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.disableIdleNativeAnimatedFrameCallbackRearmAndroid()
disableIdleNativeAnimatedFrameCallbackRearmAndroidCache = cached
}
return cached
}

override fun disableImageViewPreallocationAndroid(): Boolean {
var cached = disableImageViewPreallocationAndroidCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<2d29ddffdc0257599914ab6c55c52b40>>
*/

/**
Expand Down Expand Up @@ -38,6 +38,8 @@ public object ReactNativeFeatureFlagsCxxInterop {

@DoNotStrip @JvmStatic public external fun disableEarlyViewCommandExecution(): Boolean

@DoNotStrip @JvmStatic public external fun disableIdleNativeAnimatedFrameCallbackRearmAndroid(): Boolean

@DoNotStrip @JvmStatic public external fun disableImageViewPreallocationAndroid(): Boolean

@DoNotStrip @JvmStatic public external fun disableMountItemReorderingAndroid(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<42e8906f2b12d14277b3af082fc7595d>>
*/

/**
Expand Down Expand Up @@ -33,6 +33,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi

override fun disableEarlyViewCommandExecution(): Boolean = false

override fun disableIdleNativeAnimatedFrameCallbackRearmAndroid(): Boolean = false

override fun disableImageViewPreallocationAndroid(): Boolean = false

override fun disableMountItemReorderingAndroid(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<f218220c66b8367211cae49adba46afc>>
* @generated SignedSource<<37d43af00cb238b2e28108c2a98d6c8e>>
*/

/**
Expand All @@ -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 disableIdleNativeAnimatedFrameCallbackRearmAndroidCache: Boolean? = null
private var disableImageViewPreallocationAndroidCache: Boolean? = null
private var disableMountItemReorderingAndroidCache: Boolean? = null
private var disableSubviewClippingAndroidCache: Boolean? = null
Expand Down Expand Up @@ -161,6 +162,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}

override fun disableIdleNativeAnimatedFrameCallbackRearmAndroid(): Boolean {
var cached = disableIdleNativeAnimatedFrameCallbackRearmAndroidCache
if (cached == null) {
cached = currentProvider.disableIdleNativeAnimatedFrameCallbackRearmAndroid()
accessedFeatureFlags.add("disableIdleNativeAnimatedFrameCallbackRearmAndroid")
disableIdleNativeAnimatedFrameCallbackRearmAndroidCache = cached
}
return cached
}

override fun disableImageViewPreallocationAndroid(): Boolean {
var cached = disableImageViewPreallocationAndroidCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<bad3dbaf92a0a869dfb91523ef4904f9>>
* @generated SignedSource<<adde664babf1cfe0543c67229761825c>>
*/

/**
Expand All @@ -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 disableIdleNativeAnimatedFrameCallbackRearmAndroid(): Boolean = true

override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = true

override fun preventShadowTreeCommitExhaustion(): Boolean = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<e367592ef88f7bca939e0d148cfae64d>>
*/

/**
Expand Down Expand Up @@ -33,6 +33,8 @@ public interface ReactNativeFeatureFlagsProvider {

@DoNotStrip public fun disableEarlyViewCommandExecution(): Boolean

@DoNotStrip public fun disableIdleNativeAnimatedFrameCallbackRearmAndroid(): Boolean

@DoNotStrip public fun disableImageViewPreallocationAndroid(): Boolean

@DoNotStrip public fun disableMountItemReorderingAndroid(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<ab7bac966684df1f1f46f798aa64c5c7>>
*/

/**
Expand Down Expand Up @@ -69,6 +69,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}

bool disableIdleNativeAnimatedFrameCallbackRearmAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("disableIdleNativeAnimatedFrameCallbackRearmAndroid");
return method(javaProvider_);
}

bool disableImageViewPreallocationAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("disableImageViewPreallocationAndroid");
Expand Down Expand Up @@ -584,6 +590,11 @@ bool JReactNativeFeatureFlagsCxxInterop::disableEarlyViewCommandExecution(
return ReactNativeFeatureFlags::disableEarlyViewCommandExecution();
}

bool JReactNativeFeatureFlagsCxxInterop::disableIdleNativeAnimatedFrameCallbackRearmAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::disableIdleNativeAnimatedFrameCallbackRearmAndroid();
}

bool JReactNativeFeatureFlagsCxxInterop::disableImageViewPreallocationAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::disableImageViewPreallocationAndroid();
Expand Down Expand Up @@ -1035,6 +1046,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"disableEarlyViewCommandExecution",
JReactNativeFeatureFlagsCxxInterop::disableEarlyViewCommandExecution),
makeNativeMethod(
"disableIdleNativeAnimatedFrameCallbackRearmAndroid",
JReactNativeFeatureFlagsCxxInterop::disableIdleNativeAnimatedFrameCallbackRearmAndroid),
makeNativeMethod(
"disableImageViewPreallocationAndroid",
JReactNativeFeatureFlagsCxxInterop::disableImageViewPreallocationAndroid),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<eab10e240a16c8ef3f659bd8ded290f0>>
* @generated SignedSource<<1976b61d204740087d85a1c782602fed>>
*/

/**
Expand Down Expand Up @@ -45,6 +45,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool disableEarlyViewCommandExecution(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool disableIdleNativeAnimatedFrameCallbackRearmAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool disableImageViewPreallocationAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<6f475a063b6427ea8166883333230d7d>>
*/

/**
Expand Down Expand Up @@ -46,6 +46,10 @@ bool ReactNativeFeatureFlags::disableEarlyViewCommandExecution() {
return getAccessor().disableEarlyViewCommandExecution();
}

bool ReactNativeFeatureFlags::disableIdleNativeAnimatedFrameCallbackRearmAndroid() {
return getAccessor().disableIdleNativeAnimatedFrameCallbackRearmAndroid();
}

bool ReactNativeFeatureFlags::disableImageViewPreallocationAndroid() {
return getAccessor().disableImageViewPreallocationAndroid();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<b41faab74fc924c5729d73abc69d4bcd>>
*/

/**
Expand Down Expand Up @@ -66,6 +66,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool disableEarlyViewCommandExecution();

/**
* Stop re-arming the NATIVE_ANIMATED_MODULE Choreographer frame callback at vsync rate while no animations are active on Android
*/
RN_EXPORT static bool disableIdleNativeAnimatedFrameCallbackRearmAndroid();

/**
* Force disable view preallocation for images triggered from createNode off the main thread on Android
*/
Expand Down
Loading
Loading