Merge changes from topic "traces-with-realtime"

* changes:
  add support for traces real timestamp
  refactor test code
  refactor Parser's interface
  parser for new screen recording metadata
This commit is contained in:
Kean Mariotti
2022-08-10 16:27:43 +00:00
committed by Android (Google) Code Review
63 changed files with 1413 additions and 386 deletions

View File

@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, Injector, Inject } from "@angular/core";
import { createCustomElement } from "@angular/elements";
import { ViewerWindowManagerComponent } from "viewers/viewer_window_manager/viewer_window_manager.component";
import { Core } from "./core";
import { ProxyState } from "trace_collection/proxy_client";
import { PersistentStore } from "../common/persistent_store";
import {Component, Inject, Injector} from "@angular/core";
import {createCustomElement} from "@angular/elements";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {PersistentStore} from "common/persistent_store";
import {ViewerWindowManagerComponent} from "viewers/viewer_window_manager/viewer_window_manager.component";
import {Core} from "./core";
import {ProxyState} from "trace_collection/proxy_client";
@Component({
selector: "app-root",
@@ -81,7 +82,7 @@ export class AppComponent {
}
public notifyCurrentTimestamp() {
const dummyTimestamp = 1000000; //TODO: get timestamp from time scrub
const dummyTimestamp = new Timestamp(TimestampType.ELAPSED, 1000000n);
this.core.notifyCurrentTimestamp(dummyTimestamp);
}

View File

@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "parsers/parser";
import {ParserFactory} from "parsers/parser_factory";
import { setTraces } from "trace_collection/set_traces";
@@ -35,10 +36,10 @@ class Core {
this.parsers = await new ParserFactory().createParsers(traces);
console.log("created parsers: ", this.parsers);
const activeTraceTypes = this.parsers.map(parser => parser.getTraceTypeId());
const activeTraceTypes = this.parsers.map(parser => parser.getTraceType());
console.log("active trace types: ", activeTraceTypes);
this.viewers = new ViewerFactory().createViewers(new Set<TraceTypeId>(activeTraceTypes));
this.viewers = new ViewerFactory().createViewers(new Set<TraceType>(activeTraceTypes));
console.log("created viewers: ", this.viewers);
}
@@ -46,27 +47,37 @@ class Core {
return this.viewers.map(viewer => viewer.getView());
}
getTimestamps(): number[] {
const mergedTimestamps: number[] = [];
getTimestamps(): Timestamp[] {
for (const type of [TimestampType.REAL, TimestampType.ELAPSED]) {
const mergedTimestamps: Timestamp[] = [];
this.parsers
.map(parser => parser.getTimestamps())
.forEach(timestamps => {
mergedTimestamps.push(...timestamps);
});
let isTypeProvidedByAllParsers = true;
const uniqueTimestamps = [... new Set<number>(mergedTimestamps)];
for(const timestamps of this.parsers.map(parser => parser.getTimestamps(type))) {
if (timestamps === undefined) {
isTypeProvidedByAllParsers = false;
break;
}
mergedTimestamps.push(...timestamps!);
}
return uniqueTimestamps;
if (isTypeProvidedByAllParsers) {
const uniqueTimestamps = [... new Set<Timestamp>(mergedTimestamps)];
uniqueTimestamps.sort();
return uniqueTimestamps;
}
}
throw new Error("Failed to create aggregated timestamps (any type)");
}
notifyCurrentTimestamp(timestamp: number) {
const traceEntries: Map<TraceTypeId, any> = new Map<TraceTypeId, any>();
notifyCurrentTimestamp(timestamp: Timestamp) {
const traceEntries: Map<TraceType, any> = new Map<TraceType, any>();
this.parsers.forEach(parser => {
const entry = parser.getTraceEntry(timestamp);
if (entry != undefined) {
traceEntries.set(parser.getTraceTypeId(), entry);
traceEntries.set(parser.getTraceType(), entry);
}
});

View File

@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class ScreenRecordingTraceEntry {
constructor(public timestamp: number,
public videoTimeSeconds: number,
constructor(public videoTimeSeconds: number,
public videoData: Blob) {
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2022 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.
*/
enum TimestampType {
ELAPSED,
REAL,
}
class Timestamp {
constructor(type: TimestampType, valueNs: bigint) {
this.type = type;
this.valueNs = valueNs;
}
public getType(): TimestampType {
return this.type;
}
public getValueNs(): bigint {
return this.valueNs;
}
public valueOf(): bigint {
return this.getValueNs();
}
private readonly type: TimestampType;
private readonly valueNs: bigint;
}
export {Timestamp, TimestampType};

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
enum TraceTypeId {
enum TraceType {
ACCESSIBILITY,
WINDOW_MANAGER,
SURFACE_FLINGER,
@@ -32,4 +32,4 @@ enum TraceTypeId {
ERROR,
}
export {TraceTypeId};
export {TraceType};

View File

@@ -81,15 +81,74 @@ describe("ArrayUtils", () => {
it("toUintLittleEndian", () => {
const buffer = new Uint8Array([0, 0, 1, 1]);
expect(ArrayUtils.toUintLittleEndian(buffer, 0, -1)).toEqual(0);
expect(ArrayUtils.toUintLittleEndian(buffer, 0, 0)).toEqual(0);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff]), 0, -1)).toEqual(0n);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff]), 0, 0)).toEqual(0n);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff]), 1, 1)).toEqual(0n);
expect(ArrayUtils.toUintLittleEndian(buffer, 0, 1)).toEqual(0);
expect(ArrayUtils.toUintLittleEndian(buffer, 0, 2)).toEqual(0);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0x00, 0x01, 0xff]), 0, 1)).toEqual(0n);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0x00, 0x01, 0xff]), 1, 2)).toEqual(1n);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0x00, 0x01, 0xff]), 2, 3)).toEqual(255n);
expect(ArrayUtils.toUintLittleEndian(buffer, 3, 4)).toEqual(1);
expect(ArrayUtils.toUintLittleEndian(buffer, 2, 4)).toEqual(1 + 256);
expect(ArrayUtils.toUintLittleEndian(buffer, 1, 4)).toEqual(256 + 256*256);
expect(ArrayUtils.toUintLittleEndian(buffer, 0, 3)).toEqual(256*256);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0x00, 0x00]), 0, 2)).toEqual(0n);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0x01, 0x00]), 0, 2)).toEqual(1n);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0x00, 0x01]), 0, 2)).toEqual(256n);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff]), 0, 2)).toEqual(0xffffn);
expect(ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff]), 0, 4)).toEqual(0xffffffffn);
expect(
ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 8))
.toEqual(0xffffffffffffffffn);
expect(
ArrayUtils.toUintLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 9))
.toEqual(0xffffffffffffffffffn);
});
it("toIntLittleEndian", () => {
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff]), 0, -1)).toEqual(0n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff]), 0, 0)).toEqual(0n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x00]), 0, 1)).toEqual(0n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x01]), 0, 1)).toEqual(1n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x7f]), 0, 1)).toEqual(127n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x80]), 0, 1)).toEqual(-128n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff]), 0, 1)).toEqual(-1n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0x7f]), 0, 2)).toEqual(32767n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x80]), 0, 2)).toEqual(-32768n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x80]), 0, 2)).toEqual(-32767n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff]), 0, 2)).toEqual(-1n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0x7f]), 0, 4)).toEqual(0x7fffffffn);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x00, 0x00, 0x80]), 0, 4)).toEqual(-0x80000000n);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x00, 0x00, 0x80]), 0, 4)).toEqual(-0x7fffffffn);
expect(ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff]), 0, 4)).toEqual(-1n);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), 0, 8)
).toEqual(0x7fffffffffffffffn);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 8)
).toEqual(-0x8000000000000000n);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 8)
).toEqual(-0x7fffffffffffffffn);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 8)
).toEqual(-1n);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), 0, 9)
).toEqual(0x7fffffffffffffffffn);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 9)
).toEqual(-0x800000000000000000n);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), 0, 9)
).toEqual(-0x7fffffffffffffffffn);
expect(
ArrayUtils.toIntLittleEndian(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0, 9)
).toEqual(-1n);
});
});

View File

@@ -86,14 +86,30 @@ class ArrayUtils {
return result;
}
static toUintLittleEndian(buffer: Uint8Array, start: number, end: number) {
let result = 0;
for (let i = end-1; i>=start; --i) {
result *= 256;
result += buffer[i];
static toUintLittleEndian(buffer: Uint8Array, start: number, end: number): bigint {
let result = 0n;
for (let i = end-1; i >= start; --i) {
result *= 256n;
result += BigInt(buffer[i]);
}
return result;
}
static toIntLittleEndian(buffer: Uint8Array, start: number, end: number): bigint {
const numOfBits = BigInt(Math.max(0, 8 * (end-start)));
if (numOfBits <= 0n) {
return 0n;
}
let result = ArrayUtils.toUintLittleEndian(buffer, start, end);
const maxSignedValue = 2n ** (numOfBits - 1n) - 1n;
if (result > maxSignedValue) {
const valuesRange = 2n ** numOfBits;
result -= valuesRange;
}
return result;
}
}
export {ArrayUtils};

View File

@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {ArrayUtils} from "../common/utils/array_utils";
import {TraceTypeId} from "common/trace/type_id";
import {ArrayUtils} from "common/utils/array_utils";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
abstract class Parser {
protected constructor(trace: Blob) {
@@ -34,17 +35,39 @@ abstract class Parser {
}
this.decodedEntries = this.decodeTrace(traceBuffer);
this.timestamps = this.decodedEntries.map((entry: any) => this.getTimestamp(entry));
for (const type of [TimestampType.ELAPSED, TimestampType.REAL]) {
const timestamps: Timestamp[] = [];
let areTimestampsValid = true;
for (const entry of this.decodedEntries) {
const timestamp = this.getTimestamp(type, entry);
if (timestamp === undefined) {
areTimestampsValid = false;
break;
}
timestamps.push(timestamp);
}
if (areTimestampsValid) {
this.timestamps.set(type, timestamps);
}
}
}
public abstract getTraceTypeId(): TraceTypeId;
public abstract getTraceType(): TraceType;
public getTimestamps(): number[] {
return this.timestamps;
public getTimestamps(type: TimestampType): undefined|Timestamp[] {
return this.timestamps.get(type);
}
public getTraceEntry(timestamp: number): undefined|any {
const index = ArrayUtils.binarySearchLowerOrEqual(this.getTimestamps(), timestamp);
public getTraceEntry(timestamp: Timestamp): undefined|any {
const timestamps = this.getTimestamps(timestamp.getType());
if (timestamps === undefined) {
throw TypeError(`Timestamps with type "${timestamp.getType()}" not available`);
}
const index = ArrayUtils.binarySearchLowerOrEqual(timestamps, timestamp);
if (index === undefined) {
return undefined;
}
@@ -59,12 +82,12 @@ abstract class Parser {
protected abstract getMagicNumber(): undefined|number[];
protected abstract decodeTrace(trace: Uint8Array): any[];
protected abstract getTimestamp(decodedEntry: any): number;
protected abstract getTimestamp(type: TimestampType, decodedEntry: any): undefined|Timestamp;
protected abstract processDecodedEntry(decodedEntry: any): any;
protected trace: Blob;
protected decodedEntries: any[] = [];
protected timestamps: number[] = [];
private timestamps: Map<TimestampType, Timestamp[]> = new Map<TimestampType, Timestamp[]>();
}
export {Parser};

View File

@@ -13,32 +13,75 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {ParserFactory} from "./parser_factory";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("ParserAccessibility", () => {
let parser: Parser;
describe("trace with elapsed + real timestamp", () => {
let parser: Parser;
beforeAll(async () => {
const trace = TestUtils.getFixtureBlob("trace_Accessibility.pb");
const parsers = await new ParserFactory().createParsers([trace]);
expect(parsers.length).toEqual(1);
parser = parsers[0];
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.getTraceTypeId()).toEqual(TraceTypeId.ACCESSIBILITY);
});
describe("trace with elapsed (only) timestamp", () => {
let parser: Parser;
it("provides timestamps", () => {
expect(parser.getTimestamps())
.toEqual([850297444302, 850297882046, 850756176154, 850773581835]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/Accessibility.pb");
});
it("retrieves trace entry", () => {
expect(Number(parser.getTraceEntry(850297444302)!.elapsedRealtimeNanos))
.toEqual(850297444302);
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);
});
});
});

View File

@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {AccessibilityTraceFileProto} from "./proto_types";
class ParserAccessibility extends Parser {
constructor(trace: Blob) {
super(trace);
this.realToElapsedTimeOffsetNs = undefined;
}
override getTraceTypeId(): TraceTypeId {
return TraceTypeId.ACCESSIBILITY;
override getTraceType(): TraceType {
return TraceType.ACCESSIBILITY;
}
override getMagicNumber(): number[] {
@@ -31,17 +33,31 @@ class ParserAccessibility extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
return (<any>AccessibilityTraceFileProto.decode(buffer)).entry;
const decoded = <any>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): number {
return Number(entryProto.elapsedRealtimeNanos);
override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type === TimestampType.ELAPSED) {
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
}

View File

@@ -13,48 +13,98 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {ParserFactory} from "./parser_factory";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {Parser} from "./parser";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("Parser", () => {
let parser: Parser;
describe("real timestamp", () => {
let parser: Parser;
beforeAll(async () => {
const buffer = TestUtils.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 timestamps", () => {
expect(parser.getTimestamps())
.toEqual([850254319343, 850763506110, 850782750048]);
});
describe("elapsed timestamp", () => {
let parser: Parser;
it("retrieves trace entry (no timestamp matches)", () => {
expect(parser.getTraceEntry(850254319342))
.toEqual(undefined);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/WindowManager.pb");
});
it("retrieves trace entry (equal timestamp matches)", () => {
expect(Number(parser.getTraceEntry(850254319343)!.timestampMs))
.toEqual(850254319343);
});
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)", () => {
expect(Number(parser.getTraceEntry(850763506110)!.timestampMs))
.toEqual(850763506110);
});
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)", () => {
expect(Number(parser.getTraceEntry(850254319344)!.timestampMs))
.toEqual(850254319343);
});
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)", () => {
expect(Number(parser.getTraceEntry(850763506111)!.timestampMs))
.toEqual(850763506110);
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);
});
});
});

View File

@@ -20,6 +20,7 @@ import {ParserInputMethodManagerService} from "./parser_input_method_manager_ser
import {ParserInputMethodService} from "./parser_input_method_service";
import {ParserProtoLog} from "./parser_protolog";
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 {ParserWindowManager} from "./parser_window_manager";
@@ -33,6 +34,7 @@ class ParserFactory {
ParserInputMethodService,
ParserProtoLog,
ParserScreenRecording,
ParserScreenRecordingLegacy,
ParserSurfaceFlinger,
ParserTransactions,
ParserWindowManager,

View File

@@ -13,34 +13,78 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {ParserFactory} from "./parser_factory";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("ParserInputMethodlClients", () => {
let parser: Parser;
describe("trace with elapsed + real timestamp", () => {
let parser: Parser;
beforeAll(async () => {
const buffer = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.INPUT_METHOD_CLIENTS);
});
describe("trace with elapsed (only) timestamp", () => {
let parser: Parser;
it("provides timestamps", () => {
expect(parser.getTimestamps().length)
.toEqual(33);
expect(parser.getTimestamps().slice(0, 3))
.toEqual([1149083651642, 1149083950633, 1149127567251]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodClients.pb");
});
it("retrieves trace entry", () => {
expect(Number(parser.getTraceEntry(1149083651642)!.elapsedRealtimeNanos))
.toEqual(1149083651642);
it("has expected trace type", () => {
expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS);
});
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));
});
});
});

View File

@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {InputMethodClientsTraceFileProto} from "./proto_types";
class ParserInputMethodClients extends Parser {
constructor(trace: Blob) {
super(trace);
this.realToElapsedTimeOffsetNs = undefined;
}
getTraceTypeId(): TraceTypeId {
return TraceTypeId.INPUT_METHOD_CLIENTS;
getTraceType(): TraceType {
return TraceType.INPUT_METHOD_CLIENTS;
}
override getMagicNumber(): number[] {
@@ -31,17 +33,32 @@ class ParserInputMethodClients extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decoded = <any>InputMethodClientsTraceFileProto.decode(buffer);
if (Object.prototype.hasOwnProperty.call(decoded, "realToElapsedTimeOffsetNanos")) {
this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos);
}
else {
this.realToElapsedTimeOffsetNs = undefined;
}
return (<any>InputMethodClientsTraceFileProto.decode(buffer)).entry;
}
override getTimestamp(entryProto: any): number {
return Number(entryProto.elapsedRealtimeNanos);
override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type === TimestampType.ELAPSED) {
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
}

View File

@@ -13,32 +13,65 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {ParserFactory} from "./parser_factory";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("ParserInputMethodManagerService", () => {
let parser: Parser;
describe("trace with elapsed + real timestamp", () => {
let parser: Parser;
beforeAll(async () => {
const buffer = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.INPUT_METHOD_MANAGER_SERVICE);
});
describe("trace with elapsed (only) timestamp", () => {
let parser: Parser;
it("provides timestamps", () => {
expect(parser.getTimestamps())
.toEqual([1149226290110, 1149237707591, 1149238950389]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodManagerService.pb");
});
it("retrieves trace entry", () => {
expect(Number(parser.getTraceEntry(1149226290110)!.elapsedRealtimeNanos))
.toEqual(1149226290110);
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);
});
});
});

View File

@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {InputMethodManagerServiceTraceFileProto} from "./proto_types";
class ParserInputMethodManagerService extends Parser {
constructor(trace: Blob) {
super(trace);
this.realToElapsedTimeOffsetNs = undefined;
}
getTraceTypeId(): TraceTypeId {
return TraceTypeId.INPUT_METHOD_MANAGER_SERVICE;
getTraceType(): TraceType {
return TraceType.INPUT_METHOD_MANAGER_SERVICE;
}
override getMagicNumber(): number[] {
@@ -31,17 +33,31 @@ class ParserInputMethodManagerService extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
return (<any>InputMethodManagerServiceTraceFileProto.decode(buffer)).entry;
const decoded = <any>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): number {
return Number(entryProto.elapsedRealtimeNanos);
protected override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type === TimestampType.ELAPSED) {
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
}

View File

@@ -13,32 +13,72 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {ParserFactory} from "./parser_factory";
import {Parser} from "./parser";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("ParserInputMethodService", () => {
let parser: Parser;
describe("trace with elapsed + real timestamp", () => {
let parser: Parser;
beforeAll(async () => {
const buffer = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.INPUT_METHOD_SERVICE);
});
describe("trace with elapsed (only) timestamp", () => {
let parser: Parser;
it("provides timestamps", () => {
expect(parser.getTimestamps())
.toEqual([1149230019887, 1149234359324, 1149241227244, 1149243083608, 1149249518016, 1149249784617, 1149272993520]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/InputMethodService.pb");
});
it("retrieves trace entry", () => {
expect(Number(parser.getTraceEntry(1149230019887)!.elapsedRealtimeNanos))
.toEqual(1149230019887);
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);
});
});
});

View File

@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {InputMethodServiceTraceFileProto} from "./proto_types";
class ParserInputMethodService extends Parser {
constructor(trace: Blob) {
super(trace);
this.realToElapsedTimeOffsetNs = undefined;
}
getTraceTypeId(): TraceTypeId {
return TraceTypeId.INPUT_METHOD_SERVICE;
getTraceType(): TraceType {
return TraceType.INPUT_METHOD_SERVICE;
}
override getMagicNumber(): number[] {
@@ -31,17 +33,31 @@ class ParserInputMethodService extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
return (<any>InputMethodServiceTraceFileProto.decode(buffer)).entry;
const decoded = <any>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): number {
return Number(entryProto.elapsedRealtimeNanos);
override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type === TimestampType.ELAPSED) {
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, 0x49, 0x4d, 0x53, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMSTRACE
}

View File

@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {ParserFactory} from "./parser_factory";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
import {LogMessage} from "../common/trace/protolog";
describe("ParserProtoLog", () => {
@@ -32,26 +32,44 @@ describe("ParserProtoLog", () => {
};
beforeAll(async () => {
const buffer = TestUtils.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", () => {
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.PROTO_LOG);
expect(parser.getTraceType()).toEqual(TraceType.PROTO_LOG);
});
it("provides timestamps", () => {
const timestamps = parser.getTimestamps();
it("provides elapsed timestamps", () => {
const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!;
expect(timestamps.length)
.toEqual(50);
const expected = [
new Timestamp(TimestampType.ELAPSED, 850746266486n),
new Timestamp(TimestampType.ELAPSED, 850746336718n),
new Timestamp(TimestampType.ELAPSED, 850746350430n),
];
expect(timestamps.slice(0, 3))
.toEqual([850746266486, 850746336718, 850746350430]);
.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 actualMessage = parser.getTraceEntry(850746266486)!;
const timestamp = new Timestamp(TimestampType.ELAPSED, 850746266486n);
const actualMessage = parser.getTraceEntry(timestamp)!;
expect(actualMessage).toBeInstanceOf(LogMessage);
expect(Object.assign({}, actualMessage)).toEqual(expectedFirstLogMessage);

View File

@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {LogMessage, FormattedLogMessage, UnformattedLogMessage} from "common/trace/protolog";
import {TraceTypeId} from "common/trace/type_id";
import {FormattedLogMessage, LogMessage, UnformattedLogMessage} from "common/trace/protolog";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {ProtoLogFileProto} from "./proto_types";
import configJson from "../../../../../frameworks/base/data/etc/services.core.protolog.json";
@@ -24,8 +25,8 @@ class ParserProtoLog extends Parser {
super(trace);
}
override getTraceTypeId(): TraceTypeId {
return TraceTypeId.PROTO_LOG;
override getTraceType(): TraceType {
return TraceType.PROTO_LOG;
}
override getMagicNumber(): number[] {
@@ -47,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);
});
@@ -54,8 +57,14 @@ class ParserProtoLog extends Parser {
return fileProto.log;
}
override getTimestamp(entryProto: any): number {
return Number(entryProto.elapsedRealtimeNanos);
override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type == TimestampType.ELAPSED) {
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 {
@@ -81,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";
}

View File

@@ -14,49 +14,81 @@
* limitations under the License.
*/
import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
import {TraceTypeId} from "common/trace/type_id";
import {TestUtils} from "test/test_utils";
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 buffer = TestUtils.getFixtureBlob("screen_recording.mp4");
const parsers = await new ParserFactory().createParsers([buffer]);
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", () => {
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.SCREEN_RECORDING);
expect(parser.getTraceType()).toEqual(TraceType.SCREEN_RECORDING);
});
it("provides timestamps", () => {
const timestamps = parser.getTimestamps();
it ("provides elapsed timestamps", () => {
const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!;
expect(timestamps.length)
.toEqual(85);
.toEqual(15);
const expected = [
new Timestamp(TimestampType.ELAPSED, 144857685000n),
new Timestamp(TimestampType.ELAPSED, 144866679000n),
new Timestamp(TimestampType.ELAPSED, 144875772000n),
];
expect(timestamps.slice(0, 3))
.toEqual([19446131807000, 19446158500000, 19446167117000]);
expect(timestamps.slice(timestamps.length-3, timestamps.length))
.toEqual([19448470076000, 19448487525000, 19448501007000]);
.toEqual(expected);
});
it("retrieves trace entry", () => {
it("provides real timestamps", () => {
const timestamps = parser.getTimestamps(TimestampType.REAL)!;
expect(timestamps.length)
.toEqual(15);
const expected = [
new Timestamp(TimestampType.REAL, 1659687791485257266n),
new Timestamp(TimestampType.REAL, 1659687791494251266n),
new Timestamp(TimestampType.REAL, 1659687791503344266n),
];
expect(timestamps.slice(0, 3))
.toEqual(expected);
});
it("retrieves trace entry from elapsed timestamp", () => {
{
const entry = parser.getTraceEntry(19446131807000)!;
const timestamp = new Timestamp(TimestampType.ELAPSED, 144857685000n);
const entry = parser.getTraceEntry(timestamp)!;
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0);
}
{
const entry = parser.getTraceEntry(19448501007000)!;
const timestamp = new Timestamp(TimestampType.ELAPSED, 145300550000n);
const entry = parser.getTraceEntry(timestamp)!;
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(2.37, 0.001);
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0.442, 0.001);
}
});
it("retrieves trace entry from real timestamp", () => {
{
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, 1659687791928122266n);
const entry = parser.getTraceEntry(timestamp)!;
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0.322, 0.001);
}
});
});

View File

@@ -13,38 +13,72 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {ArrayUtils} from "common/utils/array_utils";
import {Parser} from "./parser";
import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
class ScreenRecordingMetadataEntry {
constructor(public timestampMonotonicNs: bigint, public timestampRealtimeNs: bigint) {
}
}
class ParserScreenRecording extends Parser {
constructor(trace: Blob) {
super(trace);
}
override getTraceTypeId(): TraceTypeId {
return TraceTypeId.SCREEN_RECORDING;
override getTraceType(): TraceType {
return TraceType.SCREEN_RECORDING;
}
override getMagicNumber(): number[] {
return ParserScreenRecording.MPEG4_MAGIC_NMBER;
}
override decodeTrace(videoData: Uint8Array): number[] {
const posCount = this.searchMagicString(videoData);
const [posTimestamps, count] = this.parseTimestampsCount(videoData, posCount);
return this.parseTimestamps(videoData, posTimestamps, count);
override decodeTrace(videoData: Uint8Array): ScreenRecordingMetadataEntry[] {
const posVersion = this.searchMagicString(videoData);
const [posTimeOffset, metadataVersion] = this.parseMetadataVersion(videoData, posVersion);
if (metadataVersion !== 1) {
throw TypeError(`Metadata version "${metadataVersion}" not supported`);
}
const [posCount, timeOffsetNs] = this.parseRealToMonotonicTimeOffsetNs(videoData, posTimeOffset);
const [posTimestamps, count] = this.parseFramesCount(videoData, posCount);
const timestampsMonotonicNs = this.parseTimestampsMonotonicNs(videoData, posTimestamps, count);
return timestampsMonotonicNs.map((timestampMonotonicNs: bigint) => {
return new ScreenRecordingMetadataEntry(timestampMonotonicNs, timestampMonotonicNs + timeOffsetNs);
});
}
override getTimestamp(decodedEntry: number): number {
return decodedEntry;
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),
// 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 will work as expected.
return new Timestamp(type, decodedEntry.timestampMonotonicNs);
}
else if (type === TimestampType.REAL) {
return new Timestamp(type, decodedEntry.timestampRealtimeNs);
}
return undefined;
}
override processDecodedEntry(timestamp: number): ScreenRecordingTraceEntry {
const videoTimeSeconds = (timestamp - this.timestamps[0]) / 1000000000 + ParserScreenRecording.EPSILON;
override processDecodedEntry(entry: ScreenRecordingMetadataEntry): ScreenRecordingTraceEntry {
const initialTimestampNs = this.getTimestamps(TimestampType.ELAPSED)![0].getValueNs();
const currentTimestampNs = entry.timestampMonotonicNs;
const videoTimeSeconds = Number(currentTimestampNs - initialTimestampNs) / 1000000000;
const videoData = this.trace;
return new ScreenRecordingTraceEntry(timestamp, videoTimeSeconds, videoData);
return new ScreenRecordingTraceEntry(videoTimeSeconds, videoData);
}
private searchMagicString(videoData: Uint8Array): number {
@@ -56,22 +90,40 @@ class ParserScreenRecording extends Parser {
return pos;
}
private parseTimestampsCount(videoData: Uint8Array, pos: number) : [number, number] {
if (pos + 4 >= videoData.length) {
throw new TypeError("video data is too short. Expected timestamps count doesn't fit");
private parseMetadataVersion(videoData: Uint8Array, pos: number) : [number, number] {
if (pos + 4 > videoData.length) {
throw new TypeError("Failed to parse metadata version. Video data is too short.");
}
const timestampsCount = ArrayUtils.toUintLittleEndian(videoData, pos, pos+4);
const version = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos+4));
pos += 4;
return [pos, timestampsCount];
return [pos, version];
}
private parseTimestamps(videoData: Uint8Array, pos: number, count: number): number[] {
if (pos + count * 8 >= videoData.length) {
throw new TypeError("video data is too short. Expected timestamps do not fit");
private parseRealToMonotonicTimeOffsetNs(videoData: Uint8Array, pos: number) : [number, bigint] {
if (pos + 8 > videoData.length) {
throw new TypeError("Failed to parse realtime-to-monotonic time offset. Video data is too short.");
}
const timestamps: number[] = [];
const offset = ArrayUtils.toIntLittleEndian(videoData, pos, pos+8);
pos += 8;
return [pos, offset];
}
private parseFramesCount(videoData: Uint8Array, pos: number) : [number, number] {
if (pos + 4 > videoData.length) {
throw new TypeError("Failed to parse frames count. Video data is too short.");
}
const count = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos+4));
pos += 4;
return [pos, count];
}
private parseTimestampsMonotonicNs(videoData: Uint8Array, pos: number, count: number) : bigint[] {
if (pos + count * 16 > videoData.length) {
throw new TypeError("Failed to parse monotonic timestamps. Video data is too short.");
}
const timestamps: bigint[] = [];
for (let i = 0; i < count; ++i) {
const timestamp = ArrayUtils.toUintLittleEndian(videoData, pos, pos+8) * 1000;
const timestamp = ArrayUtils.toUintLittleEndian(videoData, pos, pos+8);
pos += 8;
timestamps.push(timestamp);
}
@@ -79,8 +131,7 @@ class ParserScreenRecording extends Parser {
}
private static readonly MPEG4_MAGIC_NMBER = [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32]; // ....ftypmp42
private static readonly WINSCOPE_META_MAGIC_STRING = [0x23, 0x56, 0x56, 0x31, 0x4e, 0x53, 0x43, 0x30, 0x50, 0x45, 0x54, 0x31, 0x4d, 0x45, 0x21, 0x23]; // #VV1NSC0PET1ME!#
private static readonly EPSILON = 0.00001;
private static readonly WINSCOPE_META_MAGIC_STRING = [0x23, 0x56, 0x56, 0x31, 0x4e, 0x53, 0x43, 0x30, 0x50, 0x45, 0x54, 0x31, 0x4d, 0x45, 0x32, 0x23]; // #VV1NSC0PET1ME2#
}
export {ParserScreenRecording};

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2022 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 {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {UnitTestUtils} from "test/unit/utils";
import {Parser} from "./parser";
describe("ParserScreenRecordingLegacy", () => {
let parser: Parser;
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/screen_recording.mp4");
});
it("has expected trace type", () => {
expect(parser.getTraceType()).toEqual(TraceType.SCREEN_RECORDING);
});
it("provides elapsed timestamps", () => {
const timestamps = parser.getTimestamps(TimestampType.ELAPSED)!;
expect(timestamps.length)
.toEqual(85);
let expected = [
new Timestamp(TimestampType.ELAPSED, 19446131807000n),
new Timestamp(TimestampType.ELAPSED, 19446158500000n),
new Timestamp(TimestampType.ELAPSED, 19446167117000n),
];
expect(timestamps.slice(0, 3))
.toEqual(expected);
expected = [
new Timestamp(TimestampType.ELAPSED, 19448470076000n),
new Timestamp(TimestampType.ELAPSED, 19448487525000n),
new Timestamp(TimestampType.ELAPSED, 19448501007000n),
];
expect(timestamps.slice(timestamps.length-3, timestamps.length))
.toEqual(expected);
});
it("doesn't provide real timestamps", () => {
expect(parser.getTimestamps(TimestampType.REAL))
.toEqual(undefined);
});
it("retrieves trace entry", () => {
{
const timestamp = new Timestamp(TimestampType.ELAPSED, 19446131807000n);
const entry = parser.getTraceEntry(timestamp)!;
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0);
}
{
const timestamp = new Timestamp(TimestampType.ELAPSED, 19448501007000n);
const entry = parser.getTraceEntry(timestamp)!;
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(2.37, 0.001);
}
});
});

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2022 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 {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {ArrayUtils} from "common/utils/array_utils";
import {Parser} from "./parser";
import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
class ParserScreenRecordingLegacy extends Parser {
constructor(trace: Blob) {
super(trace);
}
override getTraceType(): TraceType {
return TraceType.SCREEN_RECORDING;
}
override getMagicNumber(): number[] {
return ParserScreenRecordingLegacy.MPEG4_MAGIC_NMBER;
}
override decodeTrace(videoData: Uint8Array): Timestamp[] {
const posCount = this.searchMagicString(videoData);
const [posTimestamps, count] = this.parseFramesCount(videoData, posCount);
return this.parseTimestamps(videoData, posTimestamps, count);
}
override getTimestamp(type: TimestampType, decodedEntry: Timestamp): undefined|Timestamp {
if (type !== TimestampType.ELAPSED) {
return undefined;
}
return decodedEntry;
}
override processDecodedEntry(entry: Timestamp): ScreenRecordingTraceEntry {
const currentTimestamp = entry;
const initialTimestamp = this.getTimestamps(TimestampType.ELAPSED)![0];
const videoTimeSeconds =
Number(currentTimestamp.getValueNs() - initialTimestamp.getValueNs()) / 1000000000
+ ParserScreenRecordingLegacy.EPSILON;
const videoData = this.trace;
return new ScreenRecordingTraceEntry(videoTimeSeconds, videoData);
}
private searchMagicString(videoData: Uint8Array): number {
let pos = ArrayUtils.searchSubarray(videoData, ParserScreenRecordingLegacy.WINSCOPE_META_MAGIC_STRING);
if (pos === undefined) {
throw new TypeError("video data doesn't contain winscope magic string");
}
pos += ParserScreenRecordingLegacy.WINSCOPE_META_MAGIC_STRING.length;
return pos;
}
private parseFramesCount(videoData: Uint8Array, pos: number) : [number, number] {
if (pos + 4 > videoData.length) {
throw new TypeError("Failed to parse frames count. Video data is too short.");
}
const framesCount = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos+4));
pos += 4;
return [pos, framesCount];
}
private parseTimestamps(videoData: Uint8Array, pos: number, count: number): Timestamp[] {
if (pos + count * 8 > videoData.length) {
throw new TypeError("Failed to parse timestamps. Video data is too short.");
}
const timestamps: Timestamp[] = [];
for (let i = 0; i < count; ++i) {
const value = ArrayUtils.toUintLittleEndian(videoData, pos, pos+8) * 1000n;
pos += 8;
timestamps.push(new Timestamp(TimestampType.ELAPSED, value));
}
return timestamps;
}
private static readonly MPEG4_MAGIC_NMBER = [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32]; // ....ftypmp42
private static readonly WINSCOPE_META_MAGIC_STRING = [0x23, 0x56, 0x56, 0x31, 0x4e, 0x53, 0x43, 0x30, 0x50, 0x45, 0x54, 0x31, 0x4d, 0x45, 0x21, 0x23]; // #VV1NSC0PET1ME!#
private static readonly EPSILON = 0.00001;
}
export {ParserScreenRecordingLegacy};

View File

@@ -13,34 +13,78 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry";
import {TestUtils} from "test/test_utils";
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 = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.SURFACE_FLINGER);
});
describe("trace with elapsed (only) timestamp", () => {
let parser: Parser;
it("provides timestamps", () => {
expect(parser.getTimestamps())
.toEqual([850335483446, 850686322883, 850736507697]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/SurfaceFlinger.pb");
});
it("retrieves trace entry", () => {
const entry = parser.getTraceEntry(850335483446)!;
expect(entry).toBeInstanceOf(LayerTraceEntry);
expect(Number(entry.timestampMs)).toEqual(850335483446);
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);
});
});
});

View File

@@ -13,18 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry";
import {TraceTypeId} from "common/trace/type_id";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {LayersTraceFileProto} from "./proto_types";
class ParserSurfaceFlinger extends Parser {
constructor(trace: Blob) {
super(trace);
this.realToElapsedTimeOffsetNs = undefined;
}
override getTraceTypeId(): TraceTypeId {
return TraceTypeId.SURFACE_FLINGER;
override getTraceType(): TraceType {
return TraceType.SURFACE_FLINGER;
}
override getMagicNumber(): number[] {
@@ -32,17 +34,36 @@ class ParserSurfaceFlinger extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
return (<any>LayersTraceFileProto.decode(buffer)).entry;
const decoded = <any>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): number {
return Number(entryProto.elapsedRealtimeNanos);
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));
}
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
}

View File

@@ -13,33 +13,73 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry";
import {TestUtils} from "test/test_utils";
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 = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.SURFACE_FLINGER);
});
describe("trace with elapsed (only) timestamp", () => {
let parser: Parser;
it("provides timestamp", () => {
expect(parser.getTimestamps()).toEqual([0]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/dump_SurfaceFlinger.pb");
});
it("retrieves trace entry", () => {
const entry = parser.getTraceEntry(0)!;
expect(entry).toBeInstanceOf(LayerTraceEntry);
expect(Number(entry.timestampMs)).toEqual(0);
it("has expected trace type", () => {
expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER);
});
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);
});
});
});

View File

@@ -13,35 +13,95 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {ParserFactory} from "./parser_factory";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("ParserTransactions", () => {
let parser: Parser;
describe("trace with elapsed + real timestamp", () => {
let parser: Parser;
beforeAll(async () => {
const buffer = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.TRANSACTIONS);
});
describe("trace with elapsed (only) timestamp", () => {
let parser: Parser;
it("provides timestamps", () => {
const timestamps = parser.getTimestamps();
expect(timestamps.length)
.toEqual(4997);
expect(timestamps.slice(0, 3))
.toEqual([14862317023, 14873423549, 14884850511]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/Transactions.pb");
});
it("retrieves trace entry", () => {
expect(Number(parser.getTraceEntry(14862317023)!.elapsedRealtimeNanos))
.toEqual(14862317023);
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(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);
});
});
});

View File

@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
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 getTraceTypeId(): TraceTypeId {
return TraceTypeId.TRANSACTIONS;
override getTraceType(): TraceType {
return TraceType.TRANSACTIONS;
}
override getMagicNumber(): number[] {
@@ -31,17 +33,31 @@ class ParserTransactions extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
return (<any>TransactionsTraceFileProto.decode(buffer)).entry;
const decoded = <any>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): number {
return Number(entryProto.elapsedRealtimeNanos);
override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type === TimestampType.ELAPSED) {
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, 0x54, 0x4e, 0x58, 0x54, 0x52, 0x41, 0x43, 0x45]; // .TNXTRACE
}

View File

@@ -14,33 +14,84 @@
* limitations under the License.
*/
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
import {TraceTypeId} from "common/trace/type_id";
import {ParserFactory} from "./parser_factory";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("ParserWindowManager", () => {
let parser: Parser;
describe("trace with elapsed + real timestamp", () => {
let parser: Parser;
beforeAll(async () => {
const buffer = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.WINDOW_MANAGER);
});
describe("trace elapsed timestamp", () => {
let parser: Parser;
it("provides timestamps", () => {
expect(parser.getTimestamps())
.toEqual([850254319343, 850763506110, 850782750048]);
});
beforeAll(async () => {
parser = await UnitTestUtils.getParser("traces/elapsed_timestamp/WindowManager.pb");
});
it("retrieves trace entry", () => {
const entry = parser.getTraceEntry(850254319343)!;
expect(entry).toBeInstanceOf(WindowManagerState);
expect(Number(entry.timestampMs)).toEqual(850254319343);
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);
});
});
});

View File

@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {WindowManagerTraceFileProto} from "./proto_types";
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
@@ -21,10 +22,11 @@ import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerS
class ParserWindowManager extends Parser {
constructor(trace: Blob) {
super(trace);
this.realToElapsedTimeOffsetNs = undefined;
}
override getTraceTypeId(): TraceTypeId {
return TraceTypeId.WINDOW_MANAGER;
override getTraceType(): TraceType {
return TraceType.WINDOW_MANAGER;
}
override getMagicNumber(): number[] {
@@ -32,17 +34,31 @@ class ParserWindowManager extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
return (<any>WindowManagerTraceFileProto.decode(buffer)).entry;
const decoded = <any>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): number {
return Number(entryProto.elapsedRealtimeNanos);
override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type === TimestampType.ELAPSED) {
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): 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
}

View File

@@ -14,33 +14,39 @@
* limitations under the License.
*/
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
import {TraceTypeId} from "common/trace/type_id";
import {ParserFactory} from "./parser_factory";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {TestUtils} from "test/test_utils";
import {UnitTestUtils} from "test/unit/utils";
describe("ParserWindowManagerDump", () => {
let parser: Parser;
beforeAll(async () => {
const buffer = TestUtils.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.getTraceTypeId()).toEqual(TraceTypeId.WINDOW_MANAGER);
expect(parser.getTraceType()).toEqual(TraceType.WINDOW_MANAGER);
});
it("provides timestamps", () => {
expect(parser.getTimestamps())
.toEqual([0]);
it("provides elapsed timestamp (always zero)", () => {
const expected = [
new Timestamp(TimestampType.ELAPSED, 0n),
];
expect(parser.getTimestamps(TimestampType.ELAPSED))
.toEqual(expected);
});
it("retrieves trace entry", () => {
const entry = parser.getTraceEntry(0)!;
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(Number(entry.timestampMs)).toEqual(0);
expect(BigInt(entry.timestampMs)).toEqual(0n);
});
});

View File

@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {Timestamp, TimestampType} from "common/trace/timestamp";
import {TraceType} from "common/trace/trace_type";
import {Parser} from "./parser";
import {WindowManagerServiceDumpProto} from "./proto_types";
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
@@ -23,8 +24,8 @@ class ParserWindowManagerDump extends Parser {
super(trace);
}
override getTraceTypeId(): TraceTypeId {
return TraceTypeId.WINDOW_MANAGER;
override getTraceType(): TraceType {
return TraceType.WINDOW_MANAGER;
}
override getMagicNumber(): undefined {
@@ -35,8 +36,11 @@ class ParserWindowManagerDump extends Parser {
return [WindowManagerServiceDumpProto.decode(buffer)];
}
override getTimestamp(entryProto: any): number {
return 0;
override getTimestamp(type: TimestampType, entryProto: any): undefined|Timestamp {
if (type !== TimestampType.ELAPSED) {
return undefined;
}
return new Timestamp(TimestampType.ELAPSED, 0n);
}
override processDecodedEntry(entryProto: any): WindowManagerState {

View File

@@ -17,27 +17,30 @@ import * as fs from "fs";
import * as path from "path";
import {Blob} from "./blob";
class TestUtils {
class CommonTestUtils {
static getFixtureBlob(filename: string): Blob {
const buffer = TestUtils.loadFixture(filename);
const buffer = CommonTestUtils.loadFixture(filename);
return new Blob(buffer);
}
static loadFixture(filename: string): ArrayBuffer {
return fs.readFileSync(TestUtils.getFixturePath(filename));
return fs.readFileSync(CommonTestUtils.getFixturePath(filename));
}
static getFixturePath(filename: string): string {
return path.join(TestUtils.getProjectRootPath(), "src/test/fixtures", filename);
}
static getProductionIndexHtmlPath(): string {
return path.join(TestUtils.getProjectRootPath(), "dist/prod/index.html");
if (path.isAbsolute(filename)) {
return filename;
}
return path.join(CommonTestUtils.getProjectRootPath(), "src/test/fixtures", filename);
}
static getProjectRootPath(): string {
return path.join(__dirname, "../..");
let root = __dirname;
while (path.basename(root) !== "winscope-ng") {
root = path.dirname(root);
}
return root;
}
}
export {TestUtils};
export {CommonTestUtils};

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2022 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 * as path from "path";
import {CommonTestUtils} from "../common/utils";
class E2eTestUtils extends CommonTestUtils {
static getProductionIndexHtmlPath(): string {
return path.join(CommonTestUtils.getProjectRootPath(), "dist/prod/index.html");
}
}
export {E2eTestUtils};

View File

@@ -14,17 +14,17 @@
* limitations under the License.
*/
import {browser, element, by} from "protractor";
import {TestUtils} from "../test_utils";
import {E2eTestUtils} from "./utils";
describe("Viewer WindowManager", () => {
beforeAll(async () => {
browser.manage().timeouts().implicitlyWait(1000);
browser.get("file://" + TestUtils.getProductionIndexHtmlPath());
browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath());
}),
it("processes trace and renders view", () => {
const inputFile = element(by.css("input[type=\"file\"]"));
inputFile.sendKeys(TestUtils.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");

View File

@@ -14,11 +14,11 @@
* limitations under the License.
*/
import {browser, element, by} from "protractor";
import {TestUtils} from "../test_utils";
import {E2eTestUtils} from "./utils";
describe("winscope", () => {
beforeAll(() => {
browser.get("file://" + TestUtils.getProductionIndexHtmlPath());
browser.get("file://" + E2eTestUtils.getProductionIndexHtmlPath());
}),
it("has title", () => {

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2022 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 {Parser} from "parsers/parser";
import {ParserFactory} from "parsers/parser_factory";
import {CommonTestUtils} from "test/common/utils";
class UnitTestUtils extends CommonTestUtils {
static async getParser(filename: string): Promise<Parser> {
const trace = CommonTestUtils.getFixtureBlob(filename);
const parsers = await new ParserFactory().createParsers([trace]);
expect(parsers.length).toEqual(1);
return parsers[0];
}
}
export {UnitTestUtils};

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TraceTypeId } from "common/trace/type_id";
import { TraceType } from "common/trace/trace_type";
interface Viewer {
//TODO: add TraceEntry data type
notifyCurrentTraceEntries(entries: Map<TraceTypeId, any>): void;
notifyCurrentTraceEntries(entries: Map<TraceType, any>): void;
getView(): HTMLElement;
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TraceTypeId } from "common/trace/type_id";
import { TraceType } from "common/trace/trace_type";
import { Viewer } from "./viewer";
import { ViewerWindowManager } from "./viewer_window_manager/viewer_window_manager";
@@ -22,11 +22,11 @@ class ViewerFactory {
ViewerWindowManager,
];
public createViewers(activeTraceTypes: Set<TraceTypeId>): Viewer[] {
public createViewers(activeTraceTypes: Set<TraceType>): Viewer[] {
const viewers: Viewer[] = [];
for (const Viewer of ViewerFactory.VIEWERS) {
const areViewerDepsSatisfied = Viewer.DEPENDENCIES.every((traceType: TraceTypeId) =>
const areViewerDepsSatisfied = Viewer.DEPENDENCIES.every((traceType: TraceType) =>
activeTraceTypes.has(traceType)
);

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {TraceType} from "common/trace/trace_type";
import {UiData} from "./ui_data";
type UiDataCallbackType = (uiData: UiData) => void;
@@ -25,7 +25,7 @@ class Presenter {
this.uiDataCallback(this.uiData);
}
public notifyCurrentTraceEntries(entries: Map<TraceTypeId, any>) {
public notifyCurrentTraceEntries(entries: Map<TraceType, any>) {
this.uiData = new UiData("UI data selected by user on time scrub");
this.uiDataCallback(this.uiData);
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceTypeId} from "common/trace/type_id";
import {TraceType} from "common/trace/trace_type";
import {Viewer} from "viewers/viewer";
import {Presenter} from "./presenter";
import {UiData} from "./ui_data";
@@ -27,7 +27,7 @@ class ViewerWindowManager implements Viewer {
this.view.addEventListener("outputEvent", () => this.presenter.notifyUiEvent());
}
public notifyCurrentTraceEntries(entries: Map<TraceTypeId, any>): void {
public notifyCurrentTraceEntries(entries: Map<TraceType, any>): void {
this.presenter.notifyCurrentTraceEntries(entries);
}
@@ -35,7 +35,7 @@ class ViewerWindowManager implements Viewer {
return this.view;
}
public static readonly DEPENDENCIES: TraceTypeId[] = [TraceTypeId.WINDOW_MANAGER];
public static readonly DEPENDENCIES: TraceType[] = [TraceType.WINDOW_MANAGER];
private view: HTMLElement;
private presenter: Presenter;
}