Merge "Add CUJ trace parser to Winscope" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
aaa8dcd1f7
@@ -30,6 +30,7 @@ const TAG_ICON = 'details';
|
|||||||
const TRACE_ERROR_ICON = 'warning';
|
const TRACE_ERROR_ICON = 'warning';
|
||||||
const EVENT_LOG_ICON = 'description';
|
const EVENT_LOG_ICON = 'description';
|
||||||
const TRANSITION_ICON = 'animation';
|
const TRANSITION_ICON = 'animation';
|
||||||
|
const CUJ_ICON = 'label';
|
||||||
|
|
||||||
interface TraceInfoMap {
|
interface TraceInfoMap {
|
||||||
[key: number]: {
|
[key: number]: {
|
||||||
@@ -161,4 +162,10 @@ export const TRACE_INFO: TraceInfoMap = {
|
|||||||
color: '#EC407A',
|
color: '#EC407A',
|
||||||
downloadArchiveDir: 'transition',
|
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 {FunctionUtils, OnProgressUpdateType} from 'common/function_utils';
|
||||||
import {ParserError, ParserFactory} from 'parsers/parser_factory';
|
import {ParserError, ParserFactory} from 'parsers/parser_factory';
|
||||||
|
import {TracesParserCujs} from 'parsers/traces_parser_cujs';
|
||||||
import {TracesParserTransitions} from 'parsers/traces_parser_transitions';
|
import {TracesParserTransitions} from 'parsers/traces_parser_transitions';
|
||||||
import {FrameMapper} from 'trace/frame_mapper';
|
import {FrameMapper} from 'trace/frame_mapper';
|
||||||
import {LoadedTrace} from 'trace/loaded_trace';
|
import {LoadedTrace} from 'trace/loaded_trace';
|
||||||
@@ -43,9 +44,14 @@ class TracePipeline {
|
|||||||
);
|
);
|
||||||
this.parsers = parsers.map((it) => it.parser);
|
this.parsers = parsers.map((it) => it.parser);
|
||||||
|
|
||||||
const tracesParser = new TracesParserTransitions(this.parsers);
|
const tracesParsers = [
|
||||||
if (tracesParser.canProvideEntries()) {
|
new TracesParserTransitions(this.parsers),
|
||||||
this.parsers.push(tracesParser);
|
new TracesParserCujs(this.parsers),
|
||||||
|
];
|
||||||
|
for (const tracesParser of tracesParsers) {
|
||||||
|
if (tracesParser.canProvideEntries()) {
|
||||||
|
this.parsers.push(tracesParser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const parser of parsers) {
|
for (const parser of parsers) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {Timestamp, TimestampType} from 'trace/timestamp';
|
|||||||
import {TraceFile} from 'trace/trace_file';
|
import {TraceFile} from 'trace/trace_file';
|
||||||
import {TraceType} from 'trace/trace_type';
|
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 traceFile: TraceFile;
|
||||||
protected decodedEntries: any[] = [];
|
protected decodedEntries: any[] = [];
|
||||||
private timestamps: Map<TimestampType, Timestamp[]> = new Map<TimestampType, Timestamp[]>();
|
private timestamps: Map<TimestampType, Timestamp[]> = new Map<TimestampType, Timestamp[]>();
|
||||||
@@ -78,7 +78,7 @@ abstract class AbstractParser implements Parser<object> {
|
|||||||
return this.timestamps.get(type);
|
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]);
|
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 {TraceType} from 'trace/trace_type';
|
||||||
import {AbstractParser} from './abstract_parser';
|
import {AbstractParser} from './abstract_parser';
|
||||||
|
|
||||||
class ParserEventLog extends AbstractParser {
|
class ParserEventLog extends AbstractParser<Event> {
|
||||||
override getTraceType(): TraceType {
|
override getTraceType(): TraceType {
|
||||||
return TraceType.EVENT_LOG;
|
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 FlickerEvent = require('flicker').android.tools.common.traces.events.FlickerEvent;
|
||||||
const FocusEvent = require('flicker').android.tools.common.traces.events.FocusEvent;
|
const FocusEvent = require('flicker').android.tools.common.traces.events.FocusEvent;
|
||||||
const EventLogParser = require('flicker').android.tools.common.parsers.events.EventLogParser;
|
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
|
// Transitions
|
||||||
const Transition = require('flicker').android.tools.common.traces.wm.Transition;
|
const Transition = require('flicker').android.tools.common.traces.wm.Transition;
|
||||||
@@ -313,6 +315,8 @@ export {
|
|||||||
FlickerEvent,
|
FlickerEvent,
|
||||||
FocusEvent,
|
FocusEvent,
|
||||||
EventLogParser,
|
EventLogParser,
|
||||||
|
CujTrace,
|
||||||
|
Cuj,
|
||||||
// Transitions
|
// Transitions
|
||||||
Transition,
|
Transition,
|
||||||
TransitionType,
|
TransitionType,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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 {LayerTraceEntry} from './flickerlib/layers/LayerTraceEntry';
|
||||||
import {WindowManagerState} from './flickerlib/windows/WindowManagerState';
|
import {WindowManagerState} from './flickerlib/windows/WindowManagerState';
|
||||||
import {LogMessage} from './protolog';
|
import {LogMessage} from './protolog';
|
||||||
@@ -38,6 +38,7 @@ export enum TraceType {
|
|||||||
WM_TRANSITION,
|
WM_TRANSITION,
|
||||||
SHELL_TRANSITION,
|
SHELL_TRANSITION,
|
||||||
TRANSITION,
|
TRANSITION,
|
||||||
|
CUJS,
|
||||||
TAG,
|
TAG,
|
||||||
ERROR,
|
ERROR,
|
||||||
TEST_TRACE_STRING,
|
TEST_TRACE_STRING,
|
||||||
@@ -63,6 +64,7 @@ export interface TraceEntryTypeMap {
|
|||||||
[TraceType.WM_TRANSITION]: object;
|
[TraceType.WM_TRANSITION]: object;
|
||||||
[TraceType.SHELL_TRANSITION]: object;
|
[TraceType.SHELL_TRANSITION]: object;
|
||||||
[TraceType.TRANSITION]: Transition;
|
[TraceType.TRANSITION]: Transition;
|
||||||
|
[TraceType.CUJS]: Cuj;
|
||||||
[TraceType.TAG]: object;
|
[TraceType.TAG]: object;
|
||||||
[TraceType.ERROR]: object;
|
[TraceType.ERROR]: object;
|
||||||
[TraceType.TEST_TRACE_STRING]: string;
|
[TraceType.TEST_TRACE_STRING]: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user