diff --git a/tools/winscope-ng/src/parsers/parser.ts b/tools/winscope-ng/src/parsers/parser.ts index ff683a138..9614a2dae 100644 --- a/tools/winscope-ng/src/parsers/parser.ts +++ b/tools/winscope-ng/src/parsers/parser.ts @@ -41,7 +41,7 @@ abstract class Parser { let areTimestampsValid = true; for (const entry of this.decodedEntries) { - const timestamp = this.getTimestamp(entry, type); + const timestamp = this.getTimestamp(type, entry); if (timestamp === undefined) { areTimestampsValid = false; break; @@ -82,8 +82,7 @@ abstract class Parser { protected abstract getMagicNumber(): undefined|number[]; protected abstract decodeTrace(trace: Uint8Array): any[]; - //TODO: invert parameters below - protected abstract getTimestamp(decodedEntry: any, type: TimestampType): undefined|Timestamp; + protected abstract getTimestamp(type: TimestampType, decodedEntry: any): undefined|Timestamp; protected abstract processDecodedEntry(decodedEntry: any): any; protected trace: Blob; diff --git a/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts b/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts index 5b486bb23..5965cd5ed 100644 --- a/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_accessibility.spec.ts @@ -16,34 +16,72 @@ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; import {Parser} from "./parser"; -import {ParserFactory} from "./parser_factory"; import {UnitTestUtils} from "test/unit/utils"; describe("ParserAccessibility", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - parser = await UnitTestUtils.getParser("traces/Accessibility.pb"); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/Accessibility.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.ACCESSIBILITY); + }); + + it("provides elapsed timestamps", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 14499089524n), + new Timestamp(TimestampType.ELAPSED, 14499599656n), + new Timestamp(TimestampType.ELAPSED, 14953120693n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) + .toEqual(expected); + }); + + it("provides real timestamps", () => { + const expected = [ + new Timestamp(TimestampType.REAL, 1659107089100052652n), + new Timestamp(TimestampType.REAL, 1659107089100562784n), + new Timestamp(TimestampType.REAL, 1659107089554083821n), + ]; + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) + .toEqual(expected); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 14499599656n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(14499599656n); + }); + + it("retrieves trace entry from real timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107089100562784n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(14499599656n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.ACCESSIBILITY); - }); + describe("trace with elapsed (only) timestamp", () => { + let parser: Parser; - it("provides elapsed timestamps", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 850297444302n), - new Timestamp(TimestampType.ELAPSED, 850297882046n), - new Timestamp(TimestampType.ELAPSED, 850756176154n), - new Timestamp(TimestampType.ELAPSED, 850773581835n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); - }); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/Accessibility.pb"); + }); - it("retrieves trace entry from elapsed timestamp", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850297444302n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(850297444302n); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.ACCESSIBILITY); + }); + + it("provides elapsed timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) + .toEqual(new Timestamp(TimestampType.ELAPSED, 850297444302n)); + }); + + it("doesn't provide real timestamps", () => { + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual(undefined); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_accessibility.ts b/tools/winscope-ng/src/parsers/parser_accessibility.ts index 0ed7caa4f..2dd8747a3 100644 --- a/tools/winscope-ng/src/parsers/parser_accessibility.ts +++ b/tools/winscope-ng/src/parsers/parser_accessibility.ts @@ -21,6 +21,7 @@ import {AccessibilityTraceFileProto} from "./proto_types"; class ParserAccessibility extends Parser { constructor(trace: Blob) { super(trace); + this.realToElapsedTimeOffsetNs = undefined; } override getTraceType(): TraceType { @@ -32,20 +33,31 @@ class ParserAccessibility extends Parser { } override decodeTrace(buffer: Uint8Array): any[] { - return (AccessibilityTraceFileProto.decode(buffer)).entry; + const decoded = AccessibilityTraceFileProto.decode(buffer); + if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); + } + else { + this.realToElapsedTimeOffsetNs = undefined; + } + return decoded.entry; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + if (type === TimestampType.ELAPSED) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); + else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } + return undefined; } override processDecodedEntry(entryProto: any): any { return entryProto; } + private realToElapsedTimeOffsetNs: undefined|bigint; private static readonly MAGIC_NUMBER = [0x09, 0x41, 0x31, 0x31, 0x59, 0x54, 0x52, 0x41, 0x43]; // .A11YTRAC } diff --git a/tools/winscope-ng/src/parsers/parser_common.spec.ts b/tools/winscope-ng/src/parsers/parser_common.spec.ts index e0a8605d5..60d45f553 100644 --- a/tools/winscope-ng/src/parsers/parser_common.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_common.spec.ts @@ -14,57 +14,97 @@ * limitations under the License. */ import {Timestamp, TimestampType} from "common/trace/timestamp"; -import {ParserFactory} from "./parser_factory"; import {Parser} from "./parser"; import {UnitTestUtils} from "test/unit/utils"; describe("Parser", () => { - let parser: Parser; + describe("real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_WindowManager.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/WindowManager.pb"); + }); + + it("provides timestamps", () => { + const expected = [ + new Timestamp(TimestampType.REAL, 1659107089075566202n), + new Timestamp(TimestampType.REAL, 1659107089999048990n), + new Timestamp(TimestampType.REAL, 1659107090010194213n) + ]; + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) + .toEqual(expected); + }); + + it("retrieves trace entry (no timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107089075566201n); + expect(parser.getTraceEntry(timestamp)) + .toEqual(undefined); + }); + + it("retrieves trace entry (equal timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107089075566202n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) + .toEqual(14474594000n); + }); + + it("retrieves trace entry (equal timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048990n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) + .toEqual(15398076788n); + }); + + it("retrieves trace entry (lower timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048991n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) + .toEqual(15398076788n); + }); }); - it("provides elapsed timestamps", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 850254319343n), - new Timestamp(TimestampType.ELAPSED, 850763506110n), - new Timestamp(TimestampType.ELAPSED, 850782750048n) - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); - }); + describe("elapsed timestamp", () => { + let parser: Parser; - it("retrieves trace entry (no timestamp matches)", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319342n); - expect(parser.getTraceEntry(timestamp)) - .toEqual(undefined); - }); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/WindowManager.pb"); + }); - it("retrieves trace entry (equal timestamp matches)", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) - .toEqual(850254319343n); - }); + it("provides timestamps", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 850254319343n), + new Timestamp(TimestampType.ELAPSED, 850763506110n), + new Timestamp(TimestampType.ELAPSED, 850782750048n) + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)) + .toEqual(expected); + }); - it("retrieves trace entry (equal timestamp matches)", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506110n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) - .toEqual(850763506110n); - }); + it("retrieves trace entry (no timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319342n); + expect(parser.getTraceEntry(timestamp)) + .toEqual(undefined); + }); - it("retrieves trace entry (lower timestamp matches)", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319344n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) - .toEqual(850254319343n); - }); + it("retrieves trace entry (equal timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) + .toEqual(850254319343n); + }); - it("retrieves trace entry (equal timestamp matches)", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506111n); - expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) - .toEqual(850763506110n); + it("retrieves trace entry (equal timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506110n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) + .toEqual(850763506110n); + }); + + it("retrieves trace entry (lower timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319344n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) + .toEqual(850254319343n); + }); + + it("retrieves trace entry (equal timestamp matches)", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506111n); + expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs)) + .toEqual(850763506110n); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts b/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts index 6f391cbe1..167942506 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_clients.spec.ts @@ -15,40 +15,76 @@ */ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; -import {ParserFactory} from "./parser_factory"; import {Parser} from "./parser"; import {UnitTestUtils} from "test/unit/utils"; describe("ParserInputMethodlClients", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_InputMethodClients.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/InputMethodClients.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS); + }); + + it("provides elapsed timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)!.length) + .toEqual(13); + + const expected = [ + new Timestamp(TimestampType.ELAPSED, 15613638434n), + new Timestamp(TimestampType.ELAPSED, 15647516364n), + new Timestamp(TimestampType.ELAPSED, 15677650967n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) + .toEqual(expected); + }); + + it("provides real timestamps", () => { + const expected = [ + new Timestamp(TimestampType.REAL, 1659107090215405395n), + new Timestamp(TimestampType.REAL, 1659107090249283325n), + new Timestamp(TimestampType.REAL, 1659107090279417928n), + ]; + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) + .toEqual(expected); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 15647516364n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(15647516364n); + }); + + it("retrieves trace entry from real timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107090249283325n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(15647516364n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS); - }); + describe("trace with elapsed (only) timestamp", () => { + let parser: Parser; - it("provides elapsed timestamps", () => { - expect(parser.getTimestamps(TimestampType.ELAPSED)!.length) - .toEqual(33); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodClients.pb"); + }); - const expected = [ - new Timestamp(TimestampType.ELAPSED, 1149083651642n), - new Timestamp(TimestampType.ELAPSED, 1149083950633n), - new Timestamp(TimestampType.ELAPSED, 1149127567251n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) - .toEqual(expected); - }); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS); + }); - it("retrieves trace entry", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 1149083651642n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(1149083651642n); + it("provides elapsed timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) + .toEqual(new Timestamp(TimestampType.ELAPSED, 1149083651642n)); + }); + + it("doesn't provide real timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) + .toEqual(new Timestamp(TimestampType.ELAPSED, 1149083651642n)); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_input_method_clients.ts b/tools/winscope-ng/src/parsers/parser_input_method_clients.ts index c8dfd4e9a..c3783b2c8 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_clients.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_clients.ts @@ -21,6 +21,7 @@ import {InputMethodClientsTraceFileProto} from "./proto_types"; class ParserInputMethodClients extends Parser { constructor(trace: Blob) { super(trace); + this.realToElapsedTimeOffsetNs = undefined; } getTraceType(): TraceType { @@ -32,20 +33,32 @@ class ParserInputMethodClients extends Parser { } override decodeTrace(buffer: Uint8Array): any[] { + const decoded = InputMethodClientsTraceFileProto.decode(buffer); + if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); + } + else { + this.realToElapsedTimeOffsetNs = undefined; + } + return (InputMethodClientsTraceFileProto.decode(buffer)).entry; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + if (type === TimestampType.ELAPSED) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); + else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs != undefined) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs); + } + return undefined; } override processDecodedEntry(entryProto: any): any { return entryProto; } + private realToElapsedTimeOffsetNs: undefined|bigint; private static readonly MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x43, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMCTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts index 455db1e2d..b6d0794fe 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.spec.ts @@ -15,37 +15,63 @@ */ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; -import {ParserFactory} from "./parser_factory"; import {Parser} from "./parser"; import {UnitTestUtils} from "test/unit/utils"; describe("ParserInputMethodManagerService", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_InputMethodManagerService.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/InputMethodManagerService.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_MANAGER_SERVICE); + }); + + it("provides elapsed timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)) + .toEqual([new Timestamp(TimestampType.ELAPSED, 15963782518n)]); + }); + + it("provides real timestamps", () => { + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual([new Timestamp(TimestampType.REAL, 1659107090565549479n)]); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 15963782518n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(15963782518n); + }); + + it("retrieves trace entry from real timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107090565549479n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(15963782518n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_MANAGER_SERVICE); - }); + describe("trace with elapsed (only) timestamp", () => { + let parser: Parser; - it("provides elapsed timestamps", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 1149226290110n), - new Timestamp(TimestampType.ELAPSED, 1149237707591n), - new Timestamp(TimestampType.ELAPSED, 1149238950389n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); - }); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodManagerService.pb"); + }); - it("retrieves trace entry", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 1149226290110n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(1149226290110n); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_MANAGER_SERVICE); + }); + + it("provides elapsed timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) + .toEqual(new Timestamp(TimestampType.ELAPSED, 1149226290110n)); + }); + + it("doesn't provide real timestamps", () => { + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual(undefined); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts index cd9146625..d1517f3a2 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_manager_service.ts @@ -21,6 +21,7 @@ import {InputMethodManagerServiceTraceFileProto} from "./proto_types"; class ParserInputMethodManagerService extends Parser { constructor(trace: Blob) { super(trace); + this.realToElapsedTimeOffsetNs = undefined; } getTraceType(): TraceType { @@ -32,20 +33,31 @@ class ParserInputMethodManagerService extends Parser { } override decodeTrace(buffer: Uint8Array): any[] { - return (InputMethodManagerServiceTraceFileProto.decode(buffer)).entry; + const decoded = InputMethodManagerServiceTraceFileProto.decode(buffer); + if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); + } + else { + this.realToElapsedTimeOffsetNs = undefined; + } + return decoded.entry; } - protected override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + protected override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + if (type === TimestampType.ELAPSED) { + return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos)); + else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } + return undefined; } protected override processDecodedEntry(entryProto: any): any { return entryProto; } + private realToElapsedTimeOffsetNs: undefined|bigint; private static readonly MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x4d, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMMTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts b/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts index 1da9481b5..a606f45c8 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_service.spec.ts @@ -20,36 +20,65 @@ import {Parser} from "./parser"; import {UnitTestUtils} from "test/unit/utils"; describe("ParserInputMethodService", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_InputMethodService.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/InputMethodService.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_SERVICE); + }); + + it("provides elapsed timestamps", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 16578752896n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)) + .toEqual(expected); + }); + + it("provides real timestamps", () => { + const expected = [ + new Timestamp(TimestampType.REAL, 1659107091180519857n), + ]; + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual(expected); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 16578752896n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(16578752896n); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107091180519857n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(16578752896n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_SERVICE); - }); + describe("trace with elapsed (only) timestamp", () => { + let parser: Parser; - it("provides timestamps", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 1149230019887n), - new Timestamp(TimestampType.ELAPSED, 1149234359324n), - new Timestamp(TimestampType.ELAPSED, 1149241227244n), - new Timestamp(TimestampType.ELAPSED, 1149243083608n), - new Timestamp(TimestampType.ELAPSED, 1149249518016n), - new Timestamp(TimestampType.ELAPSED, 1149249784617n), - new Timestamp(TimestampType.ELAPSED, 1149272993520n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); - }); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodService.pb"); + }); - it("retrieves trace entry", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 1149230019887n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(1149230019887n); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_SERVICE); + }); + + it("provides elapsed timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) + .toEqual(new Timestamp(TimestampType.ELAPSED, 1149230019887n)); + }); + + it("doesn't provide real timestamps", () => { + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual(undefined); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_input_method_service.ts b/tools/winscope-ng/src/parsers/parser_input_method_service.ts index f8d258806..5ed664c27 100644 --- a/tools/winscope-ng/src/parsers/parser_input_method_service.ts +++ b/tools/winscope-ng/src/parsers/parser_input_method_service.ts @@ -21,6 +21,7 @@ import {InputMethodServiceTraceFileProto} from "./proto_types"; class ParserInputMethodService extends Parser { constructor(trace: Blob) { super(trace); + this.realToElapsedTimeOffsetNs = undefined; } getTraceType(): TraceType { @@ -32,20 +33,31 @@ class ParserInputMethodService extends Parser { } override decodeTrace(buffer: Uint8Array): any[] { - return (InputMethodServiceTraceFileProto.decode(buffer)).entry; + const decoded = InputMethodServiceTraceFileProto.decode(buffer); + if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); + } + else { + this.realToElapsedTimeOffsetNs = undefined; + } + return decoded.entry; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + if (type === TimestampType.ELAPSED) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos)); + else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } + return undefined; } override processDecodedEntry(entryProto: any): any { return entryProto; } + private realToElapsedTimeOffsetNs: undefined|bigint; private static readonly MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x53, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMSTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_protolog.spec.ts b/tools/winscope-ng/src/parsers/parser_protolog.spec.ts index ab73af269..018138c64 100644 --- a/tools/winscope-ng/src/parsers/parser_protolog.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_protolog.spec.ts @@ -15,7 +15,6 @@ */ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; -import {ParserFactory} from "./parser_factory"; import {Parser} from "./parser"; import {UnitTestUtils} from "test/unit/utils"; import {LogMessage} from "../common/trace/protolog"; @@ -33,10 +32,7 @@ describe("ParserProtoLog", () => { }; beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_ProtoLog.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/ProtoLog.pb"); }); it("has expected trace type", () => { @@ -57,6 +53,20 @@ describe("ParserProtoLog", () => { .toEqual(expected); }); + it("provides real timestamps", () => { + const timestamps = parser.getTimestamps(TimestampType.REAL)!; + expect(timestamps.length) + .toEqual(50); + + const expected = [ + new Timestamp(TimestampType.REAL, 1655727125377266486n), + new Timestamp(TimestampType.REAL, 1655727125377336718n), + new Timestamp(TimestampType.REAL, 1655727125377350430n), + ]; + expect(timestamps.slice(0, 3)) + .toEqual(expected); + }); + it("reconstructs human-readable log message", () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 850746266486n); const actualMessage = parser.getTraceEntry(timestamp)!; diff --git a/tools/winscope-ng/src/parsers/parser_protolog.ts b/tools/winscope-ng/src/parsers/parser_protolog.ts index 34aac33a6..e8656c6e6 100644 --- a/tools/winscope-ng/src/parsers/parser_protolog.ts +++ b/tools/winscope-ng/src/parsers/parser_protolog.ts @@ -48,6 +48,8 @@ class ParserProtoLog extends Parser { throw new TypeError(message); } + this.realToElapsedTimeOffsetNs = BigInt(fileProto.realTimeToElapsedTimeOffsetMillis) * 1000000n; + fileProto.log.sort((a: any, b: any) => { return Number(a.elapsedRealtimeNanos) - Number(b.elapsedRealtimeNanos); }); @@ -55,11 +57,14 @@ class ParserProtoLog extends Parser { return fileProto.log; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + if (type == TimestampType.ELAPSED) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); + else if (type == TimestampType.REAL) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs!); + } + return undefined; } override processDecodedEntry(entryProto: any): LogMessage { @@ -85,6 +90,7 @@ class ParserProtoLog extends Parser { }); } + private realToElapsedTimeOffsetNs: undefined|bigint = undefined; private static readonly MAGIC_NUMBER = [0x09, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x4c, 0x4f, 0x47]; // .PROTOLOG private static readonly PROTOLOG_VERSION = "1.0.0"; } diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts b/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts index 211fa5371..8dfff7714 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording.spec.ts @@ -18,16 +18,12 @@ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; import {UnitTestUtils} from "test/unit/utils"; import {Parser} from "./parser"; -import {ParserFactory} from "./parser_factory"; describe("ParserScreenRecording", () => { let parser: Parser; beforeAll(async () => { - const trace = UnitTestUtils.getFixtureBlob("screen_recording.mp4"); - const parsers = await new ParserFactory().createParsers([trace]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/screen_recording.mp4"); }); it("has expected trace type", () => { @@ -38,12 +34,12 @@ describe("ParserScreenRecording", () => { const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; expect(timestamps.length) - .toEqual(88); + .toEqual(15); const expected = [ - new Timestamp(TimestampType.ELAPSED, 732949304000n), - new Timestamp(TimestampType.ELAPSED, 733272129000n), - new Timestamp(TimestampType.ELAPSED, 733283916000n), + new Timestamp(TimestampType.ELAPSED, 144857685000n), + new Timestamp(TimestampType.ELAPSED, 144866679000n), + new Timestamp(TimestampType.ELAPSED, 144875772000n), ]; expect(timestamps.slice(0, 3)) .toEqual(expected); @@ -53,12 +49,12 @@ describe("ParserScreenRecording", () => { const timestamps = parser.getTimestamps(TimestampType.REAL)!; expect(timestamps.length) - .toEqual(88); + .toEqual(15); const expected = [ - new Timestamp(TimestampType.REAL, 1658843852566916386n), - new Timestamp(TimestampType.REAL, 1658843852889741386n), - new Timestamp(TimestampType.REAL, 1658843852901528386n), + new Timestamp(TimestampType.REAL, 1659687791485257266n), + new Timestamp(TimestampType.REAL, 1659687791494251266n), + new Timestamp(TimestampType.REAL, 1659687791503344266n), ]; expect(timestamps.slice(0, 3)) .toEqual(expected); @@ -66,30 +62,30 @@ describe("ParserScreenRecording", () => { it("retrieves trace entry from elapsed timestamp", () => { { - const timestamp = new Timestamp(TimestampType.ELAPSED, 732949304000n); + const timestamp = new Timestamp(TimestampType.ELAPSED, 144857685000n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry); expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0); } { - const timestamp = new Timestamp(TimestampType.ELAPSED, 733272129000n); + const timestamp = new Timestamp(TimestampType.ELAPSED, 145300550000n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry); - expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0.322, 0.001); + expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0.442, 0.001); } }); it("retrieves trace entry from real timestamp", () => { { - const timestamp = new Timestamp(TimestampType.REAL, 1658843852566916386n); + const timestamp = new Timestamp(TimestampType.REAL, 1659687791485257266n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry); expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0); } { - const timestamp = new Timestamp(TimestampType.REAL, 1658843852889741386n); + const timestamp = new Timestamp(TimestampType.REAL, 1659687791928122266n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry); expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0.322, 0.001); diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording.ts b/tools/winscope-ng/src/parsers/parser_screen_recording.ts index cc1def217..92dc05867 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording.ts @@ -52,19 +52,19 @@ class ParserScreenRecording extends Parser { }); } - override getTimestamp(decodedEntry: ScreenRecordingMetadataEntry, type: TimestampType): undefined|Timestamp { + override getTimestamp(type: TimestampType, decodedEntry: ScreenRecordingMetadataEntry): undefined|Timestamp { if (type !== TimestampType.ELAPSED && type !== TimestampType.REAL) { return undefined; } if (type === TimestampType.ELAPSED) { - // Traces typically contain "elapsed" timestamps (SYSTEM_TIME_BOOTTIME). - // Screen recordings contain SYSTEM_TIME_MONOTONIC timestamps. + // Traces typically contain "elapsed" timestamps (SYSTEM_TIME_BOOTTIME), + // whereas screen recordings contain SYSTEM_TIME_MONOTONIC timestamps. // // Here we are pretending that screen recordings contain "elapsed" timestamps // as well, in order to synchronize with the other traces. // // If no device suspensions are involved, SYSTEM_TIME_MONOTONIC should indeed - // correspond to SYSTEM_TIME_BOOTTIME and things should work as expected. + // correspond to SYSTEM_TIME_BOOTTIME and things will work as expected. return new Timestamp(type, decodedEntry.timestampMonotonicNs); } else if (type === TimestampType.REAL) { @@ -125,8 +125,6 @@ class ParserScreenRecording extends Parser { for (let i = 0; i < count; ++i) { const timestamp = ArrayUtils.toUintLittleEndian(videoData, pos, pos+8); pos += 8; - //parse VSYNC ID here when available - pos += 8; timestamps.push(timestamp); } return timestamps; diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts index a5175a16f..a0c8b76f1 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.spec.ts @@ -18,16 +18,12 @@ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; import {UnitTestUtils} from "test/unit/utils"; import {Parser} from "./parser"; -import {ParserFactory} from "./parser_factory"; describe("ParserScreenRecordingLegacy", () => { let parser: Parser; beforeAll(async () => { - const trace = UnitTestUtils.getFixtureBlob("screen_recording_legacy.mp4"); - const parsers = await new ParserFactory().createParsers([trace]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/screen_recording.mp4"); }); it("has expected trace type", () => { diff --git a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts index 01550cef9..71c57a263 100644 --- a/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts +++ b/tools/winscope-ng/src/parsers/parser_screen_recording_legacy.ts @@ -38,7 +38,7 @@ class ParserScreenRecordingLegacy extends Parser { return this.parseTimestamps(videoData, posTimestamps, count); } - override getTimestamp(decodedEntry: Timestamp, type: TimestampType): undefined|Timestamp { + override getTimestamp(type: TimestampType, decodedEntry: Timestamp): undefined|Timestamp { if (type !== TimestampType.ELAPSED) { return undefined; } diff --git a/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts b/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts index 467018e96..d67494dd6 100644 --- a/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_surface_flinger.spec.ts @@ -18,36 +18,73 @@ import {TraceType} from "common/trace/trace_type"; import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry"; import {UnitTestUtils} from "test/unit/utils"; import {Parser} from "./parser"; -import {ParserFactory} from "./parser_factory"; describe("ParserSurfaceFlinger", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_SurfaceFlinger.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/SurfaceFlinger.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); + }); + + it("provides elapsed timestamps", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 14500282843n), + new Timestamp(TimestampType.ELAPSED, 14631249355n), + new Timestamp(TimestampType.ELAPSED, 15403446377n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) + .toEqual(expected); + }); + + it("provides real timestamps", () => { + const expected = [ + new Timestamp(TimestampType.REAL, 1659107089102062832n), + new Timestamp(TimestampType.REAL, 1659107089233029344n), + new Timestamp(TimestampType.REAL, 1659107090005226366n), + ]; + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) + .toEqual(expected); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 14631249355n); + const entry = parser.getTraceEntry(timestamp)!; + expect(entry).toBeInstanceOf(LayerTraceEntry); + expect(BigInt(entry.timestampMs)).toEqual(14631249355n); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107089233029344n); + const entry = parser.getTraceEntry(timestamp)!; + expect(entry).toBeInstanceOf(LayerTraceEntry); + expect(BigInt(entry.timestampMs)).toEqual(14631249355n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); - }); + describe("trace with elapsed (only) timestamp", () => { + let parser: Parser; - it("provides elapsed timestamps", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 850335483446n), - new Timestamp(TimestampType.ELAPSED, 850686322883n), - new Timestamp(TimestampType.ELAPSED, 850736507697n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); - }); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/SurfaceFlinger.pb"); + }); - it("retrieves trace entry", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850335483446n); - const entry = parser.getTraceEntry(timestamp)!; - expect(entry).toBeInstanceOf(LayerTraceEntry); - expect(BigInt(entry.timestampMs)).toEqual(850335483446n); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); + }); + + it("provides elapsed timestamps", () => { + expect(parser.getTimestamps(TimestampType.ELAPSED)![0]) + .toEqual(new Timestamp(TimestampType.ELAPSED, 850335483446n)); + }); + + it("doesn't provide real timestamps", () => { + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual(undefined); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_surface_flinger.ts b/tools/winscope-ng/src/parsers/parser_surface_flinger.ts index c8cedf033..62a6a73f9 100644 --- a/tools/winscope-ng/src/parsers/parser_surface_flinger.ts +++ b/tools/winscope-ng/src/parsers/parser_surface_flinger.ts @@ -22,6 +22,7 @@ import {LayersTraceFileProto} from "./proto_types"; class ParserSurfaceFlinger extends Parser { constructor(trace: Blob) { super(trace); + this.realToElapsedTimeOffsetNs = undefined; } override getTraceType(): TraceType { @@ -33,20 +34,36 @@ class ParserSurfaceFlinger extends Parser { } override decodeTrace(buffer: Uint8Array): any[] { - return (LayersTraceFileProto.decode(buffer)).entry; + const decoded = LayersTraceFileProto.decode(buffer); + if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); + } + else { + this.realToElapsedTimeOffsetNs = undefined; + } + return decoded.entry; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + const isDump = !Object.prototype.hasOwnProperty.call(entryProto, "elapsedRealtimeNanos"); + if (type === TimestampType.ELAPSED) { + return isDump + ? new Timestamp(type, 0n) + : new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(TimestampType.ELAPSED, entryProto.elapsedRealtimeNanos); + else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return isDump + ? new Timestamp(type, 0n) + : new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } + return undefined; } override processDecodedEntry(entryProto: any): any { return LayerTraceEntry.fromProto(entryProto.layers.layers, entryProto.displays, entryProto.elapsedRealtimeNanos, entryProto.hwcBlob); } + private realToElapsedTimeOffsetNs: undefined|bigint; private static readonly MAGIC_NUMBER = [0x09, 0x4c, 0x59, 0x52, 0x54, 0x52, 0x41, 0x43, 0x45]; // .LYRTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts b/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts index 508ae9c17..e32da20e2 100644 --- a/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_surface_flinger_dump.spec.ts @@ -18,35 +18,68 @@ import {TraceType} from "common/trace/trace_type"; import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry"; import {UnitTestUtils} from "test/unit/utils"; import {Parser} from "./parser"; -import {ParserFactory} from "./parser_factory"; describe("ParserSurfaceFlingerDump", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("dump_SurfaceFlinger.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/dump_SurfaceFlinger.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); + }); + + it("provides elapsed timestamp", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 0n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); + }); + + it("provides real timestamp (always zero)", () => { + const expected = [ + new Timestamp(TimestampType.REAL, 0n), + ]; + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(expected); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 0n); + const entry = parser.getTraceEntry(timestamp)!; + expect(entry).toBeInstanceOf(LayerTraceEntry); + expect(BigInt(entry.timestampMs)).toEqual(0n); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 0n); + const entry = parser.getTraceEntry(timestamp)!; + expect(entry).toBeInstanceOf(LayerTraceEntry); + expect(BigInt(entry.timestampMs)).toEqual(0n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); - }); + describe("trace with elapsed (only) timestamp", () => { + let parser: Parser; - it("provides timestamp", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 0n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); - }); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/dump_SurfaceFlinger.pb"); + }); - it("retrieves trace entry", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 0n); - const entry = parser.getTraceEntry(timestamp)!; - expect(entry).toBeInstanceOf(LayerTraceEntry); - expect(BigInt(entry.timestampMs)).toEqual(0n); - }); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER); + }); - //TODO: add real timestamp + it("provides elapsed timestamp (always zero)", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 0n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected); + }); + + it("doesn't provide real timestamp", () => { + expect(parser.getTimestamps(TimestampType.REAL)).toEqual(undefined); + }); + }); }); diff --git a/tools/winscope-ng/src/parsers/parser_transactions.spec.ts b/tools/winscope-ng/src/parsers/parser_transactions.spec.ts index dce33ad7c..2bbf63973 100644 --- a/tools/winscope-ng/src/parsers/parser_transactions.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_transactions.spec.ts @@ -16,41 +16,92 @@ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; import {Parser} from "./parser"; -import {ParserFactory} from "./parser_factory"; import {UnitTestUtils} from "test/unit/utils"; describe("ParserTransactions", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_Transactions.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/Transactions.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.TRANSACTIONS); + }); + + it("provides elapsed timestamps", () => { + const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; + + expect(timestamps.length) + .toEqual(712); + + const expected = [ + new Timestamp(TimestampType.ELAPSED, 2450981445n), + new Timestamp(TimestampType.ELAPSED, 2517952515n), + new Timestamp(TimestampType.ELAPSED, 4021151449n), + ]; + expect(timestamps.slice(0, 3)) + .toEqual(expected); + }); + + it("provides real timestamps", () => { + const timestamps = parser.getTimestamps(TimestampType.REAL)!; + + expect(timestamps.length) + .toEqual(712); + + const expected = [ + new Timestamp(TimestampType.REAL, 1659507541051480997n), + new Timestamp(TimestampType.REAL, 1659507541118452067n), + new Timestamp(TimestampType.REAL, 1659507542621651001n), + ]; + expect(timestamps.slice(0, 3)) + .toEqual(expected); + }); + + it("retrieves trace entry from elsapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 2517952515n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(2517952515n); + }); + + it("retrieves trace entry from real timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659507541118452067n); + expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) + .toEqual(2517952515n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.TRANSACTIONS); - }); + describe("trace with elapsed (only) timestamp", () => { + let parser: Parser; - it("provides timestamps", () => { - const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/Transactions.pb"); + }); - expect(timestamps.length) - .toEqual(4997); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.TRANSACTIONS); + }); - const expected = [ - new Timestamp(TimestampType.ELAPSED, 14862317023n), - new Timestamp(TimestampType.ELAPSED, 14873423549n), - new Timestamp(TimestampType.ELAPSED, 14884850511n), - ]; - expect(timestamps.slice(0, 3)) - .toEqual(expected); - }); + it("provides elapsed timestamps", () => { + const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; - it("retrieves trace entry", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 14862317023n); - expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos)) - .toEqual(14862317023n); + expect(timestamps.length) + .toEqual(4997); + + const expected = [ + new Timestamp(TimestampType.ELAPSED, 14862317023n), + new Timestamp(TimestampType.ELAPSED, 14873423549n), + new Timestamp(TimestampType.ELAPSED, 14884850511n), + ]; + expect(timestamps.slice(0, 3)) + .toEqual(expected); + }); + + it("doesn't provide real timestamps", () => { + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual(undefined); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_transactions.ts b/tools/winscope-ng/src/parsers/parser_transactions.ts index b3da697cc..6af4c4c55 100644 --- a/tools/winscope-ng/src/parsers/parser_transactions.ts +++ b/tools/winscope-ng/src/parsers/parser_transactions.ts @@ -16,11 +16,12 @@ import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; import {Parser} from "./parser"; -import {TransactionsTraceFileProto} from "./proto_types"; +import {AccessibilityTraceFileProto, TransactionsTraceFileProto} from "./proto_types"; class ParserTransactions extends Parser { constructor(trace: Blob) { super(trace); + this.realToElapsedTimeOffsetNs = undefined; } override getTraceType(): TraceType { @@ -32,20 +33,31 @@ class ParserTransactions extends Parser { } override decodeTrace(buffer: Uint8Array): any[] { - return (TransactionsTraceFileProto.decode(buffer)).entry; + const decoded = TransactionsTraceFileProto.decode(buffer); + if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); + } + else { + this.realToElapsedTimeOffsetNs = undefined; + } + return decoded.entry; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + if (type === TimestampType.ELAPSED) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos)); + else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } + return undefined; } override processDecodedEntry(entryProto: any): any { return entryProto; } + private realToElapsedTimeOffsetNs: undefined|bigint; private static readonly MAGIC_NUMBER = [0x09, 0x54, 0x4e, 0x58, 0x54, 0x52, 0x41, 0x43, 0x45]; // .TNXTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts b/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts index ca1a816b0..3c50fc02b 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager.spec.ts @@ -16,38 +16,82 @@ import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState"; import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; -import {ParserFactory} from "./parser_factory"; import {Parser} from "./parser"; import {UnitTestUtils} from "test/unit/utils"; describe("ParserWindowManager", () => { - let parser: Parser; + describe("trace with elapsed + real timestamp", () => { + let parser: Parser; - beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("trace_WindowManager.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_and_real_timestamp/WindowManager.pb"); + }); + + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER); + }); + + it("provides elapsed timestamps", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 14474594000n), + new Timestamp(TimestampType.ELAPSED, 15398076788n), + new Timestamp(TimestampType.ELAPSED, 15409222011n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3)) + .toEqual(expected); + }); + + it("provides real timestamps", () => { + const expected = [ + new Timestamp(TimestampType.REAL, 1659107089075566202n), + new Timestamp(TimestampType.REAL, 1659107089999048990n), + new Timestamp(TimestampType.REAL, 1659107090010194213n), + ]; + expect(parser.getTimestamps(TimestampType.REAL)!.slice(0, 3)) + .toEqual(expected); + }); + + it("retrieves trace entry from elapsed timestamp", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 15398076788n); + const entry = parser.getTraceEntry(timestamp)!; + expect(entry).toBeInstanceOf(WindowManagerState); + expect(BigInt(entry.timestampMs)).toEqual(15398076788n); + }); + + it("retrieves trace entry from real timestamp", () => { + const timestamp = new Timestamp(TimestampType.REAL, 1659107089999048990n); + const entry = parser.getTraceEntry(timestamp)!; + expect(entry).toBeInstanceOf(WindowManagerState); + expect(BigInt(entry.timestampMs)).toEqual(15398076788n); + }); }); - it("has expected trace type", () => { - expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER); - }); + describe("trace elapsed timestamp", () => { + let parser: Parser; - it("provides timestamps", () => { - const expected = [ - new Timestamp(TimestampType.ELAPSED, 850254319343n), - new Timestamp(TimestampType.ELAPSED, 850763506110n), - new Timestamp(TimestampType.ELAPSED, 850782750048n), - ]; - expect(parser.getTimestamps(TimestampType.ELAPSED)) - .toEqual(expected); - }); + beforeAll(async () => { + parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/WindowManager.pb"); + }); - it("retrieves trace entry", () => { - const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n); - const entry = parser.getTraceEntry(timestamp)!; - expect(entry).toBeInstanceOf(WindowManagerState); - expect(BigInt(entry.timestampMs)).toEqual(850254319343n); + it("has expected trace type", () => { + expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER); + }); + + it("provides timestamps", () => { + const expected = [ + new Timestamp(TimestampType.ELAPSED, 850254319343n), + new Timestamp(TimestampType.ELAPSED, 850763506110n), + new Timestamp(TimestampType.ELAPSED, 850782750048n), + ]; + expect(parser.getTimestamps(TimestampType.ELAPSED)) + .toEqual(expected); + }); + + it("retrieves trace entry", () => { + const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n); + const entry = parser.getTraceEntry(timestamp)!; + expect(entry).toBeInstanceOf(WindowManagerState); + expect(BigInt(entry.timestampMs)).toEqual(850254319343n); + }); }); }); diff --git a/tools/winscope-ng/src/parsers/parser_window_manager.ts b/tools/winscope-ng/src/parsers/parser_window_manager.ts index 958aa48a6..08a6f6004 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager.ts @@ -22,6 +22,7 @@ import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerS class ParserWindowManager extends Parser { constructor(trace: Blob) { super(trace); + this.realToElapsedTimeOffsetNs = undefined; } override getTraceType(): TraceType { @@ -33,20 +34,31 @@ class ParserWindowManager extends Parser { } override decodeTrace(buffer: Uint8Array): any[] { - return (WindowManagerTraceFileProto.decode(buffer)).entry; + const decoded = WindowManagerTraceFileProto.decode(buffer); + if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) { + this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos); + } + else { + this.realToElapsedTimeOffsetNs = undefined; + } + return decoded.entry; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { - if (type !== TimestampType.ELAPSED) { - return undefined; + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { + if (type === TimestampType.ELAPSED) { + return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos)); } - return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos)); + else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { + return new Timestamp(type, this.realToElapsedTimeOffsetNs + BigInt(entryProto.elapsedRealtimeNanos)); + } + return undefined; } override processDecodedEntry(entryProto: any): WindowManagerState { return WindowManagerState.fromProto(entryProto.windowManagerService, entryProto.elapsedRealtimeNanos, entryProto.where); } + private realToElapsedTimeOffsetNs: undefined|bigint; private static readonly MAGIC_NUMBER = [0x09, 0x57, 0x49, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45]; // .WINTRACE } diff --git a/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts b/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts index 5c8cd6fcf..107400042 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager_dump.spec.ts @@ -16,7 +16,6 @@ import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState"; import {Timestamp, TimestampType} from "common/trace/timestamp"; import {TraceType} from "common/trace/trace_type"; -import {ParserFactory} from "./parser_factory"; import {Parser} from "./parser"; import {UnitTestUtils} from "test/unit/utils"; @@ -24,17 +23,14 @@ describe("ParserWindowManagerDump", () => { let parser: Parser; beforeAll(async () => { - const buffer = UnitTestUtils.getFixtureBlob("dump_WindowManager.pb"); - const parsers = await new ParserFactory().createParsers([buffer]); - expect(parsers.length).toEqual(1); - parser = parsers[0]; + parser = await UnitTestUtils.getParser("traces/dump_WindowManager.pb"); }); it("has expected trace type", () => { expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER); }); - it("provides timestamps", () => { + it("provides elapsed timestamp (always zero)", () => { const expected = [ new Timestamp(TimestampType.ELAPSED, 0n), ]; @@ -42,12 +38,15 @@ describe("ParserWindowManagerDump", () => { .toEqual(expected); }); - it("retrieves trace entry", () => { + it("doesn't provide real timestamp (never)", () => { + expect(parser.getTimestamps(TimestampType.REAL)) + .toEqual(undefined); + }); + + it("retrieves trace entry from elapsed timestamp", () => { const timestamp = new Timestamp(TimestampType.ELAPSED, 0n); const entry = parser.getTraceEntry(timestamp)!; expect(entry).toBeInstanceOf(WindowManagerState); expect(BigInt(entry.timestampMs)).toEqual(0n); }); - - //TODO: add real timestamp }); diff --git a/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts b/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts index c1e0ab2c8..0e93e4728 100644 --- a/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts +++ b/tools/winscope-ng/src/parsers/parser_window_manager_dump.ts @@ -36,7 +36,7 @@ class ParserWindowManagerDump extends Parser { return [WindowManagerServiceDumpProto.decode(buffer)]; } - override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp { + override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp { if (type !== TimestampType.ELAPSED) { return undefined; } diff --git a/tools/winscope-ng/src/test/common/utils.ts b/tools/winscope-ng/src/test/common/utils.ts index 92d06e4cf..041f82617 100644 --- a/tools/winscope-ng/src/test/common/utils.ts +++ b/tools/winscope-ng/src/test/common/utils.ts @@ -28,6 +28,9 @@ class CommonTestUtils { } static getFixturePath(filename: string): string { + if (path.isAbsolute(filename)) { + return filename; + } return path.join(CommonTestUtils.getProjectRootPath(), "src/test/fixtures", filename); } diff --git a/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts b/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts index f3f4384d8..501fcfbc3 100644 --- a/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts +++ b/tools/winscope-ng/src/test/e2e/viewer_window_manager.spec.ts @@ -24,7 +24,7 @@ describe("Viewer WindowManager", () => { it("processes trace and renders view", () => { const inputFile = element(by.css("input[type=\"file\"]")); - inputFile.sendKeys(E2eTestUtils.getFixturePath("trace_WindowManager.pb")); + inputFile.sendKeys(E2eTestUtils.getFixturePath("traces/elapsed_and_real_timestamp/WindowManager.pb")); const windowManagerViewerTitle = element(by.css(".viewer-window-manager .title")); expect(windowManagerViewerTitle.getText()).toContain("Window Manager"); diff --git a/tools/winscope-ng/src/test/fixtures/screen_recording.mp4 b/tools/winscope-ng/src/test/fixtures/screen_recording.mp4 deleted file mode 100644 index e18879be4..000000000 Binary files a/tools/winscope-ng/src/test/fixtures/screen_recording.mp4 and /dev/null differ diff --git a/tools/winscope-ng/src/test/fixtures/dump_WindowManager.pb b/tools/winscope-ng/src/test/fixtures/traces/dump_WindowManager.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/dump_WindowManager.pb rename to tools/winscope-ng/src/test/fixtures/traces/dump_WindowManager.pb diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/Accessibility.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/Accessibility.pb new file mode 100644 index 000000000..6780f22ea Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/Accessibility.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodClients.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodClients.pb new file mode 100644 index 000000000..b70ea7f3c Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodClients.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodManagerService.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodManagerService.pb new file mode 100644 index 000000000..cf5f0caf7 Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodManagerService.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodService.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodService.pb new file mode 100644 index 000000000..4b7c330cd Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/InputMethodService.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/trace_ProtoLog.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/ProtoLog.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_ProtoLog.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/ProtoLog.pb diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/SurfaceFlinger.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/SurfaceFlinger.pb new file mode 100644 index 000000000..d26f5cc79 Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/SurfaceFlinger.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/Transactions.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/Transactions.pb new file mode 100644 index 000000000..3ffe81a0f Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/Transactions.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/WindowManager.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/WindowManager.pb new file mode 100644 index 000000000..7749b4bc7 Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/WindowManager.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/dump_SurfaceFlinger.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/dump_SurfaceFlinger.pb new file mode 100644 index 000000000..b5b884f0e Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/dump_SurfaceFlinger.pb differ diff --git a/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/screen_recording.mp4 b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/screen_recording.mp4 new file mode 100644 index 000000000..0d28a1d71 Binary files /dev/null and b/tools/winscope-ng/src/test/fixtures/traces/elapsed_and_real_timestamp/screen_recording.mp4 differ diff --git a/tools/winscope-ng/src/test/fixtures/trace_Accessibility.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/Accessibility.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_Accessibility.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/Accessibility.pb diff --git a/tools/winscope-ng/src/test/fixtures/trace_InputMethodClients.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/InputMethodClients.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_InputMethodClients.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/InputMethodClients.pb diff --git a/tools/winscope-ng/src/test/fixtures/trace_InputMethodManagerService.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/InputMethodManagerService.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_InputMethodManagerService.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/InputMethodManagerService.pb diff --git a/tools/winscope-ng/src/test/fixtures/trace_InputMethodService.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/InputMethodService.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_InputMethodService.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/InputMethodService.pb diff --git a/tools/winscope-ng/src/test/fixtures/trace_SurfaceFlinger.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/SurfaceFlinger.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_SurfaceFlinger.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/SurfaceFlinger.pb diff --git a/tools/winscope-ng/src/test/fixtures/trace_Transactions.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/Transactions.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_Transactions.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/Transactions.pb diff --git a/tools/winscope-ng/src/test/fixtures/trace_WindowManager.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/WindowManager.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/trace_WindowManager.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/WindowManager.pb diff --git a/tools/winscope-ng/src/test/fixtures/dump_SurfaceFlinger.pb b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/dump_SurfaceFlinger.pb similarity index 100% rename from tools/winscope-ng/src/test/fixtures/dump_SurfaceFlinger.pb rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/dump_SurfaceFlinger.pb diff --git a/tools/winscope-ng/src/test/fixtures/screen_recording_legacy.mp4 b/tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/screen_recording.mp4 similarity index 100% rename from tools/winscope-ng/src/test/fixtures/screen_recording_legacy.mp4 rename to tools/winscope-ng/src/test/fixtures/traces/elapsed_timestamp/screen_recording.mp4