1*90c8c64dSAndroid Build Coastguard Worker/* 2*90c8c64dSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project 3*90c8c64dSAndroid Build Coastguard Worker * 4*90c8c64dSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*90c8c64dSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*90c8c64dSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*90c8c64dSAndroid Build Coastguard Worker * 8*90c8c64dSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*90c8c64dSAndroid Build Coastguard Worker * 10*90c8c64dSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*90c8c64dSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*90c8c64dSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*90c8c64dSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*90c8c64dSAndroid Build Coastguard Worker * limitations under the License. 15*90c8c64dSAndroid Build Coastguard Worker */ 16*90c8c64dSAndroid Build Coastguard Worker 17*90c8c64dSAndroid Build Coastguard Workerimport {assertDefined} from 'common/assert_utils'; 18*90c8c64dSAndroid Build Coastguard Workerimport {CustomQueryType} from './custom_query'; 19*90c8c64dSAndroid Build Coastguard Workerimport {FrameMapBuilder} from './frame_map_builder'; 20*90c8c64dSAndroid Build Coastguard Workerimport {FramesRange, Trace, TraceEntry} from './trace'; 21*90c8c64dSAndroid Build Coastguard Workerimport {Traces} from './traces'; 22*90c8c64dSAndroid Build Coastguard Workerimport {TraceType} from './trace_type'; 23*90c8c64dSAndroid Build Coastguard Worker 24*90c8c64dSAndroid Build Coastguard Workerexport class FrameMapper { 25*90c8c64dSAndroid Build Coastguard Worker // Value used to narrow time-based searches of corresponding trace entries 26*90c8c64dSAndroid Build Coastguard Worker private static readonly MAX_UI_PIPELINE_LATENCY_NS = 2000000000n; // 2 seconds 27*90c8c64dSAndroid Build Coastguard Worker 28*90c8c64dSAndroid Build Coastguard Worker constructor(private traces: Traces) {} 29*90c8c64dSAndroid Build Coastguard Worker 30*90c8c64dSAndroid Build Coastguard Worker async computeMapping() { 31*90c8c64dSAndroid Build Coastguard Worker this.pickMostReliableTraceAndSetInitialFrameInfo(); 32*90c8c64dSAndroid Build Coastguard Worker await this.propagateFrameInfoToOtherTraces(); 33*90c8c64dSAndroid Build Coastguard Worker } 34*90c8c64dSAndroid Build Coastguard Worker 35*90c8c64dSAndroid Build Coastguard Worker private pickMostReliableTraceAndSetInitialFrameInfo() { 36*90c8c64dSAndroid Build Coastguard Worker const TRACES_IN_PREFERENCE_ORDER = [ 37*90c8c64dSAndroid Build Coastguard Worker TraceType.SCREEN_RECORDING, 38*90c8c64dSAndroid Build Coastguard Worker TraceType.SURFACE_FLINGER, 39*90c8c64dSAndroid Build Coastguard Worker TraceType.WINDOW_MANAGER, 40*90c8c64dSAndroid Build Coastguard Worker ]; 41*90c8c64dSAndroid Build Coastguard Worker 42*90c8c64dSAndroid Build Coastguard Worker const type = TRACES_IN_PREFERENCE_ORDER.find( 43*90c8c64dSAndroid Build Coastguard Worker (type) => this.traces.getTrace(type) !== undefined, 44*90c8c64dSAndroid Build Coastguard Worker ); 45*90c8c64dSAndroid Build Coastguard Worker if (type === undefined) { 46*90c8c64dSAndroid Build Coastguard Worker return; 47*90c8c64dSAndroid Build Coastguard Worker } 48*90c8c64dSAndroid Build Coastguard Worker 49*90c8c64dSAndroid Build Coastguard Worker const trace = assertDefined(this.traces.getTrace(type)); 50*90c8c64dSAndroid Build Coastguard Worker const frameMapBuilder = new FrameMapBuilder( 51*90c8c64dSAndroid Build Coastguard Worker trace.lengthEntries, 52*90c8c64dSAndroid Build Coastguard Worker trace.lengthEntries, 53*90c8c64dSAndroid Build Coastguard Worker ); 54*90c8c64dSAndroid Build Coastguard Worker 55*90c8c64dSAndroid Build Coastguard Worker for (let i = 0; i < trace.lengthEntries; ++i) { 56*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames(i, {start: i, end: i + 1}); 57*90c8c64dSAndroid Build Coastguard Worker } 58*90c8c64dSAndroid Build Coastguard Worker 59*90c8c64dSAndroid Build Coastguard Worker const frameMap = frameMapBuilder.build(); 60*90c8c64dSAndroid Build Coastguard Worker trace.setFrameInfo(frameMap, frameMap.getFullTraceFramesRange()); 61*90c8c64dSAndroid Build Coastguard Worker } 62*90c8c64dSAndroid Build Coastguard Worker 63*90c8c64dSAndroid Build Coastguard Worker private async propagateFrameInfoToOtherTraces() { 64*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 65*90c8c64dSAndroid Build Coastguard Worker TraceType.SCREEN_RECORDING, 66*90c8c64dSAndroid Build Coastguard Worker TraceType.SURFACE_FLINGER, 67*90c8c64dSAndroid Build Coastguard Worker this.propagateFromScreenRecordingToSurfaceFlinger, 68*90c8c64dSAndroid Build Coastguard Worker ); 69*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 70*90c8c64dSAndroid Build Coastguard Worker TraceType.SURFACE_FLINGER, 71*90c8c64dSAndroid Build Coastguard Worker TraceType.TRANSACTIONS, 72*90c8c64dSAndroid Build Coastguard Worker this.propagateFromSurfaceFlingerToTraceWithVsyncIds, 73*90c8c64dSAndroid Build Coastguard Worker ); 74*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 75*90c8c64dSAndroid Build Coastguard Worker TraceType.SURFACE_FLINGER, 76*90c8c64dSAndroid Build Coastguard Worker TraceType.VIEW_CAPTURE, 77*90c8c64dSAndroid Build Coastguard Worker this.propagateFromSurfaceFlingerToViewCapture, 78*90c8c64dSAndroid Build Coastguard Worker ); 79*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 80*90c8c64dSAndroid Build Coastguard Worker TraceType.SURFACE_FLINGER, 81*90c8c64dSAndroid Build Coastguard Worker TraceType.INPUT_EVENT_MERGED, 82*90c8c64dSAndroid Build Coastguard Worker this.propagateFromSurfaceFlingerToTraceWithVsyncIds, 83*90c8c64dSAndroid Build Coastguard Worker ); 84*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 85*90c8c64dSAndroid Build Coastguard Worker TraceType.TRANSACTIONS, 86*90c8c64dSAndroid Build Coastguard Worker TraceType.WINDOW_MANAGER, 87*90c8c64dSAndroid Build Coastguard Worker this.propagateFromTransactionsToWindowManager, 88*90c8c64dSAndroid Build Coastguard Worker ); 89*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 90*90c8c64dSAndroid Build Coastguard Worker TraceType.WINDOW_MANAGER, 91*90c8c64dSAndroid Build Coastguard Worker TraceType.PROTO_LOG, 92*90c8c64dSAndroid Build Coastguard Worker this.propagateFromWindowManagerToProtoLog, 93*90c8c64dSAndroid Build Coastguard Worker ); 94*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 95*90c8c64dSAndroid Build Coastguard Worker TraceType.WINDOW_MANAGER, 96*90c8c64dSAndroid Build Coastguard Worker TraceType.INPUT_METHOD_CLIENTS, 97*90c8c64dSAndroid Build Coastguard Worker this.propagateFromWindowManagerToIme, 98*90c8c64dSAndroid Build Coastguard Worker ); 99*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 100*90c8c64dSAndroid Build Coastguard Worker TraceType.WINDOW_MANAGER, 101*90c8c64dSAndroid Build Coastguard Worker TraceType.INPUT_METHOD_MANAGER_SERVICE, 102*90c8c64dSAndroid Build Coastguard Worker this.propagateFromWindowManagerToIme, 103*90c8c64dSAndroid Build Coastguard Worker ); 104*90c8c64dSAndroid Build Coastguard Worker await this.tryPropagateMapping( 105*90c8c64dSAndroid Build Coastguard Worker TraceType.WINDOW_MANAGER, 106*90c8c64dSAndroid Build Coastguard Worker TraceType.INPUT_METHOD_SERVICE, 107*90c8c64dSAndroid Build Coastguard Worker this.propagateFromWindowManagerToIme, 108*90c8c64dSAndroid Build Coastguard Worker ); 109*90c8c64dSAndroid Build Coastguard Worker } 110*90c8c64dSAndroid Build Coastguard Worker 111*90c8c64dSAndroid Build Coastguard Worker private async propagateFromScreenRecordingToSurfaceFlinger( 112*90c8c64dSAndroid Build Coastguard Worker screenRecording: Trace<object>, 113*90c8c64dSAndroid Build Coastguard Worker surfaceFlinger: Trace<object>, 114*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder: FrameMapBuilder, 115*90c8c64dSAndroid Build Coastguard Worker ) { 116*90c8c64dSAndroid Build Coastguard Worker screenRecording.forEachEntry((srcEntry) => { 117*90c8c64dSAndroid Build Coastguard Worker const startSearchTime = srcEntry 118*90c8c64dSAndroid Build Coastguard Worker .getTimestamp() 119*90c8c64dSAndroid Build Coastguard Worker .add(-FrameMapper.MAX_UI_PIPELINE_LATENCY_NS); 120*90c8c64dSAndroid Build Coastguard Worker const endSearchTime = srcEntry.getTimestamp(); 121*90c8c64dSAndroid Build Coastguard Worker const matches = surfaceFlinger.sliceTime(startSearchTime, endSearchTime); 122*90c8c64dSAndroid Build Coastguard Worker if (matches.lengthEntries > 0) { 123*90c8c64dSAndroid Build Coastguard Worker const dstEntry = matches.getEntry(matches.lengthEntries - 1); 124*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames( 125*90c8c64dSAndroid Build Coastguard Worker dstEntry.getIndex(), 126*90c8c64dSAndroid Build Coastguard Worker srcEntry.getFramesRange(), 127*90c8c64dSAndroid Build Coastguard Worker ); 128*90c8c64dSAndroid Build Coastguard Worker } 129*90c8c64dSAndroid Build Coastguard Worker }); 130*90c8c64dSAndroid Build Coastguard Worker } 131*90c8c64dSAndroid Build Coastguard Worker 132*90c8c64dSAndroid Build Coastguard Worker private async propagateFromSurfaceFlingerToTraceWithVsyncIds( 133*90c8c64dSAndroid Build Coastguard Worker surfaceFlinger: Trace<object>, 134*90c8c64dSAndroid Build Coastguard Worker traceWithVsyncIds: Trace<object>, 135*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder: FrameMapBuilder, 136*90c8c64dSAndroid Build Coastguard Worker ) { 137*90c8c64dSAndroid Build Coastguard Worker const entries = await traceWithVsyncIds.customQuery( 138*90c8c64dSAndroid Build Coastguard Worker CustomQueryType.VSYNCID, 139*90c8c64dSAndroid Build Coastguard Worker ); 140*90c8c64dSAndroid Build Coastguard Worker 141*90c8c64dSAndroid Build Coastguard Worker const surfaceFlingerEntries = await surfaceFlinger.customQuery( 142*90c8c64dSAndroid Build Coastguard Worker CustomQueryType.VSYNCID, 143*90c8c64dSAndroid Build Coastguard Worker ); 144*90c8c64dSAndroid Build Coastguard Worker 145*90c8c64dSAndroid Build Coastguard Worker const vsyncIdToFrames = new Map<bigint, FramesRange>(); 146*90c8c64dSAndroid Build Coastguard Worker 147*90c8c64dSAndroid Build Coastguard Worker surfaceFlingerEntries.forEach((srcEntry) => { 148*90c8c64dSAndroid Build Coastguard Worker const vsyncId = srcEntry.getValue(); 149*90c8c64dSAndroid Build Coastguard Worker const srcFrames = srcEntry.getFramesRange(); 150*90c8c64dSAndroid Build Coastguard Worker if (!srcFrames) { 151*90c8c64dSAndroid Build Coastguard Worker return; 152*90c8c64dSAndroid Build Coastguard Worker } 153*90c8c64dSAndroid Build Coastguard Worker let frames = vsyncIdToFrames.get(vsyncId); 154*90c8c64dSAndroid Build Coastguard Worker if (!frames) { 155*90c8c64dSAndroid Build Coastguard Worker frames = {start: Number.MAX_VALUE, end: Number.MIN_VALUE}; 156*90c8c64dSAndroid Build Coastguard Worker } 157*90c8c64dSAndroid Build Coastguard Worker frames.start = Math.min(frames.start, srcFrames.start); 158*90c8c64dSAndroid Build Coastguard Worker frames.end = Math.max(frames.end, srcFrames.end); 159*90c8c64dSAndroid Build Coastguard Worker vsyncIdToFrames.set(vsyncId, frames); 160*90c8c64dSAndroid Build Coastguard Worker }); 161*90c8c64dSAndroid Build Coastguard Worker 162*90c8c64dSAndroid Build Coastguard Worker entries.forEach((dstEntry) => { 163*90c8c64dSAndroid Build Coastguard Worker const vsyncId = dstEntry.getValue(); 164*90c8c64dSAndroid Build Coastguard Worker const frames = vsyncIdToFrames.get(vsyncId); 165*90c8c64dSAndroid Build Coastguard Worker if (frames === undefined) { 166*90c8c64dSAndroid Build Coastguard Worker return; 167*90c8c64dSAndroid Build Coastguard Worker } 168*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames(dstEntry.getIndex(), frames); 169*90c8c64dSAndroid Build Coastguard Worker }); 170*90c8c64dSAndroid Build Coastguard Worker } 171*90c8c64dSAndroid Build Coastguard Worker 172*90c8c64dSAndroid Build Coastguard Worker private async propagateFromSurfaceFlingerToViewCapture( 173*90c8c64dSAndroid Build Coastguard Worker surfaceFlinger: Trace<object>, 174*90c8c64dSAndroid Build Coastguard Worker viewCapture: Trace<object>, 175*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder: FrameMapBuilder, 176*90c8c64dSAndroid Build Coastguard Worker ) { 177*90c8c64dSAndroid Build Coastguard Worker surfaceFlinger.forEachEntry((srcEntry) => { 178*90c8c64dSAndroid Build Coastguard Worker const dstEntry = viewCapture.findLastLowerEntry(srcEntry.getTimestamp()); 179*90c8c64dSAndroid Build Coastguard Worker if (!dstEntry) { 180*90c8c64dSAndroid Build Coastguard Worker return; 181*90c8c64dSAndroid Build Coastguard Worker } 182*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames(dstEntry.getIndex(), srcEntry.getFramesRange()); 183*90c8c64dSAndroid Build Coastguard Worker }); 184*90c8c64dSAndroid Build Coastguard Worker } 185*90c8c64dSAndroid Build Coastguard Worker 186*90c8c64dSAndroid Build Coastguard Worker private async propagateFromTransactionsToWindowManager( 187*90c8c64dSAndroid Build Coastguard Worker transactions: Trace<object>, 188*90c8c64dSAndroid Build Coastguard Worker windowManager: Trace<object>, 189*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder: FrameMapBuilder, 190*90c8c64dSAndroid Build Coastguard Worker ) { 191*90c8c64dSAndroid Build Coastguard Worker let prevWindowManagerEntry: TraceEntry<object> | undefined; 192*90c8c64dSAndroid Build Coastguard Worker windowManager.forEachEntry((windowManagerEntry) => { 193*90c8c64dSAndroid Build Coastguard Worker if (prevWindowManagerEntry) { 194*90c8c64dSAndroid Build Coastguard Worker const matches = transactions.sliceTime( 195*90c8c64dSAndroid Build Coastguard Worker prevWindowManagerEntry.getTimestamp(), 196*90c8c64dSAndroid Build Coastguard Worker windowManagerEntry.getTimestamp(), 197*90c8c64dSAndroid Build Coastguard Worker ); 198*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames( 199*90c8c64dSAndroid Build Coastguard Worker prevWindowManagerEntry.getIndex(), 200*90c8c64dSAndroid Build Coastguard Worker matches.getFramesRange(), 201*90c8c64dSAndroid Build Coastguard Worker ); 202*90c8c64dSAndroid Build Coastguard Worker } 203*90c8c64dSAndroid Build Coastguard Worker prevWindowManagerEntry = windowManagerEntry; 204*90c8c64dSAndroid Build Coastguard Worker }); 205*90c8c64dSAndroid Build Coastguard Worker 206*90c8c64dSAndroid Build Coastguard Worker if (windowManager.lengthEntries > 0) { 207*90c8c64dSAndroid Build Coastguard Worker const lastWindowManagerEntry = windowManager.getEntry(-1); 208*90c8c64dSAndroid Build Coastguard Worker const startSearchTime = lastWindowManagerEntry.getTimestamp(); 209*90c8c64dSAndroid Build Coastguard Worker const endSearchTime = startSearchTime.add( 210*90c8c64dSAndroid Build Coastguard Worker FrameMapper.MAX_UI_PIPELINE_LATENCY_NS, 211*90c8c64dSAndroid Build Coastguard Worker ); 212*90c8c64dSAndroid Build Coastguard Worker const matches = transactions.sliceTime(startSearchTime, endSearchTime); 213*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames( 214*90c8c64dSAndroid Build Coastguard Worker lastWindowManagerEntry.getIndex(), 215*90c8c64dSAndroid Build Coastguard Worker matches.getFramesRange(), 216*90c8c64dSAndroid Build Coastguard Worker ); 217*90c8c64dSAndroid Build Coastguard Worker } 218*90c8c64dSAndroid Build Coastguard Worker } 219*90c8c64dSAndroid Build Coastguard Worker 220*90c8c64dSAndroid Build Coastguard Worker private async propagateFromWindowManagerToProtoLog( 221*90c8c64dSAndroid Build Coastguard Worker windowManager: Trace<object>, 222*90c8c64dSAndroid Build Coastguard Worker protoLog: Trace<object>, 223*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder: FrameMapBuilder, 224*90c8c64dSAndroid Build Coastguard Worker ) { 225*90c8c64dSAndroid Build Coastguard Worker windowManager.forEachEntry((prevSrcEntry) => { 226*90c8c64dSAndroid Build Coastguard Worker const srcEntryIndex = prevSrcEntry.getIndex() + 1; 227*90c8c64dSAndroid Build Coastguard Worker const srcEntry = 228*90c8c64dSAndroid Build Coastguard Worker srcEntryIndex < windowManager.lengthEntries 229*90c8c64dSAndroid Build Coastguard Worker ? windowManager.getEntry(srcEntryIndex) 230*90c8c64dSAndroid Build Coastguard Worker : undefined; 231*90c8c64dSAndroid Build Coastguard Worker if (srcEntry === undefined) { 232*90c8c64dSAndroid Build Coastguard Worker return; 233*90c8c64dSAndroid Build Coastguard Worker } 234*90c8c64dSAndroid Build Coastguard Worker const startSearchTime = prevSrcEntry.getTimestamp().add(1n); 235*90c8c64dSAndroid Build Coastguard Worker const endSearchTime = srcEntry.getTimestamp().add(1n); 236*90c8c64dSAndroid Build Coastguard Worker const matches = protoLog.sliceTime(startSearchTime, endSearchTime); 237*90c8c64dSAndroid Build Coastguard Worker matches.forEachEntry((dstEntry) => { 238*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames( 239*90c8c64dSAndroid Build Coastguard Worker dstEntry.getIndex(), 240*90c8c64dSAndroid Build Coastguard Worker srcEntry.getFramesRange(), 241*90c8c64dSAndroid Build Coastguard Worker ); 242*90c8c64dSAndroid Build Coastguard Worker }); 243*90c8c64dSAndroid Build Coastguard Worker }); 244*90c8c64dSAndroid Build Coastguard Worker 245*90c8c64dSAndroid Build Coastguard Worker if (windowManager.lengthEntries > 0) { 246*90c8c64dSAndroid Build Coastguard Worker const firstEntry = windowManager.getEntry(0); 247*90c8c64dSAndroid Build Coastguard Worker const startSearchTime = firstEntry 248*90c8c64dSAndroid Build Coastguard Worker .getTimestamp() 249*90c8c64dSAndroid Build Coastguard Worker .add(-FrameMapper.MAX_UI_PIPELINE_LATENCY_NS); 250*90c8c64dSAndroid Build Coastguard Worker const endSearchTime = firstEntry.getTimestamp().add(1n); 251*90c8c64dSAndroid Build Coastguard Worker const matches = protoLog.sliceTime(startSearchTime, endSearchTime); 252*90c8c64dSAndroid Build Coastguard Worker matches.forEachEntry((dstEntry) => { 253*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames( 254*90c8c64dSAndroid Build Coastguard Worker dstEntry.getIndex(), 255*90c8c64dSAndroid Build Coastguard Worker firstEntry.getFramesRange(), 256*90c8c64dSAndroid Build Coastguard Worker ); 257*90c8c64dSAndroid Build Coastguard Worker }); 258*90c8c64dSAndroid Build Coastguard Worker } 259*90c8c64dSAndroid Build Coastguard Worker } 260*90c8c64dSAndroid Build Coastguard Worker 261*90c8c64dSAndroid Build Coastguard Worker private async propagateFromWindowManagerToIme( 262*90c8c64dSAndroid Build Coastguard Worker windowManager: Trace<object>, 263*90c8c64dSAndroid Build Coastguard Worker ime: Trace<object>, 264*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder: FrameMapBuilder, 265*90c8c64dSAndroid Build Coastguard Worker ) { 266*90c8c64dSAndroid Build Coastguard Worker // Value used to narrow time-based searches of corresponding WindowManager entries 267*90c8c64dSAndroid Build Coastguard Worker const MAX_TIME_DIFFERENCE_NS = 200000000n; // 200 ms 268*90c8c64dSAndroid Build Coastguard Worker 269*90c8c64dSAndroid Build Coastguard Worker const abs = (n: bigint): bigint => (n < 0n ? -n : n); 270*90c8c64dSAndroid Build Coastguard Worker 271*90c8c64dSAndroid Build Coastguard Worker ime.forEachEntry((dstEntry) => { 272*90c8c64dSAndroid Build Coastguard Worker const srcEntry = windowManager.findClosestEntry(dstEntry.getTimestamp()); 273*90c8c64dSAndroid Build Coastguard Worker if (!srcEntry) { 274*90c8c64dSAndroid Build Coastguard Worker return; 275*90c8c64dSAndroid Build Coastguard Worker } 276*90c8c64dSAndroid Build Coastguard Worker const timeDifferenceNs = abs( 277*90c8c64dSAndroid Build Coastguard Worker srcEntry.getTimestamp().getValueNs() - 278*90c8c64dSAndroid Build Coastguard Worker dstEntry.getTimestamp().getValueNs(), 279*90c8c64dSAndroid Build Coastguard Worker ); 280*90c8c64dSAndroid Build Coastguard Worker if (timeDifferenceNs > MAX_TIME_DIFFERENCE_NS) { 281*90c8c64dSAndroid Build Coastguard Worker return; 282*90c8c64dSAndroid Build Coastguard Worker } 283*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder.setFrames(dstEntry.getIndex(), srcEntry.getFramesRange()); 284*90c8c64dSAndroid Build Coastguard Worker }); 285*90c8c64dSAndroid Build Coastguard Worker } 286*90c8c64dSAndroid Build Coastguard Worker 287*90c8c64dSAndroid Build Coastguard Worker private async tryPropagateMapping( 288*90c8c64dSAndroid Build Coastguard Worker srcTraceType: TraceType, 289*90c8c64dSAndroid Build Coastguard Worker dstTraceType: TraceType, 290*90c8c64dSAndroid Build Coastguard Worker mappingLogic: ( 291*90c8c64dSAndroid Build Coastguard Worker srcTrace: Trace<{}>, 292*90c8c64dSAndroid Build Coastguard Worker dstTrace: Trace<{}>, 293*90c8c64dSAndroid Build Coastguard Worker frameMapBuilder: FrameMapBuilder, 294*90c8c64dSAndroid Build Coastguard Worker ) => Promise<void>, 295*90c8c64dSAndroid Build Coastguard Worker ) { 296*90c8c64dSAndroid Build Coastguard Worker const srcTrace = this.traces.getTrace(srcTraceType); 297*90c8c64dSAndroid Build Coastguard Worker if (!srcTrace || !srcTrace.hasFrameInfo()) { 298*90c8c64dSAndroid Build Coastguard Worker return; 299*90c8c64dSAndroid Build Coastguard Worker } 300*90c8c64dSAndroid Build Coastguard Worker 301*90c8c64dSAndroid Build Coastguard Worker const promises = this.traces 302*90c8c64dSAndroid Build Coastguard Worker .getTraces(dstTraceType) 303*90c8c64dSAndroid Build Coastguard Worker .map(async (dstTrace) => { 304*90c8c64dSAndroid Build Coastguard Worker const framesRange = srcTrace.getFramesRange(); 305*90c8c64dSAndroid Build Coastguard Worker const lengthFrames = framesRange ? framesRange.end : 0; 306*90c8c64dSAndroid Build Coastguard Worker const frameMapBuilder = new FrameMapBuilder( 307*90c8c64dSAndroid Build Coastguard Worker dstTrace.lengthEntries, 308*90c8c64dSAndroid Build Coastguard Worker lengthFrames, 309*90c8c64dSAndroid Build Coastguard Worker ); 310*90c8c64dSAndroid Build Coastguard Worker 311*90c8c64dSAndroid Build Coastguard Worker await mappingLogic(srcTrace, dstTrace, frameMapBuilder); 312*90c8c64dSAndroid Build Coastguard Worker 313*90c8c64dSAndroid Build Coastguard Worker const frameMap = frameMapBuilder.build(); 314*90c8c64dSAndroid Build Coastguard Worker dstTrace.setFrameInfo(frameMap, frameMap.getFullTraceFramesRange()); 315*90c8c64dSAndroid Build Coastguard Worker }); 316*90c8c64dSAndroid Build Coastguard Worker 317*90c8c64dSAndroid Build Coastguard Worker await Promise.all(promises); 318*90c8c64dSAndroid Build Coastguard Worker } 319*90c8c64dSAndroid Build Coastguard Worker} 320