Add CUJ trace parser to Winscope
Bug: 265791272 Test: npm run test:all Change-Id: Ibb62236c405ab44caf94c9ac66ef34cbef4a0111
This commit is contained in:
@@ -30,6 +30,7 @@ const TAG_ICON = 'details';
|
||||
const TRACE_ERROR_ICON = 'warning';
|
||||
const EVENT_LOG_ICON = 'description';
|
||||
const TRANSITION_ICON = 'animation';
|
||||
const CUJ_ICON = 'label';
|
||||
|
||||
interface TraceInfoMap {
|
||||
[key: number]: {
|
||||
@@ -161,4 +162,10 @@ export const TRACE_INFO: TraceInfoMap = {
|
||||
color: '#EC407A',
|
||||
downloadArchiveDir: 'transition',
|
||||
},
|
||||
[TraceType.CUJS]: {
|
||||
name: 'Cujs',
|
||||
icon: CUJ_ICON,
|
||||
color: '#EC407A',
|
||||
downloadArchiveDir: 'eventlog',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import {FunctionUtils, OnProgressUpdateType} from 'common/function_utils';
|
||||
import {ParserError, ParserFactory} from 'parsers/parser_factory';
|
||||
import {TracesParserCujs} from 'parsers/traces_parser_cujs';
|
||||
import {TracesParserTransitions} from 'parsers/traces_parser_transitions';
|
||||
import {FrameMapper} from 'trace/frame_mapper';
|
||||
import {LoadedTrace} from 'trace/loaded_trace';
|
||||
@@ -43,9 +44,14 @@ class TracePipeline {
|
||||
);
|
||||
this.parsers = parsers.map((it) => it.parser);
|
||||
|
||||
const tracesParser = new TracesParserTransitions(this.parsers);
|
||||
if (tracesParser.canProvideEntries()) {
|
||||
this.parsers.push(tracesParser);
|
||||
const tracesParsers = [
|
||||
new TracesParserTransitions(this.parsers),
|
||||
new TracesParserCujs(this.parsers),
|
||||
];
|
||||
for (const tracesParser of tracesParsers) {
|
||||
if (tracesParser.canProvideEntries()) {
|
||||
this.parsers.push(tracesParser);
|
||||
}
|
||||
}
|
||||
|
||||
for (const parser of parsers) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import {Timestamp, TimestampType} from 'trace/timestamp';
|
||||
import {TraceFile} from 'trace/trace_file';
|
||||
import {TraceType} from 'trace/trace_type';
|
||||
|
||||
abstract class AbstractParser implements Parser<object> {
|
||||
abstract class AbstractParser<T extends object = object> implements Parser<object> {
|
||||
protected traceFile: TraceFile;
|
||||
protected decodedEntries: any[] = [];
|
||||
private timestamps: Map<TimestampType, Timestamp[]> = new Map<TimestampType, Timestamp[]>();
|
||||
@@ -78,7 +78,7 @@ abstract class AbstractParser implements Parser<object> {
|
||||
return this.timestamps.get(type);
|
||||
}
|
||||
|
||||
getEntry(index: number, timestampType: TimestampType): object {
|
||||
getEntry(index: number, timestampType: TimestampType): T {
|
||||
return this.processDecodedEntry(index, timestampType, this.decodedEntries[index]);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {RealTimestamp, Timestamp, TimestampType} from 'trace/timestamp';
|
||||
import {TraceType} from 'trace/trace_type';
|
||||
import {AbstractParser} from './abstract_parser';
|
||||
|
||||
class ParserEventLog extends AbstractParser {
|
||||
class ParserEventLog extends AbstractParser<Event> {
|
||||
override getTraceType(): TraceType {
|
||||
return TraceType.EVENT_LOG;
|
||||
}
|
||||
|
||||
90
tools/winscope/src/parsers/traces_parser_cujs.ts
Normal file
90
tools/winscope/src/parsers/traces_parser_cujs.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 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 {Cuj, CujTrace, EventLog, Transition} from 'trace/flickerlib/common';
|
||||
import {Parser} from 'trace/parser';
|
||||
import {Timestamp, TimestampType} from 'trace/timestamp';
|
||||
import {TraceType} from 'trace/trace_type';
|
||||
import {AbstractTracesParser} from './abstract_traces_parser';
|
||||
import {ParserEventLog} from './parser_eventlog';
|
||||
|
||||
export class TracesParserCujs extends AbstractTracesParser<Transition> {
|
||||
private readonly eventLogTrace: ParserEventLog | undefined;
|
||||
private readonly descriptors: string[];
|
||||
|
||||
constructor(parsers: Array<Parser<object>>) {
|
||||
super(parsers);
|
||||
|
||||
const eventlogTraces = this.parsers.filter((it) => it.getTraceType() === TraceType.EVENT_LOG);
|
||||
if (eventlogTraces.length > 0) {
|
||||
this.eventLogTrace = eventlogTraces[0] as ParserEventLog;
|
||||
}
|
||||
|
||||
if (this.eventLogTrace !== undefined) {
|
||||
this.descriptors = this.eventLogTrace.getDescriptors();
|
||||
} else {
|
||||
this.descriptors = [];
|
||||
}
|
||||
}
|
||||
|
||||
override canProvideEntries(): boolean {
|
||||
return this.eventLogTrace !== undefined;
|
||||
}
|
||||
|
||||
getLengthEntries(): number {
|
||||
return this.getDecodedEntries().length;
|
||||
}
|
||||
|
||||
getEntry(index: number, timestampType: TimestampType): Transition {
|
||||
return this.getDecodedEntries()[index];
|
||||
}
|
||||
|
||||
private cujTrace: CujTrace | undefined;
|
||||
getDecodedEntries(): Cuj[] {
|
||||
if (this.eventLogTrace === undefined) {
|
||||
throw new Error('eventLogTrace not defined');
|
||||
}
|
||||
|
||||
if (this.cujTrace === undefined) {
|
||||
const events: Event[] = [];
|
||||
|
||||
for (let i = 0; i < this.eventLogTrace.getLengthEntries(); i++) {
|
||||
events.push(this.eventLogTrace.getEntry(i, TimestampType.REAL));
|
||||
}
|
||||
|
||||
this.cujTrace = new EventLog(events).cujTrace;
|
||||
}
|
||||
|
||||
return this.cujTrace.entries;
|
||||
}
|
||||
|
||||
override getDescriptors(): string[] {
|
||||
return this.descriptors;
|
||||
}
|
||||
|
||||
getTraceType(): TraceType {
|
||||
return TraceType.CUJS;
|
||||
}
|
||||
|
||||
override getTimestamp(type: TimestampType, transition: Transition): undefined | Timestamp {
|
||||
if (type === TimestampType.ELAPSED) {
|
||||
return new Timestamp(type, BigInt(transition.timestamp.elapsedNanos.toString()));
|
||||
} else if (type === TimestampType.REAL) {
|
||||
return new Timestamp(type, BigInt(transition.timestamp.unixNanos.toString()));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
66
tools/winscope/src/parsers/traces_parser_cujs_test.ts
Normal file
66
tools/winscope/src/parsers/traces_parser_cujs_test.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 {assertDefined} from 'common/assert_utils';
|
||||
import {UnitTestUtils} from 'test/unit/utils';
|
||||
import {Cuj} from 'trace/flickerlib/common';
|
||||
import {Parser} from 'trace/parser';
|
||||
import {Timestamp, TimestampType} from 'trace/timestamp';
|
||||
import {TraceType} from 'trace/trace_type';
|
||||
import {TracesParserCujs} from './traces_parser_cujs';
|
||||
|
||||
describe('ParserCujs', () => {
|
||||
let parser: Parser<Cuj>;
|
||||
|
||||
beforeAll(async () => {
|
||||
const eventLogParser = assertDefined(
|
||||
await UnitTestUtils.getParser('traces/eventlog.winscope')
|
||||
) as Parser<Event>;
|
||||
|
||||
parser = new TracesParserCujs([eventLogParser]);
|
||||
});
|
||||
|
||||
it('has expected trace type', () => {
|
||||
expect(parser.getTraceType()).toEqual(TraceType.CUJS);
|
||||
});
|
||||
|
||||
it('provides elapsed timestamps', () => {
|
||||
const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!;
|
||||
|
||||
expect(timestamps.length).toEqual(16);
|
||||
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 2661012770462n),
|
||||
new Timestamp(TimestampType.ELAPSED, 2661012874914n),
|
||||
new Timestamp(TimestampType.ELAPSED, 2661012903966n),
|
||||
];
|
||||
expect(timestamps.slice(0, 3)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('provides real timestamps', () => {
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.REAL, 1681207048025446000n),
|
||||
new Timestamp(TimestampType.REAL, 1681207048025551000n),
|
||||
new Timestamp(TimestampType.REAL, 1681207048025580000n),
|
||||
];
|
||||
|
||||
const timestamps = parser.getTimestamps(TimestampType.REAL)!;
|
||||
|
||||
expect(timestamps.length).toEqual(16);
|
||||
|
||||
expect(timestamps.slice(0, 3)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -62,6 +62,8 @@ const Event = require('flicker').android.tools.common.traces.events.Event;
|
||||
const FlickerEvent = require('flicker').android.tools.common.traces.events.FlickerEvent;
|
||||
const FocusEvent = require('flicker').android.tools.common.traces.events.FocusEvent;
|
||||
const EventLogParser = require('flicker').android.tools.common.parsers.events.EventLogParser;
|
||||
const CujTrace = require('flicker').android.tools.common.parsers.events.CujTrace;
|
||||
const Cuj = require('flicker').android.tools.common.parsers.events.Cuj;
|
||||
|
||||
// Transitions
|
||||
const Transition = require('flicker').android.tools.common.traces.wm.Transition;
|
||||
@@ -313,6 +315,8 @@ export {
|
||||
FlickerEvent,
|
||||
FocusEvent,
|
||||
EventLogParser,
|
||||
CujTrace,
|
||||
Cuj,
|
||||
// Transitions
|
||||
Transition,
|
||||
TransitionType,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {Event, Transition} from 'trace/flickerlib/common';
|
||||
import {Cuj, Event, Transition} from 'trace/flickerlib/common';
|
||||
import {LayerTraceEntry} from './flickerlib/layers/LayerTraceEntry';
|
||||
import {WindowManagerState} from './flickerlib/windows/WindowManagerState';
|
||||
import {LogMessage} from './protolog';
|
||||
@@ -38,6 +38,7 @@ export enum TraceType {
|
||||
WM_TRANSITION,
|
||||
SHELL_TRANSITION,
|
||||
TRANSITION,
|
||||
CUJS,
|
||||
TAG,
|
||||
ERROR,
|
||||
TEST_TRACE_STRING,
|
||||
@@ -63,6 +64,7 @@ export interface TraceEntryTypeMap {
|
||||
[TraceType.WM_TRANSITION]: object;
|
||||
[TraceType.SHELL_TRANSITION]: object;
|
||||
[TraceType.TRANSITION]: Transition;
|
||||
[TraceType.CUJS]: Cuj;
|
||||
[TraceType.TAG]: object;
|
||||
[TraceType.ERROR]: object;
|
||||
[TraceType.TEST_TRACE_STRING]: string;
|
||||
|
||||
Reference in New Issue
Block a user