refactor Parser's interface
- add class TimestampType (ELAPSED or REAL) - add class Timestamp (timestamp value + type) - use bigint (instead of number) to represent timestamp values Test: cd development/tools/winscope-ng && npm run build:all && npm run test:all Change-Id: I1db9f2f9d48ca54bd79d3ffb989f6dde9ac11cd7
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
44
tools/winscope-ng/src/common/trace/timestamp.ts
Normal file
44
tools/winscope-ng/src/common/trace/timestamp.ts
Normal 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};
|
||||
@@ -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};
|
||||
@@ -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(entry, type);
|
||||
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,13 @@ abstract class Parser {
|
||||
|
||||
protected abstract getMagicNumber(): undefined|number[];
|
||||
protected abstract decodeTrace(trace: Uint8Array): any[];
|
||||
protected abstract getTimestamp(decodedEntry: any): number;
|
||||
//TODO: invert parameters below
|
||||
protected abstract getTimestamp(decodedEntry: any, type: TimestampType): 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};
|
||||
|
||||
@@ -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 {ParserFactory} from "./parser_factory";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
@@ -29,16 +30,23 @@ describe("ParserAccessibility", () => {
|
||||
});
|
||||
|
||||
it("has expected trace type", () => {
|
||||
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.ACCESSIBILITY);
|
||||
expect(parser.getTraceType()).toEqual(TraceType.ACCESSIBILITY);
|
||||
});
|
||||
|
||||
it("provides timestamps", () => {
|
||||
expect(parser.getTimestamps())
|
||||
.toEqual([850297444302, 850297882046, 850756176154, 850773581835]);
|
||||
it("provides elapsed timestamps", () => {
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 850297444302n),
|
||||
new Timestamp(TimestampType.ELAPSED, 850297882046n),
|
||||
new Timestamp(TimestampType.ELAPSED, 850756176154n),
|
||||
new Timestamp(TimestampType.ELAPSED, 850773581835n),
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
expect(Number(parser.getTraceEntry(850297444302)!.elapsedRealtimeNanos))
|
||||
.toEqual(850297444302);
|
||||
it("retrieves trace entry from elapsed timestamp", () => {
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 850297444302n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos))
|
||||
.toEqual(850297444302n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 {AccessibilityTraceFileProto} from "./proto_types";
|
||||
|
||||
@@ -22,8 +23,8 @@ class ParserAccessibility extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
override getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.ACCESSIBILITY;
|
||||
override getTraceType(): TraceType {
|
||||
return TraceType.ACCESSIBILITY;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -34,8 +35,11 @@ class ParserAccessibility extends Parser {
|
||||
return (<any>AccessibilityTraceFileProto.decode(buffer)).entry;
|
||||
}
|
||||
|
||||
override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos));
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): any {
|
||||
|
||||
@@ -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 {Timestamp, TimestampType} from "common/trace/timestamp";
|
||||
import {ParserFactory} from "./parser_factory";
|
||||
import {Parser} from "./parser";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
@@ -28,33 +28,43 @@ describe("Parser", () => {
|
||||
parser = parsers[0];
|
||||
});
|
||||
|
||||
it("provides timestamps", () => {
|
||||
expect(parser.getTimestamps())
|
||||
.toEqual([850254319343, 850763506110, 850782750048]);
|
||||
it("provides elapsed timestamps", () => {
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 850254319343n),
|
||||
new Timestamp(TimestampType.ELAPSED, 850763506110n),
|
||||
new Timestamp(TimestampType.ELAPSED, 850782750048n)
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry (no timestamp matches)", () => {
|
||||
expect(parser.getTraceEntry(850254319342))
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319342n);
|
||||
expect(parser.getTraceEntry(timestamp))
|
||||
.toEqual(undefined);
|
||||
});
|
||||
|
||||
it("retrieves trace entry (equal timestamp matches)", () => {
|
||||
expect(Number(parser.getTraceEntry(850254319343)!.timestampMs))
|
||||
.toEqual(850254319343);
|
||||
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(850763506110)!.timestampMs))
|
||||
.toEqual(850763506110);
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506110n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs))
|
||||
.toEqual(850763506110n);
|
||||
});
|
||||
|
||||
it("retrieves trace entry (lower timestamp matches)", () => {
|
||||
expect(Number(parser.getTraceEntry(850254319344)!.timestampMs))
|
||||
.toEqual(850254319343);
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319344n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs))
|
||||
.toEqual(850254319343n);
|
||||
});
|
||||
|
||||
it("retrieves trace entry (equal timestamp matches)", () => {
|
||||
expect(Number(parser.getTraceEntry(850763506111)!.timestampMs))
|
||||
.toEqual(850763506110);
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 850763506111n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.timestampMs))
|
||||
.toEqual(850763506110n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 {ParserFactory} from "./parser_factory";
|
||||
import {Parser} from "./parser";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
@@ -29,18 +30,25 @@ describe("ParserInputMethodlClients", () => {
|
||||
});
|
||||
|
||||
it("has expected trace type", () => {
|
||||
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.INPUT_METHOD_CLIENTS);
|
||||
expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_CLIENTS);
|
||||
});
|
||||
|
||||
it("provides timestamps", () => {
|
||||
expect(parser.getTimestamps().length)
|
||||
it("provides elapsed timestamps", () => {
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED)!.length)
|
||||
.toEqual(33);
|
||||
expect(parser.getTimestamps().slice(0, 3))
|
||||
.toEqual([1149083651642, 1149083950633, 1149127567251]);
|
||||
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 1149083651642n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149083950633n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149127567251n),
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED)!.slice(0, 3))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
expect(Number(parser.getTraceEntry(1149083651642)!.elapsedRealtimeNanos))
|
||||
.toEqual(1149083651642);
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 1149083651642n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos))
|
||||
.toEqual(1149083651642n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 {InputMethodClientsTraceFileProto} from "./proto_types";
|
||||
|
||||
@@ -22,8 +23,8 @@ class ParserInputMethodClients extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.INPUT_METHOD_CLIENTS;
|
||||
getTraceType(): TraceType {
|
||||
return TraceType.INPUT_METHOD_CLIENTS;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -34,8 +35,11 @@ class ParserInputMethodClients extends Parser {
|
||||
return (<any>InputMethodClientsTraceFileProto.decode(buffer)).entry;
|
||||
}
|
||||
|
||||
override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos));
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): any {
|
||||
|
||||
@@ -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 {ParserFactory} from "./parser_factory";
|
||||
import {Parser} from "./parser";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
@@ -29,16 +30,22 @@ describe("ParserInputMethodManagerService", () => {
|
||||
});
|
||||
|
||||
it("has expected trace type", () => {
|
||||
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.INPUT_METHOD_MANAGER_SERVICE);
|
||||
expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_MANAGER_SERVICE);
|
||||
});
|
||||
|
||||
it("provides timestamps", () => {
|
||||
expect(parser.getTimestamps())
|
||||
.toEqual([1149226290110, 1149237707591, 1149238950389]);
|
||||
it("provides elapsed timestamps", () => {
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 1149226290110n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149237707591n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149238950389n),
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
expect(Number(parser.getTraceEntry(1149226290110)!.elapsedRealtimeNanos))
|
||||
.toEqual(1149226290110);
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 1149226290110n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos))
|
||||
.toEqual(1149226290110n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 {InputMethodManagerServiceTraceFileProto} from "./proto_types";
|
||||
|
||||
@@ -22,8 +23,8 @@ class ParserInputMethodManagerService extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.INPUT_METHOD_MANAGER_SERVICE;
|
||||
getTraceType(): TraceType {
|
||||
return TraceType.INPUT_METHOD_MANAGER_SERVICE;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -34,8 +35,11 @@ class ParserInputMethodManagerService extends Parser {
|
||||
return (<any>InputMethodManagerServiceTraceFileProto.decode(buffer)).entry;
|
||||
}
|
||||
|
||||
protected override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
protected override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos));
|
||||
}
|
||||
|
||||
protected override processDecodedEntry(entryProto: any): any {
|
||||
|
||||
@@ -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 {ParserFactory} from "./parser_factory";
|
||||
import {Parser} from "./parser";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
@@ -29,16 +30,26 @@ describe("ParserInputMethodService", () => {
|
||||
});
|
||||
|
||||
it("has expected trace type", () => {
|
||||
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.INPUT_METHOD_SERVICE);
|
||||
expect(parser.getTraceType()).toEqual(TraceType.INPUT_METHOD_SERVICE);
|
||||
});
|
||||
|
||||
it("provides timestamps", () => {
|
||||
expect(parser.getTimestamps())
|
||||
.toEqual([1149230019887, 1149234359324, 1149241227244, 1149243083608, 1149249518016, 1149249784617, 1149272993520]);
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 1149230019887n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149234359324n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149241227244n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149243083608n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149249518016n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149249784617n),
|
||||
new Timestamp(TimestampType.ELAPSED, 1149272993520n),
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
expect(Number(parser.getTraceEntry(1149230019887)!.elapsedRealtimeNanos))
|
||||
.toEqual(1149230019887);
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 1149230019887n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos))
|
||||
.toEqual(1149230019887n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 {InputMethodServiceTraceFileProto} from "./proto_types";
|
||||
|
||||
@@ -22,8 +23,8 @@ class ParserInputMethodService extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.INPUT_METHOD_SERVICE;
|
||||
getTraceType(): TraceType {
|
||||
return TraceType.INPUT_METHOD_SERVICE;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -34,8 +35,11 @@ class ParserInputMethodService extends Parser {
|
||||
return (<any>InputMethodServiceTraceFileProto.decode(buffer)).entry;
|
||||
}
|
||||
|
||||
override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos));
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): any {
|
||||
|
||||
@@ -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 {ParserFactory} from "./parser_factory";
|
||||
import {Parser} from "./parser";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
@@ -39,19 +40,26 @@ describe("ParserProtoLog", () => {
|
||||
});
|
||||
|
||||
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("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);
|
||||
|
||||
@@ -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[] {
|
||||
@@ -54,8 +55,11 @@ class ParserProtoLog extends Parser {
|
||||
return fileProto.log;
|
||||
}
|
||||
|
||||
override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos));
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): LogMessage {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
|
||||
import {TraceTypeId} from "common/trace/type_id";
|
||||
import {Timestamp, TimestampType} from "common/trace/timestamp";
|
||||
import {TraceType} from "common/trace/trace_type";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
import {Parser} from "./parser";
|
||||
import {ParserFactory} from "./parser_factory";
|
||||
@@ -30,28 +31,66 @@ describe("ParserScreenRecording", () => {
|
||||
});
|
||||
|
||||
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(88);
|
||||
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 732949304000n),
|
||||
new Timestamp(TimestampType.ELAPSED, 733272129000n),
|
||||
new Timestamp(TimestampType.ELAPSED, 733283916000n),
|
||||
];
|
||||
expect(timestamps.slice(0, 3))
|
||||
.toEqual([1658843852566916400, 1658843852889741300, 1658843852901528300]);
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
it("provides real timestamps", () => {
|
||||
const timestamps = parser.getTimestamps(TimestampType.REAL)!;
|
||||
|
||||
expect(timestamps.length)
|
||||
.toEqual(88);
|
||||
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.REAL, 1658843852566916386n),
|
||||
new Timestamp(TimestampType.REAL, 1658843852889741386n),
|
||||
new Timestamp(TimestampType.REAL, 1658843852901528386n),
|
||||
];
|
||||
expect(timestamps.slice(0, 3))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry from elapsed timestamp", () => {
|
||||
{
|
||||
const entry = parser.getTraceEntry(1658843852566916400)!;
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 732949304000n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
|
||||
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0);
|
||||
}
|
||||
|
||||
{
|
||||
const entry = parser.getTraceEntry(1658843852889741300)!;
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 733272129000n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
|
||||
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0.322, 0.001);
|
||||
}
|
||||
});
|
||||
|
||||
it("retrieves trace entry from real timestamp", () => {
|
||||
{
|
||||
const timestamp = new Timestamp(TimestampType.REAL, 1658843852566916386n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
|
||||
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0);
|
||||
}
|
||||
|
||||
{
|
||||
const timestamp = new Timestamp(TimestampType.REAL, 1658843852889741386n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
|
||||
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(0.322, 0.001);
|
||||
}
|
||||
|
||||
@@ -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 {ArrayUtils} from "common/utils/array_utils";
|
||||
import {Parser} from "./parser";
|
||||
import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
|
||||
@@ -28,8 +29,8 @@ class ParserScreenRecording extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
override getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.SCREEN_RECORDING;
|
||||
override getTraceType(): TraceType {
|
||||
return TraceType.SCREEN_RECORDING;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -51,14 +52,33 @@ class ParserScreenRecording extends Parser {
|
||||
});
|
||||
}
|
||||
|
||||
override getTimestamp(decodedEntry: ScreenRecordingMetadataEntry): number {
|
||||
return Number(decodedEntry.timestampRealtimeNs);
|
||||
override getTimestamp(decodedEntry: ScreenRecordingMetadataEntry, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED && type !== TimestampType.REAL) {
|
||||
return undefined;
|
||||
}
|
||||
if (type === TimestampType.ELAPSED) {
|
||||
// Traces typically contain "elapsed" timestamps (SYSTEM_TIME_BOOTTIME).
|
||||
// Screen recordings contain SYSTEM_TIME_MONOTONIC timestamps.
|
||||
//
|
||||
// Here we are pretending that screen recordings contain "elapsed" timestamps
|
||||
// as well, in order to synchronize with the other traces.
|
||||
//
|
||||
// If no device suspensions are involved, SYSTEM_TIME_MONOTONIC should indeed
|
||||
// correspond to SYSTEM_TIME_BOOTTIME and things should work as expected.
|
||||
return new Timestamp(type, decodedEntry.timestampMonotonicNs);
|
||||
}
|
||||
else if (type === TimestampType.REAL) {
|
||||
return new Timestamp(type, decodedEntry.timestampRealtimeNs);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
override processDecodedEntry(entry: ScreenRecordingMetadataEntry): ScreenRecordingTraceEntry {
|
||||
const videoTimeSeconds = (Number(entry.timestampRealtimeNs) - this.timestamps[0]) / 1000000000;
|
||||
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(Number(entry.timestampRealtimeNs), videoTimeSeconds, videoData);
|
||||
return new ScreenRecordingTraceEntry(videoTimeSeconds, videoData);
|
||||
}
|
||||
|
||||
private searchMagicString(videoData: Uint8Array): number {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
|
||||
import {TraceTypeId} from "common/trace/type_id";
|
||||
import {Timestamp, TimestampType} from "common/trace/timestamp";
|
||||
import {TraceType} from "common/trace/trace_type";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
import {Parser} from "./parser";
|
||||
import {ParserFactory} from "./parser_factory";
|
||||
@@ -30,31 +31,48 @@ describe("ParserScreenRecordingLegacy", () => {
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
let expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 19446131807000n),
|
||||
new Timestamp(TimestampType.ELAPSED, 19446158500000n),
|
||||
new Timestamp(TimestampType.ELAPSED, 19446167117000n),
|
||||
];
|
||||
expect(timestamps.slice(0, 3))
|
||||
.toEqual([19446131807000, 19446158500000, 19446167117000]);
|
||||
.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([19448470076000, 19448487525000, 19448501007000]);
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("doesn't provide real timestamps", () => {
|
||||
expect(parser.getTimestamps(TimestampType.REAL))
|
||||
.toEqual(undefined);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
{
|
||||
const entry = parser.getTraceEntry(19446131807000)!;
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 19446131807000n);
|
||||
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, 19448501007000n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(ScreenRecordingTraceEntry);
|
||||
expect(Number(entry.videoTimeSeconds)).toBeCloseTo(2.37, 0.001);
|
||||
}
|
||||
|
||||
@@ -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 {ArrayUtils} from "common/utils/array_utils";
|
||||
import {Parser} from "./parser";
|
||||
import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
|
||||
@@ -23,28 +24,35 @@ class ParserScreenRecordingLegacy extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
override getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.SCREEN_RECORDING;
|
||||
override getTraceType(): TraceType {
|
||||
return TraceType.SCREEN_RECORDING;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
return ParserScreenRecordingLegacy.MPEG4_MAGIC_NMBER;
|
||||
}
|
||||
|
||||
override decodeTrace(videoData: Uint8Array): number[] {
|
||||
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(decodedEntry: number): number {
|
||||
override getTimestamp(decodedEntry: Timestamp, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return decodedEntry;
|
||||
}
|
||||
|
||||
override processDecodedEntry(timestamp: number): ScreenRecordingTraceEntry {
|
||||
const videoTimeSeconds = (timestamp - this.timestamps[0]) / 1000000000 + ParserScreenRecordingLegacy.EPSILON;
|
||||
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(timestamp, videoTimeSeconds, videoData);
|
||||
return new ScreenRecordingTraceEntry(videoTimeSeconds, videoData);
|
||||
}
|
||||
|
||||
private searchMagicString(videoData: Uint8Array): number {
|
||||
@@ -65,15 +73,15 @@ class ParserScreenRecordingLegacy extends Parser {
|
||||
return [pos, framesCount];
|
||||
}
|
||||
|
||||
private parseTimestamps(videoData: Uint8Array, pos: number, count: number): number[] {
|
||||
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: number[] = [];
|
||||
const timestamps: Timestamp[] = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const timestamp = Number(ArrayUtils.toUintLittleEndian(videoData, pos, pos+8) * 1000n);
|
||||
const value = ArrayUtils.toUintLittleEndian(videoData, pos, pos+8) * 1000n;
|
||||
pos += 8;
|
||||
timestamps.push(timestamp);
|
||||
timestamps.push(new Timestamp(TimestampType.ELAPSED, value));
|
||||
}
|
||||
return timestamps;
|
||||
}
|
||||
|
||||
@@ -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 {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
import {Parser} from "./parser";
|
||||
@@ -30,17 +31,23 @@ describe("ParserSurfaceFlinger", () => {
|
||||
});
|
||||
|
||||
it("has expected trace type", () => {
|
||||
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.SURFACE_FLINGER);
|
||||
expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER);
|
||||
});
|
||||
|
||||
it("provides timestamps", () => {
|
||||
expect(parser.getTimestamps())
|
||||
.toEqual([850335483446, 850686322883, 850736507697]);
|
||||
it("provides elapsed timestamps", () => {
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 850335483446n),
|
||||
new Timestamp(TimestampType.ELAPSED, 850686322883n),
|
||||
new Timestamp(TimestampType.ELAPSED, 850736507697n),
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
const entry = parser.getTraceEntry(850335483446)!;
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 850335483446n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(LayerTraceEntry);
|
||||
expect(Number(entry.timestampMs)).toEqual(850335483446);
|
||||
expect(BigInt(entry.timestampMs)).toEqual(850335483446n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
* 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";
|
||||
|
||||
@@ -23,8 +24,8 @@ class ParserSurfaceFlinger extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
override getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.SURFACE_FLINGER;
|
||||
override getTraceType(): TraceType {
|
||||
return TraceType.SURFACE_FLINGER;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -35,8 +36,11 @@ class ParserSurfaceFlinger extends Parser {
|
||||
return (<any>LayersTraceFileProto.decode(buffer)).entry;
|
||||
}
|
||||
|
||||
override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(TimestampType.ELAPSED, entryProto.elapsedRealtimeNanos);
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): any {
|
||||
|
||||
@@ -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 {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
import {Parser} from "./parser";
|
||||
@@ -30,16 +31,22 @@ describe("ParserSurfaceFlingerDump", () => {
|
||||
});
|
||||
|
||||
it("has expected trace type", () => {
|
||||
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.SURFACE_FLINGER);
|
||||
expect(parser.getTraceType()).toEqual(TraceType.SURFACE_FLINGER);
|
||||
});
|
||||
|
||||
it("provides timestamp", () => {
|
||||
expect(parser.getTimestamps()).toEqual([0]);
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 0n),
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED)).toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
const entry = parser.getTraceEntry(0)!;
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 0n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(LayerTraceEntry);
|
||||
expect(Number(entry.timestampMs)).toEqual(0);
|
||||
expect(BigInt(entry.timestampMs)).toEqual(0n);
|
||||
});
|
||||
|
||||
//TODO: add real timestamp
|
||||
});
|
||||
|
||||
@@ -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 {ParserFactory} from "./parser_factory";
|
||||
import {TestUtils} from "test/test_utils";
|
||||
@@ -29,19 +30,27 @@ describe("ParserTransactions", () => {
|
||||
});
|
||||
|
||||
it("has expected trace type", () => {
|
||||
expect(parser.getTraceTypeId()).toEqual(TraceTypeId.TRANSACTIONS);
|
||||
expect(parser.getTraceType()).toEqual(TraceType.TRANSACTIONS);
|
||||
});
|
||||
|
||||
it("provides timestamps", () => {
|
||||
const timestamps = parser.getTimestamps();
|
||||
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([14862317023, 14873423549, 14884850511]);
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
expect(Number(parser.getTraceEntry(14862317023)!.elapsedRealtimeNanos))
|
||||
.toEqual(14862317023);
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 14862317023n);
|
||||
expect(BigInt(parser.getTraceEntry(timestamp)!.elapsedRealtimeNanos))
|
||||
.toEqual(14862317023n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 {TransactionsTraceFileProto} from "./proto_types";
|
||||
|
||||
@@ -22,8 +23,8 @@ class ParserTransactions extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
override getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.TRANSACTIONS;
|
||||
override getTraceType(): TraceType {
|
||||
return TraceType.TRANSACTIONS;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -34,8 +35,11 @@ class ParserTransactions extends Parser {
|
||||
return (<any>TransactionsTraceFileProto.decode(buffer)).entry;
|
||||
}
|
||||
|
||||
override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos));
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): any {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
|
||||
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";
|
||||
@@ -30,17 +31,23 @@ describe("ParserWindowManager", () => {
|
||||
});
|
||||
|
||||
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([850254319343, 850763506110, 850782750048]);
|
||||
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 entry = parser.getTraceEntry(850254319343)!;
|
||||
const timestamp = new Timestamp(TimestampType.ELAPSED, 850254319343n);
|
||||
const entry = parser.getTraceEntry(timestamp)!;
|
||||
expect(entry).toBeInstanceOf(WindowManagerState);
|
||||
expect(Number(entry.timestampMs)).toEqual(850254319343);
|
||||
expect(BigInt(entry.timestampMs)).toEqual(850254319343n);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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";
|
||||
@@ -23,8 +24,8 @@ class ParserWindowManager extends Parser {
|
||||
super(trace);
|
||||
}
|
||||
|
||||
override getTraceTypeId(): TraceTypeId {
|
||||
return TraceTypeId.WINDOW_MANAGER;
|
||||
override getTraceType(): TraceType {
|
||||
return TraceType.WINDOW_MANAGER;
|
||||
}
|
||||
|
||||
override getMagicNumber(): number[] {
|
||||
@@ -35,8 +36,11 @@ class ParserWindowManager extends Parser {
|
||||
return (<any>WindowManagerTraceFileProto.decode(buffer)).entry;
|
||||
}
|
||||
|
||||
override getTimestamp(entryProto: any): number {
|
||||
return Number(entryProto.elapsedRealtimeNanos);
|
||||
override getTimestamp(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(TimestampType.ELAPSED, BigInt(entryProto.elapsedRealtimeNanos));
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): WindowManagerState {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
|
||||
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";
|
||||
@@ -30,17 +31,23 @@ describe("ParserWindowManagerDump", () => {
|
||||
});
|
||||
|
||||
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]);
|
||||
const expected = [
|
||||
new Timestamp(TimestampType.ELAPSED, 0n),
|
||||
];
|
||||
expect(parser.getTimestamps(TimestampType.ELAPSED))
|
||||
.toEqual(expected);
|
||||
});
|
||||
|
||||
it("retrieves trace entry", () => {
|
||||
const entry = parser.getTraceEntry(0)!;
|
||||
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);
|
||||
});
|
||||
|
||||
//TODO: add real timestamp
|
||||
});
|
||||
|
||||
@@ -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(entryProto: any, type: TimestampType): undefined|Timestamp {
|
||||
if (type !== TimestampType.ELAPSED) {
|
||||
return undefined;
|
||||
}
|
||||
return new Timestamp(TimestampType.ELAPSED, 0n);
|
||||
}
|
||||
|
||||
override processDecodedEntry(entryProto: any): WindowManagerState {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user