From 28c77be00fd6b03a4b925fbb29ee383aab74ca1e Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Sun, 21 May 2023 23:41:28 +0000 Subject: [PATCH] Add WM & Shell side transitions parsers Bug: 277181336 Test: npm run test:all Change-Id: I7eb981367191c47d3b50b31ee66f147ff1d6943d --- tools/winscope/src/app/trace_info.ts | 9 +- tools/winscope/src/parsers/parser_factory.ts | 6 +- .../src/parsers/parser_transitions.ts | 122 -------------- .../src/parsers/parser_transitions_shell.ts | 159 ++++++++++++++++++ .../parsers/parser_transitions_shell_test.ts | 61 +++++++ .../src/parsers/parser_transitions_test.ts | 50 ------ .../src/parsers/parser_transitions_wm.ts | 149 ++++++++++++++++ .../src/parsers/parser_transitions_wm_test.ts | 61 +++++++ tools/winscope/src/parsers/proto_types.js | 11 +- .../shell_transition_trace.pb | 2 + .../wm_transition_trace.pb | 7 + tools/winscope/src/trace/flickerlib/common.js | 6 + tools/winscope/src/trace/trace_type.ts | 6 +- 13 files changed, 468 insertions(+), 181 deletions(-) delete mode 100644 tools/winscope/src/parsers/parser_transitions.ts create mode 100644 tools/winscope/src/parsers/parser_transitions_shell.ts create mode 100644 tools/winscope/src/parsers/parser_transitions_shell_test.ts delete mode 100644 tools/winscope/src/parsers/parser_transitions_test.ts create mode 100644 tools/winscope/src/parsers/parser_transitions_wm.ts create mode 100644 tools/winscope/src/parsers/parser_transitions_wm_test.ts create mode 100644 tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/shell_transition_trace.pb create mode 100644 tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/wm_transition_trace.pb diff --git a/tools/winscope/src/app/trace_info.ts b/tools/winscope/src/app/trace_info.ts index 9110cd781..7d595cdec 100644 --- a/tools/winscope/src/app/trace_info.ts +++ b/tools/winscope/src/app/trace_info.ts @@ -125,8 +125,13 @@ export const TRACE_INFO: TraceInfoMap = { icon: EVENT_LOG_ICON, color: '#fdd663', }, - [TraceType.TRANSITION]: { - name: 'Transition Trace', + [TraceType.WM_TRANSITION]: { + name: 'WM Transitions', + icon: TRANSITION_ICON, + color: '#EC407A', + }, + [TraceType.SHELL_TRANSITION]: { + name: 'Shell Transitions', icon: TRANSITION_ICON, color: '#EC407A', }, diff --git a/tools/winscope/src/parsers/parser_factory.ts b/tools/winscope/src/parsers/parser_factory.ts index 836735ba6..2c0b18924 100644 --- a/tools/winscope/src/parsers/parser_factory.ts +++ b/tools/winscope/src/parsers/parser_factory.ts @@ -28,7 +28,8 @@ import {ParserScreenRecording} from './parser_screen_recording'; import {ParserScreenRecordingLegacy} from './parser_screen_recording_legacy'; import {ParserSurfaceFlinger} from './parser_surface_flinger'; import {ParserTransactions} from './parser_transactions'; -import {ParserTransitions} from './parser_transitions'; +import {ParserTransitionsShell} from './parser_transitions_shell'; +import {ParserTransitionsWm} from './parser_transitions_wm'; import {ParserWindowManager} from './parser_window_manager'; import {ParserWindowManagerDump} from './parser_window_manager_dump'; @@ -46,7 +47,8 @@ export class ParserFactory { ParserWindowManager, ParserWindowManagerDump, ParserEventLog, - ParserTransitions, + ParserTransitionsWm, + ParserTransitionsShell, ]; private parsers = new Map>(); diff --git a/tools/winscope/src/parsers/parser_transitions.ts b/tools/winscope/src/parsers/parser_transitions.ts deleted file mode 100644 index f82f2d4b1..000000000 --- a/tools/winscope/src/parsers/parser_transitions.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - CrossPlatform, - Transition, - TransitionChange, - TransitionType, - WindowingMode, -} from 'trace/flickerlib/common'; -import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'trace/timestamp'; -import {TraceFile} from 'trace/trace_file'; -import {TraceType} from 'trace/trace_type'; -import {AbstractParser} from './abstract_parser'; -import {TransitionsTraceFileProto} from './proto_types'; - -export class ParserTransitions extends AbstractParser { - constructor(trace: TraceFile) { - super(trace); - this.realToElapsedTimeOffsetNs = undefined; - } - - override getTraceType(): TraceType { - return TraceType.TRANSITION; - } - - override getMagicNumber(): number[] { - return ParserTransitions.MAGIC_NUMBER; - } - - override decodeTrace(buffer: Uint8Array): any[] { - const decodedProto = TransitionsTraceFileProto.decode(buffer) as any; - this.realToElapsedTimeOffsetNs = BigInt(decodedProto.realToElapsedTimeOffsetNanos); - - return decodedProto.transitions; - } - - override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp { - if (type === TimestampType.ELAPSED) { - return new ElapsedTimestamp(BigInt(entryProto.createTimeNs)); - } - if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) { - return new RealTimestamp(this.realToElapsedTimeOffsetNs + BigInt(entryProto.createTimeNs)); - } - return undefined; - } - - override processDecodedEntry( - index: number, - timestampType: TimestampType, - entryProto: any - ): Transition { - if (!this.transitions) { - const transitions = this.decodedEntries.map((it) => this.parseProto(it)); - this.transitions = transitions; - } - return this.transitions[index]; - } - - private parseProto(entryProto: any): Transition { - const changes = entryProto.targets.map((it: any) => { - const windowingMode = WindowingMode.WINDOWING_MODE_UNDEFINED; // TODO: Get the windowing mode - - return new TransitionChange( - TransitionType.Companion.fromInt(it.mode), - it.layerId, - it.windowId, - windowingMode - ); - }); - - const createTime = CrossPlatform.timestamp.fromString( - entryProto.createTimeNs.toString(), - null, - null - ); - const sendTime = CrossPlatform.timestamp.fromString( - entryProto.sendTimeNs.toString(), - null, - null - ); - const finishTime = CrossPlatform.timestamp.fromString( - entryProto.finishTimeNs.toString(), - null, - null - ); - const startTransactionId = entryProto.startTransactionId; - const finishTransactionId = entryProto.finishTransactionId; - const type = TransitionType.Companion.fromInt(entryProto.type); - const played = entryProto.finishTimeNs > 0; - const aborted = entryProto.sendTimeNs === 0; - - return new Transition( - createTime, - sendTime, - finishTime, - startTransactionId, - finishTransactionId, - type, - changes, - played, - aborted - ); - } - - private transitions: Transition[] | undefined; - private realToElapsedTimeOffsetNs: undefined | bigint; - private static readonly MAGIC_NUMBER = [0x09, 0x54, 0x52, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45]; // .TRNTRACE -} diff --git a/tools/winscope/src/parsers/parser_transitions_shell.ts b/tools/winscope/src/parsers/parser_transitions_shell.ts new file mode 100644 index 000000000..db7941b24 --- /dev/null +++ b/tools/winscope/src/parsers/parser_transitions_shell.ts @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + CrossPlatform, + ShellTransitionData, + Transition, + WmTransitionData, +} from 'trace/flickerlib/common'; +import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'trace/timestamp'; +import {TraceType} from 'trace/trace_type'; +import {AbstractParser} from './abstract_parser'; +import {ShellTransitionsTraceFileProto} from './proto_types'; + +export class ParserTransitionsShell extends AbstractParser { + private realToElapsedTimeOffsetNs: undefined | bigint; + private handlerMapping: undefined | Map; + + override getTraceType(): TraceType { + return TraceType.SHELL_TRANSITION; + } + + override decodeTrace(traceBuffer: Uint8Array): Transition[] { + const decodedProto = ShellTransitionsTraceFileProto.decode(traceBuffer) as any; + + if (Object.prototype.hasOwnProperty.call(decodedProto, 'realToElapsedTimeOffsetNanos')) { + this.realToElapsedTimeOffsetNs = BigInt(decodedProto.realToElapsedTimeOffsetNanos); + } else { + console.warn('Missing realToElapsedTimeOffsetNanos property on SF trace proto'); + this.realToElapsedTimeOffsetNs = undefined; + } + + this.handlerMapping = new Map(); + for (const mapping of decodedProto.handlerMappings) { + this.handlerMapping.set(mapping.id, mapping.name); + } + + return decodedProto.transitions; + } + + override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: any): any { + return this.parseShellTransitionEntry(entryProto); + } + + private parseShellTransitionEntry(entry: any): Transition { + this.validateShellTransitionEntry(entry); + + if (this.realToElapsedTimeOffsetNs === undefined) { + throw new Error('missing realToElapsedTimeOffsetNs'); + } + + let dispatchTime = null; + if (entry.dispatchTimeNs && BigInt(entry.dispatchTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.dispatchTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + dispatchTime = CrossPlatform.timestamp.fromString( + entry.dispatchTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let mergeRequestTime = null; + if (entry.mergeRequestTimeNs && BigInt(entry.mergeRequestTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.mergeRequestTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + mergeRequestTime = CrossPlatform.timestamp.fromString( + entry.mergeRequestTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let mergeTime = null; + if (entry.mergeTimeNs && BigInt(entry.mergeTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.mergeTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + mergeTime = CrossPlatform.timestamp.fromString( + entry.mergeTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let abortTime = null; + if (entry.abortTimeNs && BigInt(entry.abortTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.abortTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + abortTime = CrossPlatform.timestamp.fromString( + entry.abortTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let mergedInto = null; + if (entry.mergedInto !== 0) { + mergedInto = entry.mergedInto; + } + + if (this.handlerMapping === undefined) { + throw new Error('Missing handler mapping!'); + } + + return new Transition( + entry.id, + new WmTransitionData(), + new ShellTransitionData( + dispatchTime, + mergeRequestTime, + mergeTime, + abortTime, + this.handlerMapping.get(entry.handler), + mergedInto + ) + ); + } + + private validateShellTransitionEntry(entry: any) { + if (entry.id === 0) { + throw new Error('Entry need a non null id'); + } + if ( + !entry.dispatchTimeNs && + !entry.mergeRequestTimeNs && + !entry.mergeTimeNs && + !entry.abortTimeNs + ) { + throw new Error('Requires at least one non-null timestamp'); + } + } + + protected getMagicNumber(): number[] | undefined { + return [0x09, 0x57, 0x4d, 0x53, 0x54, 0x52, 0x41, 0x43, 0x45]; // .WMSTRACE + } + + override getTimestamp(type: TimestampType, decodedEntry: Transition): undefined | Timestamp { + decodedEntry = this.parseShellTransitionEntry(decodedEntry); + + if (type === TimestampType.ELAPSED) { + return new ElapsedTimestamp(BigInt(decodedEntry.timestamp.elapsedNanos.toString())); + } + + if (type === TimestampType.REAL) { + return new RealTimestamp(BigInt(decodedEntry.timestamp.unixNanos.toString())); + } + + throw new Error('Timestamp type unsupported'); + } +} diff --git a/tools/winscope/src/parsers/parser_transitions_shell_test.ts b/tools/winscope/src/parsers/parser_transitions_shell_test.ts new file mode 100644 index 000000000..f986db709 --- /dev/null +++ b/tools/winscope/src/parsers/parser_transitions_shell_test.ts @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from 'trace/parser'; +import {ElapsedTimestamp, RealTimestamp, TimestampType} from 'trace/timestamp'; +import {TraceType} from 'trace/trace_type'; + +describe('ShellFileParserTransitions', () => { + let parser: Parser; + + beforeAll(async () => { + parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/shell_transition_trace.pb' + ); + }); + + it('has expected trace type', () => { + expect(parser.getTraceType()).toEqual(TraceType.SHELL_TRANSITION); + }); + + it('provides elapsed timestamps', () => { + const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; + + expect(timestamps.length).toEqual(6); + + const expected = [ + new ElapsedTimestamp(57649649922341n), + new ElapsedTimestamp(57649829445249n), + new ElapsedTimestamp(57649829526223n), + ]; + expect(timestamps.slice(0, 3)).toEqual(expected); + }); + + it('provides real timestamps', () => { + const expected = [ + new RealTimestamp(1683188477607285317n), + new RealTimestamp(1683188477786808225n), + new RealTimestamp(1683188477786889199n), + ]; + + const timestamps = parser.getTimestamps(TimestampType.REAL)!; + + expect(timestamps.length).toEqual(6); + + expect(timestamps.slice(0, 3)).toEqual(expected); + }); +}); diff --git a/tools/winscope/src/parsers/parser_transitions_test.ts b/tools/winscope/src/parsers/parser_transitions_test.ts deleted file mode 100644 index 27b6642b4..000000000 --- a/tools/winscope/src/parsers/parser_transitions_test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import {UnitTestUtils} from 'test/unit/utils'; -import {Parser} from 'trace/parser'; -import {ElapsedTimestamp, TimestampType} from 'trace/timestamp'; -import {TraceType} from 'trace/trace_type'; - -describe('ParserTransitions', () => { - describe('trace with elapsed (only) timestamp', () => { - let parser: Parser; - - beforeAll(async () => { - parser = await UnitTestUtils.getParser('traces/elapsed_timestamp/Transitions.pb'); - }); - - it('has expected trace type', () => { - expect(parser.getTraceType()).toEqual(TraceType.TRANSITION); - }); - - it('provides elapsed timestamps', () => { - const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; - - expect(timestamps.length).toEqual(7); - - const expected = [ - new ElapsedTimestamp(1862299518404n), - new ElapsedTimestamp(1863412780164n), - new ElapsedTimestamp(1865439877129n), - ]; - 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/src/parsers/parser_transitions_wm.ts b/tools/winscope/src/parsers/parser_transitions_wm.ts new file mode 100644 index 000000000..ee478c0a1 --- /dev/null +++ b/tools/winscope/src/parsers/parser_transitions_wm.ts @@ -0,0 +1,149 @@ +import { + CrossPlatform, + ShellTransitionData, + Transition, + TransitionChange, + TransitionType, + WmTransitionData, +} from 'trace/flickerlib/common'; +import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'trace/timestamp'; +import {TraceType} from 'trace/trace_type'; +import {AbstractParser} from './abstract_parser'; +import {WmTransitionsTraceFileProto} from './proto_types'; + +export class ParserTransitionsWm extends AbstractParser { + private realToElapsedTimeOffsetNs: undefined | bigint; + + override getTraceType(): TraceType { + return TraceType.WM_TRANSITION; + } + + override processDecodedEntry(index: number, timestampType: TimestampType, entryProto: any): any { + return this.parseWmTransitionEntry(entryProto); + } + + override decodeTrace(buffer: Uint8Array): any[] { + const decodedProto = WmTransitionsTraceFileProto.decode(buffer) as any; + if (Object.prototype.hasOwnProperty.call(decodedProto, 'realToElapsedTimeOffsetNanos')) { + this.realToElapsedTimeOffsetNs = BigInt(decodedProto.realToElapsedTimeOffsetNanos); + } else { + console.warn('Missing realToElapsedTimeOffsetNanos property on SF trace proto'); + this.realToElapsedTimeOffsetNs = undefined; + } + return decodedProto.transitions; + } + + override getMagicNumber(): number[] | undefined { + return [0x09, 0x54, 0x52, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45]; // .TRNTRACE + } + + override getTimestamp(type: TimestampType, decodedEntry: Transition): undefined | Timestamp { + decodedEntry = this.parseWmTransitionEntry(decodedEntry); + + if (type === TimestampType.ELAPSED) { + return new ElapsedTimestamp(BigInt(decodedEntry.timestamp.elapsedNanos.toString())); + } + + if (type === TimestampType.REAL) { + return new RealTimestamp(BigInt(decodedEntry.timestamp.unixNanos.toString())); + } + + throw new Error('Timestamp type unsupported'); + } + + private parseWmTransitionEntry(entry: any): Transition { + this.validateWmTransitionEntry(entry); + let changes: TransitionChange[] | null; + if (entry.targets.length === 0) { + changes = null; + } else { + changes = entry.targets.map( + (it: any) => + new TransitionChange(TransitionType.Companion.fromInt(it.mode), it.layerId, it.windowId) + ); + } + + if (this.realToElapsedTimeOffsetNs === undefined) { + throw new Error('missing realToElapsedTimeOffsetNs'); + } + + let createTime = null; + if (entry.createTimeNs && BigInt(entry.createTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.createTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + createTime = CrossPlatform.timestamp.fromString( + entry.createTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let sendTime = null; + if (entry.sendTimeNs && BigInt(entry.sendTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.sendTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + sendTime = CrossPlatform.timestamp.fromString( + entry.sendTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let abortTime = null; + if (entry.abortTimeNs && BigInt(entry.abortTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.abortTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + abortTime = CrossPlatform.timestamp.fromString( + entry.abortTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let finishTime = null; + if (entry.finishTimeNs && BigInt(entry.finishTimeNs.toString()) !== 0n) { + const unixNs = BigInt(entry.finishTimeNs.toString()) + this.realToElapsedTimeOffsetNs; + finishTime = CrossPlatform.timestamp.fromString( + entry.finishTimeNs.toString(), + null, + unixNs.toString() + ); + } + + let startTransactionId = null; + if (entry.startTransactionId !== 0) { + startTransactionId = entry.startTransactionId; + } + + let finishTransactionId = null; + if (entry.finishTransactionId !== 0) { + finishTransactionId = entry.finishTransactionId; + } + + let type = null; + if (entry.type !== 0) { + type = TransitionType.Companion.fromInt(entry.type); + } + + return new Transition( + entry.id, + new WmTransitionData( + createTime, + sendTime, + abortTime, + finishTime, + startTransactionId, + finishTransactionId, + type, + changes + ), + new ShellTransitionData() + ); + } + + private validateWmTransitionEntry(entry: any) { + if (entry.id === 0) { + throw new Error('Entry need a non null id'); + } + if (!entry.createTimeNs && !entry.sendTimeNs && !entry.abortTimeNs && !entry.finishTimeNs) { + throw new Error('Requires at least one non-null timestamp'); + } + } +} diff --git a/tools/winscope/src/parsers/parser_transitions_wm_test.ts b/tools/winscope/src/parsers/parser_transitions_wm_test.ts new file mode 100644 index 000000000..0f0cdd12e --- /dev/null +++ b/tools/winscope/src/parsers/parser_transitions_wm_test.ts @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {UnitTestUtils} from 'test/unit/utils'; +import {Parser} from 'trace/parser'; +import {ElapsedTimestamp, RealTimestamp, TimestampType} from 'trace/timestamp'; +import {TraceType} from 'trace/trace_type'; + +describe('WmFileParserTransitions', () => { + let parser: Parser; + + beforeAll(async () => { + parser = await UnitTestUtils.getParser( + 'traces/elapsed_and_real_timestamp/wm_transition_trace.pb' + ); + }); + + it('has expected trace type', () => { + expect(parser.getTraceType()).toEqual(TraceType.WM_TRANSITION); + }); + + it('provides elapsed timestamps', () => { + const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!; + + expect(timestamps.length).toEqual(8); + + const expected = [ + new ElapsedTimestamp(57649586217344n), + new ElapsedTimestamp(57649691956439n), + new ElapsedTimestamp(57650183020323n), + ]; + expect(timestamps.slice(0, 3)).toEqual(expected); + }); + + it('provides real timestamps', () => { + const expected = [ + new RealTimestamp(1683188477542869667n), + new RealTimestamp(1683188477648608762n), + new RealTimestamp(1683188478139672646n), + ]; + + const timestamps = parser.getTimestamps(TimestampType.REAL)!; + + expect(timestamps.length).toEqual(8); + + expect(timestamps.slice(0, 3)).toEqual(expected); + }); +}); diff --git a/tools/winscope/src/parsers/proto_types.js b/tools/winscope/src/parsers/proto_types.js index 9ab722600..3152bd89e 100644 --- a/tools/winscope/src/parsers/proto_types.js +++ b/tools/winscope/src/parsers/proto_types.js @@ -22,8 +22,9 @@ protobuf.configure(); import protoLogJson from 'frameworks/base/core/proto/android/internal/protolog.proto'; import accessibilityJson from 'frameworks/base/core/proto/android/server/accessibilitytrace.proto'; import windowManagerJson from 'frameworks/base/core/proto/android/server/windowmanagertrace.proto'; -import transitionsJson from 'frameworks/base/core/proto/android/server/windowmanagertransitiontrace.proto'; +import wmTransitionsJson from 'frameworks/base/core/proto/android/server/windowmanagertransitiontrace.proto'; import inputMethodClientsJson from 'frameworks/base/core/proto/android/view/inputmethod/inputmethodeditortrace.proto'; +import shellTransitionsJson from 'frameworks/base/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto'; import layersJson from 'frameworks/native/services/surfaceflinger/layerproto/layerstrace.proto'; import transactionsJson from 'frameworks/native/services/surfaceflinger/layerproto/transactions.proto'; @@ -54,9 +55,12 @@ const WindowManagerServiceDumpProto = protobuf.Root.fromJSON(windowManagerJson). const WindowManagerTraceFileProto = protobuf.Root.fromJSON(windowManagerJson).lookupType( 'com.android.server.wm.WindowManagerTraceFileProto' ); -const TransitionsTraceFileProto = protobuf.Root.fromJSON(transitionsJson).lookupType( +const WmTransitionsTraceFileProto = protobuf.Root.fromJSON(wmTransitionsJson).lookupType( 'com.android.server.wm.shell.TransitionTraceProto' ); +const ShellTransitionsTraceFileProto = protobuf.Root.fromJSON(shellTransitionsJson).lookupType( + 'com.android.wm.shell.WmShellTransitionTraceProto' +); export { AccessibilityTraceFileProto, @@ -68,5 +72,6 @@ export { TransactionsTraceFileProto, WindowManagerServiceDumpProto, WindowManagerTraceFileProto, - TransitionsTraceFileProto, + WmTransitionsTraceFileProto, + ShellTransitionsTraceFileProto, }; diff --git a/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/shell_transition_trace.pb b/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/shell_transition_trace.pb new file mode 100644 index 000000000..e49d7e15a --- /dev/null +++ b/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/shell_transition_trace.pb @@ -0,0 +1,2 @@ + WMSTRACE   +8   0    ( 0  073com.android.wm.shell.transition.DefaultMixedHandler95com.android.wm.shell.recents.RecentsTransitionHandler! a[ \ No newline at end of file diff --git a/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/wm_transition_trace.pb b/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/wm_transition_trace.pb new file mode 100644 index 000000000..f721d527c --- /dev/null +++ b/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/wm_transition_trace.pb @@ -0,0 +1,7 @@ + TRNTRACE#[? ( 8B +֒XB  qUF ש ( 8B ۉ/B  +0  +0 D ( 񇀀8HB  @qUB +֒XC Ъ (ÿ  8B @B  qU +0â  + 0܊ \ No newline at end of file diff --git a/tools/winscope/src/trace/flickerlib/common.js b/tools/winscope/src/trace/flickerlib/common.js index 5d4f01ddb..7cce4678d 100644 --- a/tools/winscope/src/trace/flickerlib/common.js +++ b/tools/winscope/src/trace/flickerlib/common.js @@ -67,6 +67,9 @@ const EventLogParser = require('flicker').android.tools.common.parsers.events.Ev const Transition = require('flicker').android.tools.common.traces.wm.Transition; const TransitionType = require('flicker').android.tools.common.traces.wm.TransitionType; const TransitionChange = require('flicker').android.tools.common.traces.wm.TransitionChange; +const TransitionsTrace = require('flicker').android.tools.common.traces.wm.TransitionsTrace; +const ShellTransitionData = require('flicker').android.tools.common.traces.wm.ShellTransitionData; +const WmTransitionData = require('flicker').android.tools.common.traces.wm.WmTransitionData; // Common const Size = require('flicker').android.tools.common.datatypes.Size; @@ -314,6 +317,9 @@ export { Transition, TransitionType, TransitionChange, + TransitionsTrace, + ShellTransitionData, + WmTransitionData, // Common Size, ActiveBuffer, diff --git a/tools/winscope/src/trace/trace_type.ts b/tools/winscope/src/trace/trace_type.ts index c721941ea..6175c1205 100644 --- a/tools/winscope/src/trace/trace_type.ts +++ b/tools/winscope/src/trace/trace_type.ts @@ -36,7 +36,8 @@ export enum TraceType { INPUT_METHOD_MANAGER_SERVICE, INPUT_METHOD_SERVICE, EVENT_LOG, - TRANSITION, + WM_TRANSITION, + SHELL_TRANSITION, TAG, ERROR, TEST_TRACE_STRING, @@ -59,7 +60,8 @@ export interface TraceEntryTypeMap { [TraceType.INPUT_METHOD_MANAGER_SERVICE]: object; [TraceType.INPUT_METHOD_SERVICE]: object; [TraceType.EVENT_LOG]: Event; - [TraceType.TRANSITION]: Transition; + [TraceType.WM_TRANSITION]: object; + [TraceType.SHELL_TRANSITION]: object; [TraceType.TAG]: object; [TraceType.ERROR]: object; [TraceType.TEST_TRACE_STRING]: string;