diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.kt index 4c46a1f6b24..88ef08dbc1d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.kt @@ -33,7 +33,7 @@ internal class FpsView(reactContext: ReactContext?) : FrameLayout(reactContext!! textView = findViewById(R.id.fps_text) as TextView frameCallback = FpsDebugFrameCallback(reactContext!!) fpsMonitorRunnable = FPSMonitorRunnable() - setCurrentFPS(0.0, 0.0, 0, 0) + setCurrentFPS(0.0, 0.0, 0, 0, frameCallback.isRunningOnFabric) } override fun onAttachedToWindow() { @@ -53,16 +53,21 @@ internal class FpsView(reactContext: ReactContext?) : FrameLayout(reactContext!! currentFPS: Double, currentJSFPS: Double, droppedUIFrames: Int, - total4PlusFrameStutters: Int + total4PlusFrameStutters: Int, + runningOnFabric: Boolean ) { - val fpsString = + var fpsString = String.format( Locale.US, - "UI: %.1f fps\n%d dropped so far\n%d stutters (4+) so far\nJS: %.1f fps", + "UI: %.1f fps\n%d dropped so far\n%d stutters (4+) so far", currentFPS, droppedUIFrames, - total4PlusFrameStutters, - currentJSFPS) + total4PlusFrameStutters) + if (!runningOnFabric) { + // The JS FPS is only relevant for the legacy architecture, as Fabric we don't use + // BridgeIdleDebugListener to track JS frame drops. + fpsString += String.format(Locale.US, "\nJS: %.1f fps", currentJSFPS) + } textView.text = fpsString FLog.d(ReactConstants.TAG, fpsString) } @@ -80,7 +85,11 @@ internal class FpsView(reactContext: ReactContext?) : FrameLayout(reactContext!! totalFramesDropped += frameCallback.expectedNumFrames - frameCallback.numFrames total4PlusFrameStutters += frameCallback.get4PlusFrameStutters() setCurrentFPS( - frameCallback.fps, frameCallback.jsFPS, totalFramesDropped, total4PlusFrameStutters) + frameCallback.fps, + frameCallback.jsFPS, + totalFramesDropped, + total4PlusFrameStutters, + frameCallback.isRunningOnFabric) frameCallback.reset() postDelayed(this, UPDATE_INTERVAL_MS.toLong()) } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt index 49ab4609d51..15358927df2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt @@ -65,6 +65,11 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) : val uiManagerModule = reactContext.getNativeModule(UIManagerModule::class.java) if (!reactContext.isBridgeless) { reactContext.catalystInstance.addBridgeIdleDebugListener(didJSUpdateUiDuringFrameDetector) + isRunningOnFabric = false + } else { + // T172641976 Consider either implementing a mechanism similar to addBridgeIdleDebugListener + // for Fabric or point users to use RNDT. + isRunningOnFabric = true } uiManagerModule?.setViewHierarchyUpdateDebugListener(didJSUpdateUiDuringFrameDetector) } @@ -97,6 +102,10 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) : 0.0 } else numFrames.toDouble() * 1e9 / (lastFrameTime - firstFrameTime) + /** + * Please note that this value is not relevant if running on Fabric. That's because we don't + * implement addBridgeIdleDebugListener on Fabric. + */ val jsFPS: Double get() = if (lastFrameTime == firstFrameTime) { @@ -115,6 +124,9 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) : return (targetFps * totalTimeMS / 1000 + 1).toInt() } + var isRunningOnFabric = true + private set + fun get4PlusFrameStutters(): Int = fourPlusFrameStutters private val totalTimeMS: Int