Skip to content

Commit 37de671

Browse files
Merge pull request #603 from Instabug/feat/screen-render-local-store
screen render updates
2 parents c21725e + c1d7ff5 commit 37de671

File tree

2 files changed

+95
-75
lines changed

2 files changed

+95
-75
lines changed

android/src/main/java/com/instabug/flutter/modules/ApmApi.java

Lines changed: 74 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -110,42 +110,40 @@ public void setAutoUITraceEnabled(@NonNull Boolean isEnabled) {
110110
*/
111111
@Override
112112
public void startExecutionTrace(@NonNull String id, @NonNull String name, ApmPigeon.Result<String> result) {
113-
ThreadManager.runOnBackground(
114-
new Runnable() {
115-
@Override
116-
public void run() {
117-
try {
118-
ExecutionTrace trace = APM.startExecutionTrace(name);
119-
if (trace != null) {
120-
traces.put(id, trace);
121-
122-
ThreadManager.runOnMainThread(new Runnable() {
123-
@Override
124-
public void run() {
125-
result.success(id);
126-
}
127-
});
128-
} else {
129-
ThreadManager.runOnMainThread(new Runnable() {
130-
@Override
131-
public void run() {
132-
result.success(null);
133-
}
134-
});
113+
ThreadManager.runOnBackground(new Runnable() {
114+
@Override
115+
public void run() {
116+
try {
117+
ExecutionTrace trace = APM.startExecutionTrace(name);
118+
if (trace != null) {
119+
traces.put(id, trace);
120+
121+
ThreadManager.runOnMainThread(new Runnable() {
122+
@Override
123+
public void run() {
124+
result.success(id);
135125
}
136-
} catch (Exception e) {
137-
e.printStackTrace();
138-
139-
ThreadManager.runOnMainThread(new Runnable() {
140-
@Override
141-
public void run() {
142-
result.success(null);
143-
}
144-
});
145-
}
126+
});
127+
} else {
128+
ThreadManager.runOnMainThread(new Runnable() {
129+
@Override
130+
public void run() {
131+
result.success(null);
132+
}
133+
});
146134
}
135+
} catch (Exception e) {
136+
e.printStackTrace();
137+
138+
ThreadManager.runOnMainThread(new Runnable() {
139+
@Override
140+
public void run() {
141+
result.success(null);
142+
}
143+
});
147144
}
148-
);
145+
}
146+
});
149147
}
150148

151149
/**
@@ -356,13 +354,9 @@ public void networkLogAndroid(@NonNull Map<String, Object> data) {
356354
}
357355

358356

359-
APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes =
360-
null;
357+
APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes = null;
361358
if (isW3cHeaderFound != null) {
362-
w3cExternalTraceAttributes = new APMCPNetworkLog.W3CExternalTraceAttributes(
363-
isW3cHeaderFound, partialId == null ? null : partialId.longValue(),
364-
networkStartTimeInSeconds == null ? null : networkStartTimeInSeconds.longValue(),
365-
w3CGeneratedHeader, w3CCaughtHeader
359+
w3cExternalTraceAttributes = new APMCPNetworkLog.W3CExternalTraceAttributes(isW3cHeaderFound, partialId == null ? null : partialId.longValue(), networkStartTimeInSeconds == null ? null : networkStartTimeInSeconds.longValue(), w3CGeneratedHeader, w3CCaughtHeader
366360

367361
);
368362
}
@@ -520,49 +514,57 @@ public void deviceRefreshRate(@NonNull ApmPigeon.Result<Double> result) {
520514

521515
@Override
522516
public void endScreenRenderForAutoUiTrace(@NonNull Map<String, Object> data) {
523-
final long traceId = ((Number) data.get("traceId")).longValue();
524-
final long slowFramesTotalDuration = ((Number) data.get("slowFramesTotalDuration")).longValue();
525-
final long frozenFramesTotalDuration = ((Number) data.get("frozenFramesTotalDuration")).longValue();
526-
final long endTime = ((Number) data.get("endTime")).longValue();
527-
528-
// Don't cast directly to ArrayList<ArrayList<Long>> because the inner lists may actually be ArrayList<Integer>
529-
// Instead, cast to List<List<Number>> and convert each value to long explicitly
530-
List<List<Number>> rawFrames = (List<List<Number>>) data.get("frameData");
531-
ArrayList<IBGFrameData> frames = new ArrayList<>();
532-
if (rawFrames != null) {
533-
for (List<Number> frameValues : rawFrames) {
534-
// Defensive: check size and nulls
535-
if (frameValues != null && frameValues.size() >= 2) {
536-
long frameStart = frameValues.get(0).longValue();
537-
long frameDuration = frameValues.get(1).longValue();
538-
frames.add(new IBGFrameData(frameStart, frameDuration));
517+
try {
518+
final long traceId = ((Number) data.get("traceId")).longValue();
519+
final long slowFramesTotalDuration = ((Number) data.get("slowFramesTotalDuration")).longValue();
520+
final long frozenFramesTotalDuration = ((Number) data.get("frozenFramesTotalDuration")).longValue();
521+
final long endTime = ((Number) data.get("endTime")).longValue();
522+
523+
// Don't cast directly to ArrayList<ArrayList<Long>> because the inner lists may actually be ArrayList<Integer>
524+
// Instead, cast to List<List<Number>> and convert each value to long explicitly
525+
List<List<Number>> rawFrames = (List<List<Number>>) data.get("frameData");
526+
ArrayList<IBGFrameData> frames = new ArrayList<>();
527+
if (rawFrames != null) {
528+
for (List<Number> frameValues : rawFrames) {
529+
// Defensive: check size and nulls
530+
if (frameValues != null && frameValues.size() >= 2) {
531+
long frameStart = frameValues.get(0).longValue();
532+
long frameDuration = frameValues.get(1).longValue();
533+
frames.add(new IBGFrameData(frameStart, frameDuration));
534+
}
539535
}
540536
}
537+
IBGScreenRenderingData screenRenderingData = new IBGScreenRenderingData(traceId, slowFramesTotalDuration, frozenFramesTotalDuration, frames);
538+
InternalAPM._endAutoUiTraceWithScreenRendering(screenRenderingData, endTime);
539+
} catch (Exception e) {
540+
e.printStackTrace();
541541
}
542-
IBGScreenRenderingData screenRenderingData = new IBGScreenRenderingData(traceId, slowFramesTotalDuration, frozenFramesTotalDuration, frames);
543-
InternalAPM._endAutoUiTraceWithScreenRendering(screenRenderingData, endTime);
544542
}
545543

546544
@Override
547545
public void endScreenRenderForCustomUiTrace(@NonNull Map<String, Object> data) {
548-
final long traceId = ((Number) data.get("traceId")).longValue();
549-
final long slowFramesTotalDuration = ((Number) data.get("slowFramesTotalDuration")).longValue();
550-
final long frozenFramesTotalDuration = ((Number) data.get("frozenFramesTotalDuration")).longValue();
551-
552-
List<List<Number>> rawFrames = (List<List<Number>>) data.get("frameData");
553-
ArrayList<IBGFrameData> frames = new ArrayList<>();
554-
if (rawFrames != null) {
555-
for (List<Number> frameValues : rawFrames) {
556-
// Defensive: check size and nulls
557-
if (frameValues != null && frameValues.size() >= 2) {
558-
long frameStart = frameValues.get(0).longValue();
559-
long frameDuration = frameValues.get(1).longValue();
560-
frames.add(new IBGFrameData(frameStart, frameDuration));
546+
try {
547+
final long traceId = ((Number) data.get("traceId")).longValue();
548+
final long slowFramesTotalDuration = ((Number) data.get("slowFramesTotalDuration")).longValue();
549+
final long frozenFramesTotalDuration = ((Number) data.get("frozenFramesTotalDuration")).longValue();
550+
551+
List<List<Number>> rawFrames = (List<List<Number>>) data.get("frameData");
552+
ArrayList<IBGFrameData> frames = new ArrayList<>();
553+
if (rawFrames != null) {
554+
for (List<Number> frameValues : rawFrames) {
555+
// Defensive: check size and nulls
556+
if (frameValues != null && frameValues.size() >= 2) {
557+
long frameStart = frameValues.get(0).longValue();
558+
long frameDuration = frameValues.get(1).longValue();
559+
frames.add(new IBGFrameData(frameStart, frameDuration));
560+
}
561561
}
562562
}
563+
IBGScreenRenderingData screenRenderingData = new IBGScreenRenderingData(traceId, slowFramesTotalDuration, frozenFramesTotalDuration, frames);
564+
InternalAPM._endCustomUiTraceWithScreenRenderingCP(screenRenderingData);
565+
} catch (Exception e) {
566+
e.printStackTrace();
563567
}
564-
IBGScreenRenderingData screenRenderingData = new IBGScreenRenderingData(traceId, slowFramesTotalDuration, frozenFramesTotalDuration, frames);
565-
InternalAPM._endCustomUiTraceWithScreenRenderingCP(screenRenderingData);
566568
}
567569

568570
}

lib/src/utils/screen_rendering/instabug_screen_render_manager.dart

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class InstabugScreenRenderManager {
2828
int _frozenFramesTotalDurationMs = 0;
2929
bool _isTimingsListenerAttached = false;
3030
bool screenRenderEnabled = false;
31+
int? _epochOffset;
3132

3233
final List<InstabugFrameData> _delayedFrames = [];
3334

@@ -95,17 +96,23 @@ class InstabugScreenRenderManager {
9596

9697
if (_isUiDelayed) {
9798
_onDelayedFrameDetected(
98-
frameTiming.timestampInMicroseconds(FramePhase.buildStart),
99+
_getMicrosecondsSinceEpoch(
100+
frameTiming.timestampInMicroseconds(FramePhase.buildStart),
101+
),
99102
_buildTime,
100103
);
101104
} else if (_isRasterDelayed) {
102105
_onDelayedFrameDetected(
103-
frameTiming.timestampInMicroseconds(FramePhase.rasterStart),
106+
_getMicrosecondsSinceEpoch(
107+
frameTiming.timestampInMicroseconds(FramePhase.rasterStart),
108+
),
104109
_rasterTime,
105110
);
106111
} else if (_isTotalTimeLarge) {
107112
_onDelayedFrameDetected(
108-
frameTiming.timestampInMicroseconds(FramePhase.vsyncStart),
113+
_getMicrosecondsSinceEpoch(
114+
frameTiming.timestampInMicroseconds(FramePhase.vsyncStart),
115+
),
109116
_totalTime,
110117
);
111118
}
@@ -243,6 +250,9 @@ class InstabugScreenRenderManager {
243250
/// Initialize the static variables
244251
Future<void> _initStaticValues() async {
245252
_timingsCallback = (timings) {
253+
// 1. Establish the offset on the first available timing.
254+
_epochOffset ??= _getEpochOffset(timings.first);
255+
246256
for (final frameTiming in timings) {
247257
analyzeFrameTiming(frameTiming);
248258
}
@@ -253,6 +263,11 @@ class InstabugScreenRenderManager {
253263
_screenRenderForCustomUiTrace = InstabugScreenRenderData(frameData: []);
254264
}
255265

266+
int _getEpochOffset(FrameTiming firstPatchedFrameTiming) {
267+
return DateTime.now().microsecondsSinceEpoch -
268+
firstPatchedFrameTiming.timestampInMicroseconds(FramePhase.vsyncStart);
269+
}
270+
256271
/// Add a frame observer by calling [WidgetsBinding.instance.addTimingsCallback]
257272
void _initFrameTimings() {
258273
if (_isTimingsListenerAttached) {
@@ -369,6 +384,9 @@ class InstabugScreenRenderManager {
369384
);
370385
}
371386

387+
int _getMicrosecondsSinceEpoch(int timeInMicroseconds) =>
388+
timeInMicroseconds + (_epochOffset ?? 0);
389+
372390
/// --------------------------- testing helper methods ---------------------
373391
374392
@visibleForTesting

0 commit comments

Comments
 (0)