Skip to content

Commit 26ff069

Browse files
hoxyqmeta-codesync[bot]
authored andcommitted
Propagate Frames data through Host (facebook#54671)
Summary: Pull Request resolved: facebook#54671 # Changelog: [Internal] Replaces the calls to `PerformanceTracer` through `jni` with the calls through inpsector's `HostTarget`. Reviewed By: sbuggay Differential Revision: D87373808 fbshipit-source-id: f86a679a09b1586a426e69914de2c9f658289039
1 parent 587d360 commit 26ff069

File tree

6 files changed

+101
-16
lines changed

6 files changed

+101
-16
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.devsupport.inspector
9+
10+
internal data class FrameTimingSequence(
11+
val id: Int,
12+
val threadId: Int,
13+
val beginDrawingTimestamp: Long,
14+
val commitTimestamp: Long,
15+
val endDrawingTimestamp: Long,
16+
)

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,42 @@ package com.facebook.react.devsupport.inspector
1010
import android.os.Build
1111
import android.os.Handler
1212
import android.os.Looper
13+
import android.os.Process
1314
import android.view.FrameMetrics
1415
import android.view.Window
1516
import com.facebook.proguard.annotations.DoNotStripAny
1617
import com.facebook.soloader.SoLoader
1718

1819
@DoNotStripAny
19-
internal class FrameTimingsObserver(private val window: Window) {
20+
internal class FrameTimingsObserver(
21+
private val window: Window,
22+
onFrameTimingSequence: (sequence: FrameTimingSequence) -> Unit,
23+
) {
2024
private val handler = Handler(Looper.getMainLooper())
2125
private var frameCounter: Int = 0
2226

2327
private external fun setLayerTreeId(frame: String, layerTreeId: Int)
2428

2529
private val frameMetricsListener =
26-
Window.OnFrameMetricsAvailableListener { _, frameMetrics, dropCount ->
27-
val metrics = FrameMetrics(frameMetrics)
30+
Window.OnFrameMetricsAvailableListener { _, frameMetrics, _dropCount ->
31+
val beginDrawingTimestamp = frameMetrics.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP)
32+
val commitTimestamp =
33+
beginDrawingTimestamp + frameMetrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION)
34+
+frameMetrics.getMetric(FrameMetrics.ANIMATION_DURATION)
35+
+frameMetrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION)
36+
+frameMetrics.getMetric(FrameMetrics.DRAW_DURATION)
37+
+frameMetrics.getMetric(FrameMetrics.SYNC_DURATION)
38+
val endDrawingTimestamp =
39+
beginDrawingTimestamp + frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION)
2840

29-
val paintStartTime = metrics.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP)
30-
val totalDuration = metrics.getMetric(FrameMetrics.TOTAL_DURATION)
31-
32-
val currentFrame = frameCounter++
33-
reportFrameTiming(
34-
frame = currentFrame,
35-
paintStartNanos = paintStartTime,
36-
paintEndNanos = paintStartTime + totalDuration,
41+
onFrameTimingSequence(
42+
FrameTimingSequence(
43+
frameCounter++,
44+
Process.myTid(),
45+
beginDrawingTimestamp,
46+
commitTimestamp,
47+
endDrawingTimestamp,
48+
)
3749
)
3850
}
3951

@@ -44,10 +56,6 @@ internal class FrameTimingsObserver(private val window: Window) {
4456
}
4557

4658
window.addOnFrameMetricsAvailableListener(frameMetricsListener, handler)
47-
48-
// Hardcoded frame identfier and layerTreeId. Needed for DevTools to
49-
// begin parsing frame events.
50-
setLayerTreeId("", 1)
5159
}
5260

5361
fun stop() {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1572,7 +1572,10 @@ public class ReactHostImpl(
15721572
TracingState.ENABLED_IN_BACKGROUND_MODE,
15731573
TracingState.ENABLED_IN_CDP_MODE -> {
15741574
currentActivity?.window?.let { window ->
1575-
val observer = FrameTimingsObserver(window)
1575+
val observer =
1576+
FrameTimingsObserver(window) { frameTimingsSequence ->
1577+
inspectorTarget.recordFrameTimings(frameTimingsSequence)
1578+
}
15761579
observer.start()
15771580
frameTimingsObserver = observer
15781581
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.facebook.proguard.annotations.DoNotStripAny
1212
import com.facebook.react.bridge.UiThreadUtil
1313
import com.facebook.react.common.annotations.FrameworkAPI
1414
import com.facebook.react.common.annotations.UnstableReactNativeAPI
15+
import com.facebook.react.devsupport.inspector.FrameTimingSequence
1516
import com.facebook.react.devsupport.inspector.TracingState
1617
import com.facebook.react.devsupport.inspector.TracingStateListener
1718
import com.facebook.react.devsupport.perfmonitor.PerfMonitorInspectorTarget
@@ -48,6 +49,8 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
4849

4950
external fun unregisterTracingStateListener(subscriptionId: Long)
5051

52+
external fun recordFrameTimings(frameTimingSequence: FrameTimingSequence)
53+
5154
override fun addPerfMonitorListener(listener: PerfMonitorUpdateListener) {
5255
perfMonitorListeners.add(listener)
5356
}

packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ void JReactHostInspectorTarget::registerNatives() {
253253
makeNativeMethod(
254254
"unregisterTracingStateListener",
255255
JReactHostInspectorTarget::unregisterTracingStateListener),
256+
makeNativeMethod(
257+
"recordFrameTimings", JReactHostInspectorTarget::recordFrameTimings),
256258
});
257259
}
258260

@@ -290,6 +292,17 @@ HostTargetTracingDelegate* JReactHostInspectorTarget::getTracingDelegate() {
290292
return tracingDelegate_.get();
291293
}
292294

295+
void JReactHostInspectorTarget::recordFrameTimings(
296+
jni::alias_ref<JFrameTimingSequence::javaobject> frameTimingSequence) {
297+
inspectorTarget_->recordFrameTimings({
298+
frameTimingSequence->getId(),
299+
frameTimingSequence->getThreadId(),
300+
frameTimingSequence->getBeginDrawingTimestamp(),
301+
frameTimingSequence->getCommitTimestamp(),
302+
frameTimingSequence->getEndDrawingTimestamp(),
303+
});
304+
}
305+
293306
void TracingDelegate::onTracingStarted(
294307
tracing::Mode tracingMode,
295308
bool screenshotsCategoryEnabled) {

packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,43 @@ struct JTracingStateListener : public jni::JavaClass<JTracingStateListener> {
3232
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/devsupport/inspector/TracingStateListener;";
3333
};
3434

35+
struct JFrameTimingSequence : public jni::JavaClass<JFrameTimingSequence> {
36+
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/devsupport/inspector/FrameTimingSequence;";
37+
38+
uint64_t getId() const
39+
{
40+
auto field = javaClassStatic()->getField<jint>("id");
41+
return static_cast<uint64_t>(getFieldValue(field));
42+
}
43+
44+
uint64_t getThreadId() const
45+
{
46+
auto field = javaClassStatic()->getField<jint>("threadId");
47+
return static_cast<uint64_t>(getFieldValue(field));
48+
}
49+
50+
HighResTimeStamp getBeginDrawingTimestamp() const
51+
{
52+
auto field = javaClassStatic()->getField<jlong>("beginDrawingTimestamp");
53+
return HighResTimeStamp::fromChronoSteadyClockTimePoint(
54+
std::chrono::steady_clock::time_point(std::chrono::nanoseconds(getFieldValue(field))));
55+
}
56+
57+
HighResTimeStamp getCommitTimestamp() const
58+
{
59+
auto field = javaClassStatic()->getField<jlong>("commitTimestamp");
60+
return HighResTimeStamp::fromChronoSteadyClockTimePoint(
61+
std::chrono::steady_clock::time_point(std::chrono::nanoseconds(getFieldValue(field))));
62+
}
63+
64+
HighResTimeStamp getEndDrawingTimestamp() const
65+
{
66+
auto field = javaClassStatic()->getField<jlong>("endDrawingTimestamp");
67+
return HighResTimeStamp::fromChronoSteadyClockTimePoint(
68+
std::chrono::steady_clock::time_point(std::chrono::nanoseconds(getFieldValue(field))));
69+
}
70+
};
71+
3572
struct JReactHostImpl : public jni::JavaClass<JReactHostImpl> {
3673
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/runtime/ReactHostImpl;";
3774

@@ -185,6 +222,11 @@ class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTar
185222
*/
186223
void unregisterTracingStateListener(jlong subscriptionId);
187224

225+
/**
226+
* Propagate frame timings information to the Inspector's Tracing subsystem.
227+
*/
228+
void recordFrameTimings(jni::alias_ref<JFrameTimingSequence::javaobject> frameTimingSequence);
229+
188230
// HostTargetDelegate methods
189231
jsinspector_modern::HostTargetMetadata getMetadata() override;
190232
void onReload(const PageReloadRequest &request) override;

0 commit comments

Comments
 (0)