Merge changes I2ab79fe4,I582d7c0d

* changes:
  Add ime_utils.ts
  Refactor tree_utils.ts
This commit is contained in:
Priyanka Patel
2022-09-20 09:40:47 +00:00
committed by Android (Google) Code Review
24 changed files with 529 additions and 240 deletions

View File

@@ -59,7 +59,7 @@ class ParserSurfaceFlinger extends Parser {
return undefined;
}
override processDecodedEntry(entryProto: any): any {
override processDecodedEntry(entryProto: any): LayerTraceEntry {
return LayerTraceEntry.fromProto(entryProto.layers.layers, entryProto.displays, entryProto.elapsedRealtimeNanos, entryProto.hwcBlob);
}

View File

@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { HierarchyTree } from "viewers/common/tree_utils";
import { HierarchyTreeNode } from "viewers/common/tree_utils";
import Chip from "viewers/common/chip";
class HierarchyTreeBuilder {
stableId = "";
name = "";
kind = "";
children: HierarchyTree[] = [];
children: HierarchyTreeNode[] = [];
shortName?: string;
type?: string;
id?: string | number;
@@ -76,7 +76,7 @@ class HierarchyTreeBuilder {
return this;
}
setChildren(children: HierarchyTree[]) {
setChildren(children: HierarchyTreeNode[]) {
this.children = children;
return this;
}
@@ -116,8 +116,8 @@ class HierarchyTreeBuilder {
return this;
}
build(): HierarchyTree {
const node = new HierarchyTree(this.name, this.kind, this.stableId, this.children);
build(): HierarchyTreeNode {
const node = new HierarchyTreeNode(this.name, this.kind, this.stableId, this.children);
node.chips = this.chips;
node.showInFilteredView = this.showInFilteredView;

View File

@@ -0,0 +1,108 @@
/*
* 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 {ImeUtils} from "./ime_utils";
import {UnitTestUtils} from "test/unit/utils";
import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry";
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
import {Timestamp, TimestampType} from "common/trace/timestamp";
async function getWindowManagerTraceEntry(): WindowManagerState {
const parser = await UnitTestUtils.getParser("traces/WindowManager_with_IME.pb");
const timestamp = new Timestamp(TimestampType.ELAPSED, 502938057652n);
return parser.getTraceEntry(timestamp)!;
}
async function getSurfaceFlingerTraceEntry(): LayerTraceEntry {
const parser = await UnitTestUtils.getParser("traces/SurfaceFlinger_with_IME.pb");
const timestamp = new Timestamp(TimestampType.ELAPSED, 502942319579n);
return parser.getTraceEntry(timestamp);
}
describe("ImeUtils", () => {
it("processes WindowManager trace entry", async () => {
const entry = await getWindowManagerTraceEntry();
const processed = ImeUtils.processWindowManagerTraceEntry(entry);
expect(processed.focusedApp)
.toEqual("com.google.android.apps.messaging/.ui.search.ZeroStateSearchActivity");
expect(processed.focusedActivity.token)
.toEqual("9d8c2ef");
expect(processed.focusedActivity.layerId)
.toEqual(260);
expect(processed.focusedWindow.token)
.toEqual("928b3d");
expect(processed.focusedWindow.title)
.toEqual("com.google.android.apps.messaging/com.google.android.apps.messaging.ui.search.ZeroStateSearchActivity");
expect(processed.protoImeControlTarget.windowContainer.identifier.title)
.toEqual("com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity");
expect(processed.protoImeControlTarget.windowContainer.identifier.hashCode)
.toEqual(247026562);
expect(processed.protoImeInputTarget.windowContainer.identifier.title)
.toEqual("com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity");
expect(processed.protoImeInputTarget.windowContainer.identifier.hashCode)
.toEqual(247026562);
expect(processed.protoImeInsetsSourceProvider
.insetsSourceProvider).toBeDefined();
expect(processed.protoImeLayeringTarget.windowContainer.identifier.title)
.toEqual("SnapshotStartingWindow for taskId=1393");
expect(processed.protoImeLayeringTarget.windowContainer.identifier.hashCode)
.toEqual(222907471);
expect(
processed.isInputMethodWindowVisible)
.toBeFalse();
});
it("processes SurfaceFlinger trace entry", async () => {
const processedWindowManagerState = ImeUtils.processWindowManagerTraceEntry(
await getWindowManagerTraceEntry());
const entry = await getSurfaceFlingerTraceEntry();
const layers = ImeUtils.getImeLayers(entry, processedWindowManagerState)!;
expect(layers.inputMethodSurface.id)
.toEqual(280);
expect(layers.inputMethodSurface.isVisible)
.toEqual(false);
expect(layers.inputMethodSurface.rect.label).toEqual(
"Surface(name=77f1069 InputMethod)/@0xb4afb8f - animation-leash of insets_animation#280");
expect(layers.inputMethodSurface.screenBounds)
.toBeDefined();
expect(layers.imeContainer.id)
.toEqual(12);
expect(layers.imeContainer.z).toEqual(1);
expect(layers.imeContainer.zOrderRelativeOfId)
.toEqual(115);
expect(String(layers.focusedWindow.color))
.toEqual("r:0 g:0 b:0 a:1");
expect(layers.taskOfImeContainer.kind)
.toEqual("SF subtree - 114");
expect(layers.taskOfImeContainer.name)
.toEqual("Task=1391#114");
expect(layers.taskOfImeSnapshot)
.toBeUndefined();
});
});

View File

@@ -0,0 +1,145 @@
/*
* 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 Activity from "common/trace/flickerlib/windows/Activity";
import Layer from "common/trace/flickerlib/layers/Layer";
import {LayerTraceEntry} from "common/trace/flickerlib/layers/LayerTraceEntry";
import {WindowManagerState} from "common/trace/flickerlib/windows/WindowManagerState";
import WindowState from "common/trace/flickerlib/windows/WindowState";
import {TreeUtils, FilterType} from "./tree_utils";
class ProcessedWindowManagerState {
constructor(
public stableId: string,
public focusedApp: string,
public focusedWindow: WindowState,
public focusedActivity: Activity,
public isInputMethodWindowVisible: boolean,
public protoImeControlTarget: any,
public protoImeInputTarget: any,
public protoImeLayeringTarget: any,
public protoImeInsetsSourceProvider: any) {
}
}
class ImeLayers {
constructor(
public imeContainer: Layer,
public inputMethodSurface: Layer,
public focusedWindow: Layer|undefined,
public taskOfImeContainer: Layer|undefined,
public taskOfImeSnapshot: Layer|undefined) {
}
}
class ImeUtils {
public static processWindowManagerTraceEntry(entry: WindowManagerState): ProcessedWindowManagerState {
const displayContent = entry.root.children[0];
return new ProcessedWindowManagerState(
entry.stableId,
entry.focusedApp,
entry.focusedWindow,
entry.focusedActivity,
this.isInputMethodVisible(displayContent),
this.getImeControlTargetProperty(displayContent.proto),
this.getImeInputTargetProperty(displayContent.proto),
this.getImeLayeringTargetProperty(displayContent.proto),
displayContent.proto.imeInsetsSourceProvider
);
}
public static getImeLayers(
entry: LayerTraceEntry,
processedWindowManagerState: ProcessedWindowManagerState): ImeLayers|undefined {
const isImeContainer = TreeUtils.makeNodeFilter("ImeContainer");
const imeContainer = TreeUtils.findDescendantNode(entry, isImeContainer);
if (!imeContainer) {
return undefined;
}
const isInputMethodSurface = TreeUtils.makeNodeFilter("InputMethod");
const inputMethodSurface =
TreeUtils.findDescendantNode(imeContainer, isInputMethodSurface);
let focusedWindowLayer: Layer = undefined;
const focusedWindowToken = processedWindowManagerState.focusedWindow?.token;
if (focusedWindowToken) {
const isFocusedWindow = TreeUtils.makeNodeFilter(focusedWindowToken);
focusedWindowLayer = TreeUtils.findDescendantNode(entry, isFocusedWindow);
}
// we want to see both ImeContainer and IME-snapshot if there are
// cases where both exist
const taskLayerOfImeContainer =
this.findAncestorTaskLayerOfImeLayer(entry, TreeUtils.makeNodeFilter("ImeContainer"));
const taskLayerOfImeSnapshot =
this.findAncestorTaskLayerOfImeLayer(entry, TreeUtils.makeNodeFilter("IME-snapshot"));
return new ImeLayers(
imeContainer,
inputMethodSurface,
focusedWindowLayer,
taskLayerOfImeContainer,
taskLayerOfImeSnapshot
);
}
private static findAncestorTaskLayerOfImeLayer(entry: LayerTraceEntry, isTargetImeLayer: FilterType): Layer {
const imeLayer = TreeUtils.findDescendantNode(entry, isTargetImeLayer);
if (!imeLayer) {
return undefined;
}
const isTaskLayer = TreeUtils.makeNodeFilter("Task, ImePlaceholder");
const taskLayer = <Layer>TreeUtils.findAncestorNode(imeLayer, isTaskLayer);
if (!taskLayer) {
return undefined;
}
taskLayer.kind = "SF subtree - " + taskLayer.id;
return taskLayer;
}
private static getImeControlTargetProperty(displayContentProto: any): any {
const POSSIBLE_NAMES = ["inputMethodControlTarget", "imeControlTarget"];
return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
}
private static getImeInputTargetProperty(displayContentProto: any): any {
const POSSIBLE_NAMES = ["inputMethodInputTarget", "imeInputTarget"];
return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
}
private static getImeLayeringTargetProperty(displayContentProto: any): any {
const POSSIBLE_NAMES = ["inputMethodTarget", "imeLayeringTarget"];
return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
}
private static findAnyPropertyWithMatchingName(object: any, possible_names: string[]): any {
const key = Object.keys(object).find(key => possible_names.includes(key));
return key ? object[key] : undefined;
}
private static isInputMethodVisible(windowOrLayer: any) : boolean {
const isInputMethod = TreeUtils.makeNodeFilter("InputMethod");
const inputMethodWindowOrLayer =
TreeUtils.findDescendantNode(windowOrLayer, isInputMethod);
return inputMethodWindowOrLayer?.isVisible == true;
}
}
export {ImeUtils};

View File

@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DiffType, getFilter, HierarchyTree, TreeFlickerItem } from "viewers/common/tree_utils";
import { TreeUtils, DiffType, HierarchyTreeNode, TreeNodeTrace } from "viewers/common/tree_utils";
import { TreeGenerator } from "viewers/common/tree_generator";
import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder";
describe("TreeGenerator", () => {
let entry: TreeFlickerItem;
let entry: TreeNodeTrace;
beforeAll(async () => {
entry = {
kind: "entry",
@@ -26,44 +26,47 @@ describe("TreeGenerator", () => {
stableId: "BaseLayerTraceEntry",
id: 0,
chips: [],
parent: undefined,
children: [{
kind: "3",
id: 3,
name: "Child1",
stableId: "3 Child1",
parent: undefined,
children: [
{
kind: "2",
id: 2,
name: "Child2",
stableId: "2 Child2",
children: []
parent: undefined,
children: [],
}
]}]
};
});
it("generates tree", () => {
const expected: HierarchyTree = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry")
const expected: HierarchyTreeNode = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry")
.setChildren([
new HierarchyTreeBuilder().setName("Child1").setStableId("3 Child1").setKind("3").setChildren([
new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).build()
]).setId(3).build()
]).setId(0).build();
const filter = getFilter("");
const filter = TreeUtils.makeNodeFilter("");
const generator = new TreeGenerator(entry, filter);
expect(generator.generateTree()).toEqual(expected);
});
it("generates diff tree with no diff", () => {
const expected: HierarchyTree = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry")
const expected: HierarchyTreeNode = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry")
.setChildren([
new HierarchyTreeBuilder().setName("Child1").setStableId("3 Child1").setKind("3").setChildren([
new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).setDiffType(DiffType.NONE).build()
]).setId(3).setDiffType(DiffType.NONE).build()
]).setId(0).setDiffType(DiffType.NONE).build();
const filter = getFilter("");
const filter = TreeUtils.makeNodeFilter("");
const tree = new TreeGenerator(entry, filter).withUniqueNodeId((node: any) => {
if (node) return node.stableId;
else return null;
@@ -72,19 +75,20 @@ describe("TreeGenerator", () => {
});
it("generates diff tree with moved node", () => {
const prevEntry: TreeFlickerItem = {
const prevEntry: TreeNodeTrace = {
kind: "entry",
name: "BaseLayerTraceEntry",
stableId: "BaseLayerTraceEntry",
chips: [],
id: 0,
parent: undefined,
children: [
{
kind: "3",
id: 3,
stableId: "3 Child1",
name: "Child1",
parent: undefined,
children: []
},
{
@@ -92,12 +96,13 @@ describe("TreeGenerator", () => {
id: 2,
stableId: "2 Child2",
name: "Child2",
parent: undefined,
children: [],
}
]
};
const expected: HierarchyTree = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry")
const expected: HierarchyTreeNode = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseLayerTraceEntry")
.setChildren([
new HierarchyTreeBuilder().setName("Child1").setStableId("3 Child1").setKind("3").setChildren([
new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).setDiffType(DiffType.ADDED_MOVE).build()
@@ -105,7 +110,7 @@ describe("TreeGenerator", () => {
new HierarchyTreeBuilder().setName("Child2").setStableId("2 Child2").setKind("2").setId(2).setDiffType(DiffType.DELETED_MOVE).build()
]).setId(0).setDiffType(DiffType.NONE).build();
const filter = getFilter("");
const filter = TreeUtils.makeNodeFilter("");
const generator = new TreeGenerator(entry, filter);
const newDiffTree = generator.withUniqueNodeId((node: any) => {
if (node) return node.stableId;

View File

@@ -14,12 +14,11 @@
* limitations under the License.
*/
import {
TreeUtils,
FilterType,
TreeFlickerItem,
TreeNodeTrace,
DiffType,
isVisibleNode,
isParentNode,
HierarchyTree
HierarchyTreeNode
} from "./tree_utils";
import ObjectFormatter from "common/trace/flickerlib/ObjectFormatter";
import {
@@ -31,8 +30,8 @@ import {
RELATIVE_Z_PARENT_CHIP
} from "viewers/common/chip";
type GetNodeIdCallbackType = (node: TreeFlickerItem | null) => string | null;
type IsModifiedCallbackType = (newTree: TreeFlickerItem | null, oldTree: TreeFlickerItem | null) => boolean;
type GetNodeIdCallbackType = (node: TreeNodeTrace | null) => string | null;
type IsModifiedCallbackType = (newTree: TreeNodeTrace | null, oldTree: TreeNodeTrace | null) => boolean;
const HwcCompositionType = {
CLIENT: 1,
@@ -45,18 +44,18 @@ export class TreeGenerator {
private isSimplifyNames = false;
private isFlatView = false;
private filter: FilterType;
private inputEntry: TreeFlickerItem;
private previousEntry: TreeFlickerItem | null = null;
private inputEntry: TreeNodeTrace;
private previousEntry: TreeNodeTrace | null = null;
private getNodeId?: GetNodeIdCallbackType;
private isModified?: IsModifiedCallbackType;
private newMapping: Map<string, TreeFlickerItem> | null = null;
private oldMapping: Map<string, TreeFlickerItem> | null = null;
private newMapping: Map<string, TreeNodeTrace> | null = null;
private oldMapping: Map<string, TreeNodeTrace> | null = null;
private readonly pinnedIds: Array<string>;
private pinnedItems: Array<HierarchyTree> = [];
private pinnedItems: Array<HierarchyTreeNode> = [];
private relZParentIds: Array<string> = [];
private flattenedChildren: Array<HierarchyTree> = [];
private flattenedChildren: Array<HierarchyTreeNode> = [];
constructor(inputEntry: TreeFlickerItem, filter: FilterType, pinnedIds?: Array<string>) {
constructor(inputEntry: TreeNodeTrace, filter: FilterType, pinnedIds?: Array<string>) {
this.inputEntry = inputEntry;
this.filter = filter;
this.pinnedIds = pinnedIds ?? [];
@@ -77,17 +76,17 @@ export class TreeGenerator {
return this;
}
public generateTree(): HierarchyTree | null {
public generateTree(): HierarchyTreeNode | null {
return this.getCustomisedTree(this.inputEntry);
}
public compareWith(previousEntry: TreeFlickerItem | null): TreeGenerator {
public compareWith(previousEntry: TreeNodeTrace | null): TreeGenerator {
this.previousEntry = previousEntry;
return this;
}
public withUniqueNodeId(getNodeId?: GetNodeIdCallbackType): TreeGenerator {
this.getNodeId = (node: TreeFlickerItem | null) => {
this.getNodeId = (node: TreeNodeTrace | null) => {
const id = getNodeId ? getNodeId(node) : this.defaultNodeIdCallback(node);
if (id === null || id === undefined) {
console.error("Null node ID for node", node);
@@ -103,17 +102,18 @@ export class TreeGenerator {
return this;
}
public generateFinalTreeWithDiff(): HierarchyTree | null {
public generateFinalTreeWithDiff(): HierarchyTreeNode | null {
this.newMapping = this.generateIdToNodeMapping(this.inputEntry);
this.oldMapping = this.previousEntry ? this.generateIdToNodeMapping(this.previousEntry) : null;
const diffTrees = this.generateDiffTree(this.inputEntry, this.previousEntry, [], []);
let diffTree;
let diffTree: TreeNodeTrace;
if (diffTrees.length > 1) {
diffTree = {
kind: "",
name: "DiffTree",
parent: undefined,
children: diffTrees,
stableId: "DiffTree",
};
@@ -123,7 +123,7 @@ export class TreeGenerator {
return this.getCustomisedTree(diffTree);
}
private getCustomisedTree(tree: TreeFlickerItem | null): HierarchyTree | null {
private getCustomisedTree(tree: TreeNodeTrace | null): HierarchyTreeNode | null {
if (!tree) return null;
let newTree = this.generateTreeWithUserOptions(tree, false);
if (!newTree) return null;
@@ -136,14 +136,14 @@ export class TreeGenerator {
return Object.freeze(newTree);
}
public getPinnedItems(): Array<HierarchyTree> {
public getPinnedItems(): Array<HierarchyTreeNode> {
return this.pinnedItems;
}
private flattenChildren(children: Array<HierarchyTree>) {
private flattenChildren(children: Array<HierarchyTreeNode>) {
for (let i = 0; i < children.length; i++) {
const child = children[i];
const childIsVisibleNode = child.isVisible && isVisibleNode(child.kind, child.type);
const childIsVisibleNode = child.isVisible && TreeUtils.isVisibleNode(child.kind, child.type);
const showInOnlyVisibleView = this.isOnlyVisibleView && childIsVisibleNode;
const passVisibleCheck = !this.isOnlyVisibleView || showInOnlyVisibleView;
if (this.filterMatches(child) && passVisibleCheck) {
@@ -155,25 +155,25 @@ export class TreeGenerator {
}
}
private filterMatches(item: HierarchyTree | null): boolean {
private filterMatches(item: HierarchyTreeNode | null): boolean {
return this.filter(item) ?? false;
}
private generateTreeWithUserOptions(
tree: TreeFlickerItem,
tree: TreeNodeTrace,
parentFilterMatch: boolean
): HierarchyTree | null {
): HierarchyTreeNode | null {
return this.applyChecks(
tree,
parentFilterMatch
);
}
private updateTreeWithRelZParentChips(tree: HierarchyTree): HierarchyTree {
private updateTreeWithRelZParentChips(tree: HierarchyTreeNode): HierarchyTreeNode {
return this.applyRelZParentCheck(tree);
}
private applyRelZParentCheck(tree: HierarchyTree) {
private applyRelZParentCheck(tree: HierarchyTreeNode) {
if (tree.id && tree.chips && this.relZParentIds.includes(`${tree.id}`)) {
tree.chips.push(RELATIVE_Z_PARENT_CHIP);
}
@@ -186,7 +186,7 @@ export class TreeGenerator {
return tree;
}
private addChips(tree: HierarchyTree): HierarchyTree {
private addChips(tree: HierarchyTreeNode): HierarchyTreeNode {
tree.chips = [];
if (tree.hwcCompositionType == HwcCompositionType.CLIENT) {
tree.chips.push(GPU_CHIP);
@@ -194,13 +194,13 @@ export class TreeGenerator {
tree.hwcCompositionType == HwcCompositionType.SOLID_COLOR)) {
tree.chips.push(HWC_CHIP);
}
if (tree.isVisible && isVisibleNode(tree.kind, tree.type)) {
if (tree.isVisible && TreeUtils.isVisibleNode(tree.kind, tree.type)) {
tree.chips.push(VISIBLE_CHIP);
}
if (
tree.zOrderRelativeOfId !== undefined
&& tree.zOrderRelativeOfId !== -1
&& !isParentNode(tree.kind)
&& !TreeUtils.isParentNode(tree.kind)
&& !tree.isRootLayer
) {
tree.chips.push(RELATIVE_Z_CHIP);
@@ -213,9 +213,9 @@ export class TreeGenerator {
}
private applyChecks(
tree: TreeFlickerItem,
tree: TreeNodeTrace,
parentFilterMatch: boolean
): HierarchyTree | null {
): HierarchyTreeNode | null {
let newTree = this.getTreeNode(tree);
// add id field to tree if id does not exist (e.g. for WM traces)
@@ -227,7 +227,7 @@ export class TreeGenerator {
newTree.simplifyNames = this.isSimplifyNames;
// check item either matches filter, or has parents/children matching filter
if (isParentNode(tree.kind) || parentFilterMatch) {
if (TreeUtils.isParentNode(tree.kind) || parentFilterMatch) {
newTree.showInFilteredView = true;
} else {
newTree.showInFilteredView = this.filterMatches(tree);
@@ -271,8 +271,8 @@ export class TreeGenerator {
return newTree;
}
private generateIdToNodeMapping(node: TreeFlickerItem, acc?: Map<string, TreeFlickerItem>): Map<string, TreeFlickerItem> {
acc = acc || new Map<string, TreeFlickerItem>();
private generateIdToNodeMapping(node: TreeNodeTrace, acc?: Map<string, TreeNodeTrace>): Map<string, TreeNodeTrace> {
acc = acc || new Map<string, TreeNodeTrace>();
const nodeId: string = this.getNodeId!(node)!;
@@ -289,7 +289,7 @@ export class TreeGenerator {
return acc;
}
private cloneDiffTreeNode(node: TreeFlickerItem | null): TreeFlickerItem | null {
private cloneDiffTreeNode(node: TreeNodeTrace | null): TreeNodeTrace | null {
const clone = ObjectFormatter.cloneObject(node);
if (node) {
clone.children = node.children;
@@ -304,8 +304,8 @@ export class TreeGenerator {
return clone;
}
private getTreeNode(node: TreeFlickerItem): HierarchyTree {
const clone = new HierarchyTree(
private getTreeNode(node: TreeNodeTrace): HierarchyTreeNode {
const clone = new HierarchyTreeNode(
node.name,
node.kind,
node.stableId,
@@ -327,11 +327,11 @@ export class TreeGenerator {
}
private generateDiffTree(
newTree: TreeFlickerItem | null,
oldTree: TreeFlickerItem | null,
newTreeSiblings: Array<TreeFlickerItem | null>,
oldTreeSiblings: Array<TreeFlickerItem | null>
): Array<TreeFlickerItem> {
newTree: TreeNodeTrace | null,
oldTree: TreeNodeTrace | null,
newTreeSiblings: Array<TreeNodeTrace | null>,
oldTreeSiblings: Array<TreeNodeTrace | null>
): Array<TreeNodeTrace> {
const diffTrees = [];
// NOTE: A null ID represents a non existent node.
if (!this.getNodeId) {
@@ -350,9 +350,9 @@ export class TreeGenerator {
// Default to no changes
diffTree.diffType = DiffType.NONE;
if (!isParentNode(newTree.kind) && newId !== oldId) {
if (!TreeUtils.isParentNode(newTree.kind) && newId !== oldId) {
// A move, addition, or deletion has occurred
let nextOldTree: TreeFlickerItem | null = null;
let nextOldTree: TreeNodeTrace | null = null;
// Check if newTree has been added or moved
if (newId && !oldTreeSiblingIds.includes(newId)) {
@@ -422,7 +422,7 @@ export class TreeGenerator {
return diffTrees;
}
private visitChildren(newTree: TreeFlickerItem | null, oldTree: TreeFlickerItem | null): Array<TreeFlickerItem> {
private visitChildren(newTree: TreeNodeTrace | null, oldTree: TreeNodeTrace | null): Array<TreeNodeTrace> {
// Recursively traverse all children of new and old tree.
const diffChildren = [];
const numOfChildren = Math.max(newTree?.children?.length ?? 0, oldTree?.children?.length ?? 0);
@@ -440,14 +440,14 @@ export class TreeGenerator {
return diffChildren;
}
private defaultNodeIdCallback(node: TreeFlickerItem | null): string | null {
private defaultNodeIdCallback(node: TreeNodeTrace | null): string | null {
return node ? node.stableId : null;
}
private defaultModifiedCheck(newNode: TreeFlickerItem | null, oldNode: TreeFlickerItem | null): boolean {
private defaultModifiedCheck(newNode: TreeNodeTrace | null, oldNode: TreeNodeTrace | null): boolean {
if (!newNode && !oldNode) {
return false;
} else if (newNode && isParentNode(newNode.kind)) {
} else if (newNode && TreeUtils.isParentNode(newNode.kind)) {
return false;
} else if ((newNode && !oldNode) || (!newNode && oldNode)) {
return true;

View File

@@ -14,11 +14,11 @@
* limitations under the License.
*/
import { TreeTransformer } from "viewers/common/tree_transformer";
import { DiffType, getFilter, HierarchyTree, Terminal, TreeFlickerItem } from "viewers/common/tree_utils";
import { TreeUtils, DiffType, HierarchyTreeNode, Terminal, TreeNodeTrace } from "viewers/common/tree_utils";
describe("TreeTransformer", () => {
let entry: TreeFlickerItem;
let selectedTree: HierarchyTree;
let entry: TreeNodeTrace;
let selectedTree: HierarchyTreeNode;
beforeAll(async () => {
entry = {
id: 3,
@@ -34,10 +34,12 @@ describe("TreeTransformer", () => {
type: "ContainerLayer",
},
chips: [],
parent: undefined,
children: [{
id: 2,
name: "Child2",
stackId: 0,
parent: undefined,
children: [],
kind: "2",
stableId: "2 Child2",
@@ -104,7 +106,7 @@ describe("TreeTransformer", () => {
propertyValue: null
};
const filter = getFilter("");
const filter = TreeUtils.makeNodeFilter("");
const transformer = new TreeTransformer(selectedTree, filter)
.showOnlyProtoDump()
.setProperties(entry);
@@ -145,7 +147,7 @@ describe("TreeTransformer", () => {
propertyValue: null,
};
const filter = getFilter("");
const filter = TreeUtils.makeNodeFilter("");
const transformer = new TreeTransformer(selectedTree, filter)
.setIsShowDiff(true)
.showOnlyProtoDump()

View File

@@ -17,11 +17,11 @@ import ObjectFormatter from "common/trace/flickerlib/ObjectFormatter";
import {
FilterType,
PropertiesTree,
PropertiesTreeNode,
DiffType,
Terminal,
TreeFlickerItem,
HierarchyTree,
TreeNodeTrace,
HierarchyTreeNode,
PropertiesDump
} from "./tree_utils";
@@ -49,7 +49,7 @@ export class TreeTransformer {
keepOriginal: false, freeze: true, metadataKey: null,
};
constructor(selectedTree: HierarchyTree, filter: FilterType) {
constructor(selectedTree: HierarchyTreeNode, filter: FilterType) {
this.stableId = this.compatibleStableId(selectedTree);
this.rootName = selectedTree.name;
this.filter = filter;
@@ -79,7 +79,7 @@ export class TreeTransformer {
return this;
}
public setProperties(currentEntry: TreeFlickerItem): TreeTransformer {
public setProperties(currentEntry: TreeNodeTrace): TreeTransformer {
const currFlickerItem = this.getOriginalFlickerItem(currentEntry, this.stableId);
const target = currFlickerItem ? currFlickerItem.obj ?? currFlickerItem : null;
ObjectFormatter.displayDefaults = this.isShowDefaults;
@@ -87,7 +87,7 @@ export class TreeTransformer {
return this;
}
public setDiffProperties(previousEntry: TreeFlickerItem | null): TreeTransformer {
public setDiffProperties(previousEntry: TreeNodeTrace | null): TreeTransformer {
if (this.isShowDiff) {
const prevFlickerItem = this.findFlickerItem(previousEntry, this.stableId);
const target = prevFlickerItem ? prevFlickerItem.obj ?? prevFlickerItem : null;
@@ -96,11 +96,11 @@ export class TreeTransformer {
return this;
}
public getOriginalFlickerItem(entry: TreeFlickerItem, stableId: string): TreeFlickerItem | null {
public getOriginalFlickerItem(entry: TreeNodeTrace, stableId: string): TreeNodeTrace | null {
return this.findFlickerItem(entry, stableId);
}
private getProtoDumpPropertiesForDisplay(entry: TreeFlickerItem): PropertiesDump | null {
private getProtoDumpPropertiesForDisplay(entry: TreeNodeTrace): PropertiesDump | null {
if (!entry) {
return null;
}
@@ -120,7 +120,7 @@ export class TreeTransformer {
return obj;
}
private getPropertiesForDisplay(entry: TreeFlickerItem): PropertiesDump | null {
private getPropertiesForDisplay(entry: TreeNodeTrace): PropertiesDump | null {
if (!entry) {
return null;
}
@@ -155,7 +155,7 @@ export class TreeTransformer {
return obj;
}
private findFlickerItem(entryFlickerItem: TreeFlickerItem | null, stableId: string): TreeFlickerItem | null {
private findFlickerItem(entryFlickerItem: TreeNodeTrace | null, stableId: string): TreeNodeTrace | null {
if (!entryFlickerItem) {
return null;
}
@@ -179,7 +179,7 @@ export class TreeTransformer {
}
public transform(): PropertiesTree {
public transform(): PropertiesTreeNode {
const {formatter} = this.options!;
if (!formatter) {
throw new Error("Missing formatter, please set with setOptions()");
@@ -198,7 +198,7 @@ export class TreeTransformer {
compareWithName: string | Terminal,
stableId: string,
transformOptions: TransformOptions,
): PropertiesTree {
): PropertiesTreeNode {
const originalProperties = properties;
const metadata = this.getMetadata(
originalProperties, transformOptions.metadataKey
@@ -305,7 +305,7 @@ export class TreeTransformer {
return transformOptions.freeze ? Object.freeze(transformedProperties) : transformedProperties;
}
private hasChildMatchingFilter(children: PropertiesTree[] | null | undefined): boolean {
private hasChildMatchingFilter(children: PropertiesTreeNode[] | null | undefined): boolean {
if (!children || children.length === 0) return false;
let match = false;
@@ -350,9 +350,9 @@ export class TreeTransformer {
return this.filter(item) ?? false;
}
private transformProperties(properties: PropertiesDump, metadataKey: string | null): PropertiesTree {
private transformProperties(properties: PropertiesDump, metadataKey: string | null): PropertiesTreeNode {
const {skip, formatter} = this.options!;
const transformedProperties: PropertiesTree = {
const transformedProperties: PropertiesTreeNode = {
properties: {},
};
let formatted = undefined;
@@ -399,7 +399,7 @@ export class TreeTransformer {
}
}
private compatibleStableId(item: HierarchyTree): string {
private compatibleStableId(item: HierarchyTreeNode): string {
// For backwards compatibility
// (the only item that doesn't have a unique stable ID in the tree)
if (item.stableId === "winToken|-|") {

View File

@@ -16,21 +16,49 @@
import Chip from "./chip";
export type FilterType = (item: HierarchyTree | PropertiesTree | null) => boolean;
export type FilterType = (item: HierarchyTreeNode | PropertiesTreeNode | null) => boolean;
export type Tree = HierarchyTree | PropertiesTree;
export type UiTreeNode = HierarchyTreeNode | PropertiesTreeNode;
export class HierarchyTree {
export interface TreeNodeTrace {
parent: TreeNodeTrace|undefined;
children: TreeNodeTrace[];
name: string;
kind: string;
stableId: string;
displays?: TreeNodeTrace[];
windowStates?: TreeNodeTrace[];
shortName?: string;
type?: string;
id?: string | number;
layerId?: number;
displayId?: number;
stackId?: number;
isVisible?: boolean;
isMissing?: boolean;
hwcCompositionType?: number;
zOrderRelativeOfId?: number;
isRootLayer?: boolean;
chips?: Chip[];
diffType?: string;
skip?: any;
equals?: any;
obj?: any;
get?: any;
proto?: any;
}
export class HierarchyTreeNode {
constructor(
public name: string,
public kind: string,
public stableId: string,
children?: HierarchyTree[]
children?: HierarchyTreeNode[]
) {
this.children = children ?? [];
}
children: HierarchyTree[];
children: HierarchyTreeNode[];
shortName?: string;
type?: string;
id?: string | number;
@@ -52,42 +80,15 @@ export class HierarchyTree {
skip?: any;
}
export interface TreeFlickerItem {
children: TreeFlickerItem[];
name: string;
kind: string;
stableId: string;
displays?: TreeFlickerItem[];
windowStates?: TreeFlickerItem[];
shortName?: string;
type?: string;
id?: string | number;
layerId?: number;
displayId?: number;
stackId?: number;
isVisible?: boolean;
isMissing?: boolean;
hwcCompositionType?: number;
zOrderRelativeOfId?: number;
isRootLayer?: boolean;
chips?: Chip[];
diffType?: string;
skip?: any;
equals?: any;
obj?: any;
get?: any;
proto?: any;
}
export interface PropertiesDump {
[key: string]: any;
}
export interface PropertiesTree {
export interface PropertiesTreeNode {
properties?: any;
kind?: string;
stableId?: string;
children?: PropertiesTree[];
children?: PropertiesTreeNode[];
propertyKey?: string | Terminal | null;
propertyValue?: string | Terminal | null;
name?: string | Terminal;
@@ -106,46 +107,74 @@ export const DiffType = {
export class Terminal {}
export function diffClass(item: Tree): string {
const diffType = item.diffType;
return diffType ?? "";
}
export function isHighlighted(item: Tree, highlightedItems: Array<string>) {
return item instanceof HierarchyTree && highlightedItems.includes(`${item.id}`);
}
export function getFilter(filterString: string): FilterType {
const filterStrings = filterString.split(",");
const positive: any[] = [];
const negative: any[] = [];
filterStrings.forEach((f) => {
f = f.trim();
if (f.startsWith("!")) {
const regex = new RegExp(f.substring(1), "i");
negative.push((s:any) => !regex.test(s));
} else {
const regex = new RegExp(f, "i");
positive.push((s:any) => regex.test(s));
export class TreeUtils
{
public static findDescendantNode(node: TreeNodeTrace, isTargetNode: FilterType): TreeNodeTrace|undefined {
if (isTargetNode(node)) {
return node;
}
});
const filter = (item: any) => {
if (item) {
const apply = (f:any) => f(`${item.name}`);
return (positive.length === 0 || positive.some(apply)) &&
(negative.length === 0 || negative.every(apply));
for (const child of node.children) {
const target = this.findDescendantNode(child, isTargetNode);
if (target) {
return target;
}
}
return false;
};
return filter;
}
const parentNodeKinds = ["entry", "WindowManagerState"];
return undefined;
}
export function isParentNode(kind: string) {
return parentNodeKinds.includes(kind);
}
public static findAncestorNode(node: TreeNodeTrace, isTargetNode: FilterType): TreeNodeTrace|undefined {
let ancestor = node.parent;
export function isVisibleNode(kind: string, type?: string) {
return kind === "WindowState" || kind === "Activity" || type?.includes("Layer");
while (ancestor && !isTargetNode(ancestor)) {
ancestor = ancestor.parent;
}
return ancestor;
}
public static makeNodeFilter(filterString: string): FilterType {
const filterStrings = filterString.split(",");
const positive: any[] = [];
const negative: any[] = [];
filterStrings.forEach((f) => {
f = f.trim();
if (f.startsWith("!")) {
const regex = new RegExp(f.substring(1), "i");
negative.push((s: any) => !regex.test(s));
} else {
const regex = new RegExp(f, "i");
positive.push((s: any) => regex.test(s));
}
});
const filter = (item: any) => {
if (item) {
const apply = (f: any) => f(`${item.name}`);
return (positive.length === 0 || positive.some(apply)) &&
(negative.length === 0 || negative.every(apply));
}
return false;
};
return filter;
}
public static diffClass(item: UiTreeNode): string {
const diffType = item.diffType;
return diffType ?? "";
}
public static isHighlighted(item: UiTreeNode, highlightedItems: Array<string>) {
return item instanceof HierarchyTreeNode && highlightedItems.includes(`${item.id}`);
}
public static isVisibleNode(kind: string, type?: string) {
return kind === "WindowState" || kind === "Activity" || type?.includes("Layer");
}
public static isParentNode(kind: string) {
return this.PARENT_NODE_KINDS.includes(kind);
}
private static readonly PARENT_NODE_KINDS = ["entry", "WindowManagerState"];
}

View File

@@ -22,7 +22,7 @@ import { MatInputModule } from "@angular/material/input";
import { MatFormFieldModule } from "@angular/material/form-field";
import { MatCheckboxModule } from "@angular/material/checkbox";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { HierarchyTree } from "viewers/common/tree_utils";
import { HierarchyTreeNode } from "viewers/common/tree_utils";
import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder";
describe("HierarchyComponent", () => {

View File

@@ -16,7 +16,7 @@
import { Component, Input, Inject, ElementRef } from "@angular/core";
import { UserOptions } from "viewers/common/user_options";
import { PersistentStore } from "common/persistent_store";
import { HierarchyTree, diffClass, isHighlighted, Tree } from "viewers/common/tree_utils";
import { TreeUtils, HierarchyTreeNode, UiTreeNode } from "viewers/common/tree_utils";
import { nodeStyles } from "viewers/components/styles/node.styles";
import { ViewerEvents } from "viewers/common/viewer_events";
import { TraceType } from "common/trace/trace_type";
@@ -147,13 +147,13 @@ import { TraceType } from "common/trace/trace_type";
export class HierarchyComponent {
objectKeys = Object.keys;
filterString = "";
diffClass = diffClass;
isHighlighted = isHighlighted;
diffClass = TreeUtils.diffClass;
isHighlighted = TreeUtils.isHighlighted;
@Input() tree!: HierarchyTree | null;
@Input() tree!: HierarchyTreeNode | null;
@Input() dependencies: Array<TraceType> = [];
@Input() highlightedItems: Array<string> = [];
@Input() pinnedItems: Array<HierarchyTree> = [];
@Input() pinnedItems: Array<HierarchyTreeNode> = [];
@Input() store!: PersistentStore;
@Input() userOptions: UserOptions = {};
@@ -172,7 +172,7 @@ export class HierarchyComponent {
};
}
public onPinnedNodeClick(event: MouseEvent, pinnedItem: HierarchyTree) {
public onPinnedNodeClick(event: MouseEvent, pinnedItem: HierarchyTreeNode) {
event.preventDefault();
if (window.getSelection()?.type === "range") {
return;
@@ -211,8 +211,8 @@ export class HierarchyComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public selectedTreeChange(item: Tree) {
if (!(item instanceof HierarchyTree)) {
public selectedTreeChange(item: UiTreeNode) {
if (!(item instanceof HierarchyTreeNode)) {
return;
}
const event: CustomEvent = new CustomEvent(
@@ -224,8 +224,8 @@ export class HierarchyComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public pinnedItemChange(item: Tree) {
if (!(item instanceof HierarchyTree)) {
public pinnedItemChange(item: UiTreeNode) {
if (!(item instanceof HierarchyTreeNode)) {
return;
}
const event: CustomEvent = new CustomEvent(

View File

@@ -16,7 +16,7 @@
import { Component, Input, Inject, ElementRef } from "@angular/core";
import { UserOptions } from "viewers/common/user_options";
import { ViewerEvents } from "viewers/common/viewer_events";
import { PropertiesTree, Terminal, TreeFlickerItem } from "viewers/common/tree_utils";
import { PropertiesTreeNode, Terminal, TreeNodeTrace } from "viewers/common/tree_utils";
@Component({
selector: "properties-view",
@@ -134,8 +134,8 @@ export class PropertiesComponent {
filterString = "";
@Input() userOptions: UserOptions = {};
@Input() propertiesTree: PropertiesTree = {};
@Input() selectedFlickerItem: TreeFlickerItem | null = null;
@Input() propertiesTree: PropertiesTreeNode = {};
@Input() selectedFlickerItem: TreeNodeTrace | null = null;
@Input() propertyGroups = false;
constructor(

View File

@@ -16,7 +16,7 @@
import { Component, Inject, Input, Output, ElementRef, EventEmitter } from "@angular/core";
import { PersistentStore } from "common/persistent_store";
import { nodeStyles, treeNodeDataViewStyles } from "viewers/components/styles/node.styles";
import { Tree, diffClass, isHighlighted, PropertiesTree, Terminal, isParentNode, HierarchyTree } from "viewers/common/tree_utils";
import { TreeUtils, UiTreeNode, HierarchyTreeNode } from "viewers/common/tree_utils";
import { TraceType } from "common/trace/trace_type";
@Component({
@@ -77,17 +77,17 @@ import { TraceType } from "common/trace/trace_type";
})
export class TreeComponent {
diffClass = diffClass;
isHighlighted = isHighlighted;
diffClass = TreeUtils.diffClass;
isHighlighted = TreeUtils.isHighlighted;
@Input() item!: Tree;
@Input() item!: UiTreeNode;
@Input() dependencies: Array<TraceType> = [];
@Input() store!: PersistentStore;
@Input() isFlattened? = false;
@Input() isShaded? = false;
@Input() initialDepth = 0;
@Input() highlightedItems: Array<string> = [];
@Input() pinnedItems?: Array<HierarchyTree> = [];
@Input() pinnedItems?: Array<HierarchyTreeNode> = [];
@Input() itemsClickable?: boolean;
@Input() useGlobalCollapsedState?: boolean;
@Input() isAlwaysCollapsed?: boolean;
@@ -95,8 +95,8 @@ export class TreeComponent {
@Input() isLeaf: (item: any) => boolean = (item: any) => !item.children || item.children.length === 0;
@Output() highlightedItemChange = new EventEmitter<string>();
@Output() selectedTreeChange = new EventEmitter<Tree>();
@Output() pinnedItemChange = new EventEmitter<Tree>();
@Output() selectedTreeChange = new EventEmitter<UiTreeNode>();
@Output() pinnedItemChange = new EventEmitter<UiTreeNode>();
@Output() hoverStart = new EventEmitter<void>();
@Output() hoverEnd = new EventEmitter<void>();
@@ -123,7 +123,7 @@ export class TreeComponent {
}
ngOnChanges() {
if (this.item instanceof HierarchyTree && isHighlighted(this.item, this.highlightedItems)) {
if (this.item instanceof HierarchyTreeNode && TreeUtils.isHighlighted(this.item, this.highlightedItems)) {
this.selectedTreeChange.emit(this.item);
}
}
@@ -159,7 +159,7 @@ export class TreeComponent {
}
private updateHighlightedItems() {
if (this.item instanceof HierarchyTree) {
if (this.item instanceof HierarchyTreeNode) {
if (this.item && this.item.id) {
this.highlightedItemChange.emit(`${this.item.id}`);
} else if (!this.item.id) {
@@ -169,7 +169,7 @@ export class TreeComponent {
}
public isPinned() {
if (this.item instanceof HierarchyTree) {
if (this.item instanceof HierarchyTreeNode) {
return this.pinnedItems?.map(item => `${item.id}`).includes(`${this.item.id}`);
}
return false;
@@ -179,11 +179,11 @@ export class TreeComponent {
this.highlightedItemChange.emit(newId);
}
public propagateNewPinnedItem(newPinnedItem: Tree) {
public propagateNewPinnedItem(newPinnedItem: UiTreeNode) {
this.pinnedItemChange.emit(newPinnedItem);
}
public propagateNewSelectedTree(newTree: Tree) {
public propagateNewSelectedTree(newTree: UiTreeNode) {
this.selectedTreeChange.emit(newTree);
}
@@ -211,12 +211,12 @@ export class TreeComponent {
return this.localCollapsedState;
}
public children(): Tree[] {
public children(): UiTreeNode[] {
return this.item.children ?? [];
}
public hasChildren() {
const isParentEntryInFlatView = isParentNode(this.item.kind ?? "") && this.isFlattened;
const isParentEntryInFlatView = TreeUtils.isParentNode(this.item.kind ?? "") && this.isFlattened;
return (!this.isFlattened || isParentEntryInFlatView) && !this.isLeaf(this.item);
}

View File

@@ -15,7 +15,7 @@
*/
import { Component, Input, Output, EventEmitter } from "@angular/core";
import { nodeInnerItemStyles } from "viewers/components/styles/node.styles";
import { Tree, DiffType, isParentNode, HierarchyTree } from "viewers/common/tree_utils";
import { TreeUtils, UiTreeNode, DiffType, HierarchyTreeNode } from "viewers/common/tree_utils";
@Component({
selector: "tree-node",
@@ -76,7 +76,7 @@ import { Tree, DiffType, isParentNode, HierarchyTree } from "viewers/common/tree
})
export class TreeNodeComponent {
@Input() item!: Tree;
@Input() item!: UiTreeNode;
@Input() isLeaf?: boolean;
@Input() flattened?: boolean;
@Input() isCollapsed?: boolean;
@@ -87,7 +87,7 @@ export class TreeNodeComponent {
@Output() toggleTreeChange = new EventEmitter<void>();
@Output() expandTreeChange = new EventEmitter<boolean>();
@Output() pinNodeChange = new EventEmitter<Tree>();
@Output() pinNodeChange = new EventEmitter<UiTreeNode>();
collapseDiffClass = "";
@@ -96,11 +96,11 @@ export class TreeNodeComponent {
}
public isPropertiesTreeNode() {
return !(this.item instanceof HierarchyTree);
return !(this.item instanceof HierarchyTreeNode);
}
public showPinNodeIcon() {
return (!this.isPropertiesTreeNode() && !isParentNode(this.item.kind ?? "")) ?? false;
return (!this.isPropertiesTreeNode() && !TreeUtils.isParentNode(this.item.kind ?? "")) ?? false;
}
public toggleTree(event: MouseEvent) {
@@ -148,7 +148,7 @@ export class TreeNodeComponent {
return DiffType.MODIFIED;
}
private getAllDiffTypesOfChildren(item: Tree) {
private getAllDiffTypesOfChildren(item: UiTreeNode) {
if (!item.children) {
return new Set();
}

View File

@@ -15,7 +15,7 @@
*/
import { Component, Input } from "@angular/core";
import { treeNodeDataViewStyles } from "viewers/components/styles/tree_node_data_view.styles";
import { Terminal, HierarchyTree, Tree } from "viewers/common/tree_utils";
import { Terminal, HierarchyTreeNode, UiTreeNode } from "viewers/common/tree_utils";
import Chip from "viewers/common/chip";
@Component({
@@ -37,14 +37,14 @@ import Chip from "viewers/common/chip";
})
export class TreeNodeDataViewComponent {
@Input() item!: Tree;
@Input() item!: UiTreeNode;
public chips() {
return (this.item instanceof HierarchyTree) ? this.item.chips : [];
return (this.item instanceof HierarchyTreeNode) ? this.item.chips : [];
}
public itemShortName() {
return (this.item instanceof HierarchyTree)? this.item.shortName : "";
return (this.item instanceof HierarchyTreeNode)? this.item.shortName : "";
}
public itemTooltip() {
@@ -55,7 +55,7 @@ export class TreeNodeDataViewComponent {
}
public showShortName() {
return (this.item instanceof HierarchyTree) && this.item.simplifyNames && this.item.shortName !== this.item.name;
return (this.item instanceof HierarchyTreeNode) && this.item.simplifyNames && this.item.shortName !== this.item.name;
}
public chipClass(chip: Chip) {

View File

@@ -15,7 +15,7 @@
*/
import { Component, Input } from "@angular/core";
import { treeNodePropertiesDataViewStyles } from "viewers/components/styles/tree_node_data_view.styles";
import { PropertiesTree } from "viewers/common/tree_utils";
import { PropertiesTreeNode } from "viewers/common/tree_utils";
@Component({
selector: "tree-node-properties-data-view",
@@ -30,7 +30,7 @@ import { PropertiesTree } from "viewers/common/tree_utils";
})
export class TreeNodePropertiesDataViewComponent {
@Input() item!: PropertiesTree;
@Input() item!: PropertiesTreeNode;
public valueClass() {
if (!this.item.propertyValue) {

View File

@@ -18,7 +18,7 @@ import { UiData } from "./ui_data";
import { UserOptions } from "viewers/common/user_options";
import { TraceType } from "common/trace/trace_type";
import { LayerTraceEntry } from "common/trace/flickerlib/common";
import { HierarchyTree, PropertiesTree } from "viewers/common/tree_utils";
import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/tree_utils";
import { UnitTestUtils } from "test/unit/utils";
import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder";
@@ -26,7 +26,7 @@ describe("PresenterSurfaceFlinger", () => {
let presenter: Presenter;
let uiData: UiData;
let entries: Map<TraceType, any>;
let selectedTree: HierarchyTree;
let selectedTree: HierarchyTreeNode;
beforeAll(async () => {
entries = new Map<TraceType, any>();
@@ -182,14 +182,14 @@ describe("PresenterSurfaceFlinger", () => {
presenter.notifyCurrentTraceEntries(entries);
presenter.newPropertiesTree(selectedTree);
let nonTerminalChildren = uiData.propertiesTree?.children?.filter(
(child: PropertiesTree) => typeof child.propertyKey === "string"
(child: PropertiesTreeNode) => typeof child.propertyKey === "string"
) ?? [];
expect(nonTerminalChildren.length).toEqual(55);
presenter.filterPropertiesTree("bound");
nonTerminalChildren = uiData.propertiesTree?.children?.filter(
(child: PropertiesTree) => typeof child.propertyKey === "string"
(child: PropertiesTreeNode) => typeof child.propertyKey === "string"
) ?? [];
expect(nonTerminalChildren.length).toEqual(3);
});

View File

@@ -18,7 +18,7 @@ import { UiData } from "./ui_data";
import { Rectangle, RectMatrix, RectTransform } from "viewers/common/rectangle";
import { TraceType } from "common/trace/trace_type";
import { UserOptions } from "viewers/common/user_options";
import { getFilter, FilterType, HierarchyTree, Tree, TreeFlickerItem, PropertiesTree } from "viewers/common/tree_utils";
import { TreeUtils, FilterType, HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/tree_utils";
import { TreeGenerator } from "viewers/common/tree_generator";
import { TreeTransformer } from "viewers/common/tree_transformer";
import { Layer, LayerTraceEntry } from "common/trace/flickerlib/common";
@@ -32,7 +32,7 @@ export class Presenter {
this.notifyViewCallback(this.uiData);
}
public updatePinnedItems(pinnedItem: HierarchyTree) {
public updatePinnedItems(pinnedItem: HierarchyTreeNode) {
const pinnedId = `${pinnedItem.id}`;
if (this.pinnedItems.map(item => `${item.id}`).includes(pinnedId)) {
this.pinnedItems = this.pinnedItems.filter(pinned => `${pinned.id}` != pinnedId);
@@ -63,7 +63,7 @@ export class Presenter {
}
public filterHierarchyTree(filterString: string) {
this.hierarchyFilter = getFilter(filterString);
this.hierarchyFilter = TreeUtils.makeNodeFilter(filterString);
this.uiData.tree = this.generateTree();
this.notifyViewCallback(this.uiData);
}
@@ -75,11 +75,11 @@ export class Presenter {
}
public filterPropertiesTree(filterString: string) {
this.propertiesFilter = getFilter(filterString);
this.propertiesFilter = TreeUtils.makeNodeFilter(filterString);
this.updateSelectedTreeUiData();
}
public newPropertiesTree(selectedItem: HierarchyTree) {
public newPropertiesTree(selectedItem: HierarchyTreeNode) {
this.selectedHierarchyTree = selectedItem;
this.updateSelectedTreeUiData();
}
@@ -145,7 +145,7 @@ export class Presenter {
.setIsSimplifyNames(this.hierarchyUserOptions["simplifyNames"]?.enabled)
.setIsFlatView(this.hierarchyUserOptions["flat"]?.enabled)
.withUniqueNodeId();
let tree: HierarchyTree | null;
let tree: HierarchyTreeNode | null;
if (!this.hierarchyUserOptions["showDiff"]?.enabled) {
tree = generator.generateTree();
} else {
@@ -210,7 +210,7 @@ export class Presenter {
}
}
private getTreeWithTransformedProperties(selectedTree: HierarchyTree): PropertiesTree {
private getTreeWithTransformedProperties(selectedTree: HierarchyTreeNode): PropertiesTreeNode {
const transformer = new TreeTransformer(selectedTree, this.propertiesFilter)
.showOnlyProtoDump()
.setIsShowDefaults(this.propertiesUserOptions["showDefaults"]?.enabled)
@@ -225,13 +225,13 @@ export class Presenter {
private readonly notifyViewCallback: NotifyViewCallbackType;
private uiData: UiData;
private hierarchyFilter: FilterType = getFilter("");
private propertiesFilter: FilterType = getFilter("");
private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter("");
private propertiesFilter: FilterType = TreeUtils.makeNodeFilter("");
private highlightedItems: Array<string> = [];
private displayIds: Array<number> = [];
private pinnedItems: Array<HierarchyTree> = [];
private pinnedItems: Array<HierarchyTreeNode> = [];
private pinnedIds: Array<string> = [];
private selectedHierarchyTree: HierarchyTree | null = null;
private selectedHierarchyTree: HierarchyTreeNode | null = null;
private selectedLayer: LayerTraceEntry | Layer | null = null;
private previousEntry: LayerTraceEntry | null = null;
private entry: LayerTraceEntry | null = null;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { HierarchyTree, PropertiesTree } from "viewers/common/tree_utils";
import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/tree_utils";
import { UserOptions } from "viewers/common/user_options";
import { Layer } from "common/trace/flickerlib/common";
import { TraceType } from "common/trace/trace_type";
@@ -25,10 +25,10 @@ export class UiData {
displayIds: number[] = [];
hasVirtualDisplays = false;
highlightedItems: Array<string> = [];
pinnedItems: Array<HierarchyTree> = [];
pinnedItems: Array<HierarchyTreeNode> = [];
hierarchyUserOptions: UserOptions = {};
propertiesUserOptions: UserOptions = {};
tree: HierarchyTree | null = null;
propertiesTree: PropertiesTree | null = null;
tree: HierarchyTreeNode | null = null;
propertiesTree: PropertiesTreeNode | null = null;
selectedLayer: Layer = {};
}

View File

@@ -1,4 +1,4 @@
9;/*
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@ import { UiData } from "./ui_data";
import { UserOptions } from "viewers/common/user_options";
import { TraceType } from "common/trace/trace_type";
import { WindowManagerState } from "common/trace/flickerlib/common";
import { PropertiesTree, Terminal, HierarchyTree } from "viewers/common/tree_utils";
import { PropertiesTreeNode, Terminal, HierarchyTreeNode } from "viewers/common/tree_utils";
import { UnitTestUtils } from "test/unit/utils";
import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder";
import { VISIBLE_CHIP } from "viewers/common/chip";
@@ -27,7 +27,7 @@ describe("PresenterWindowManager", () => {
let presenter: Presenter;
let uiData: UiData;
let entries: Map<TraceType, any>;
let selectedTree: HierarchyTree;
let selectedTree: HierarchyTreeNode;
beforeAll(async () => {
entries = new Map<TraceType, any>();
@@ -187,14 +187,14 @@ describe("PresenterWindowManager", () => {
presenter.newPropertiesTree(selectedTree);
let nonTerminalChildren = uiData.propertiesTree?.children?.filter(
(child: PropertiesTree) => typeof child.propertyKey === "string"
(child: PropertiesTreeNode) => typeof child.propertyKey === "string"
) ?? [];
expect(nonTerminalChildren.length).toEqual(45);
presenter.filterPropertiesTree("visible");
nonTerminalChildren = uiData.propertiesTree?.children?.filter(
(child: PropertiesTree) => typeof child.propertyKey === "string"
(child: PropertiesTreeNode) => typeof child.propertyKey === "string"
) ?? [];
expect(nonTerminalChildren.length).toEqual(4);
});

View File

@@ -17,7 +17,7 @@ import { UiData } from "./ui_data";
import { Rectangle, RectMatrix, RectTransform } from "viewers/common/rectangle";
import { TraceType } from "common/trace/trace_type";
import { UserOptions } from "viewers/common/user_options";
import { getFilter, FilterType, Tree, HierarchyTree, PropertiesTree, TreeFlickerItem } from "viewers/common/tree_utils";
import { TreeUtils, FilterType, HierarchyTreeNode, PropertiesTreeNode, TreeNodeTrace } from "viewers/common/tree_utils";
import { TreeGenerator } from "viewers/common/tree_generator";
import { TreeTransformer } from "viewers/common/tree_transformer";
import DisplayContent from "common/trace/flickerlib/windows/DisplayContent";
@@ -31,7 +31,7 @@ export class Presenter {
this.notifyViewCallback(this.uiData);
}
public updatePinnedItems(pinnedItem: HierarchyTree) {
public updatePinnedItems(pinnedItem: HierarchyTreeNode) {
const pinnedId = `${pinnedItem.id}`;
if (this.pinnedItems.map(item => `${item.id}`).includes(pinnedId)) {
this.pinnedItems = this.pinnedItems.filter(pinned => `${pinned.id}` != pinnedId);
@@ -62,7 +62,7 @@ export class Presenter {
}
public filterHierarchyTree(filterString: string) {
this.hierarchyFilter = getFilter(filterString);
this.hierarchyFilter = TreeUtils.makeNodeFilter(filterString);
this.uiData.tree = this.generateTree();
this.notifyViewCallback(this.uiData);
}
@@ -74,11 +74,11 @@ export class Presenter {
}
public filterPropertiesTree(filterString: string) {
this.propertiesFilter = getFilter(filterString);
this.propertiesFilter = TreeUtils.makeNodeFilter(filterString);
this.updateSelectedTreeUiData();
}
public newPropertiesTree(selectedTree: HierarchyTree) {
public newPropertiesTree(selectedTree: HierarchyTreeNode) {
this.selectedHierarchyTree = selectedTree;
this.updateSelectedTreeUiData();
}
@@ -143,7 +143,7 @@ export class Presenter {
.setIsSimplifyNames(this.hierarchyUserOptions["simplifyNames"]?.enabled)
.setIsFlatView(this.hierarchyUserOptions["flat"]?.enabled)
.withUniqueNodeId();
let tree: HierarchyTree | null;
let tree: HierarchyTreeNode | null;
if (!this.hierarchyUserOptions["showDiff"]?.enabled) {
tree = generator.generateTree();
} else {
@@ -208,7 +208,7 @@ export class Presenter {
}
}
private getTreeWithTransformedProperties(selectedTree: HierarchyTree): PropertiesTree {
private getTreeWithTransformedProperties(selectedTree: HierarchyTreeNode): PropertiesTreeNode {
if (!this.entry) {
return {};
}
@@ -225,15 +225,15 @@ export class Presenter {
private readonly notifyViewCallback: NotifyViewCallbackType;
private uiData: UiData;
private hierarchyFilter: FilterType = getFilter("");
private propertiesFilter: FilterType = getFilter("");
private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter("");
private propertiesFilter: FilterType = TreeUtils.makeNodeFilter("");
private highlightedItems: Array<string> = [];
private displayIds: Array<number> = [];
private pinnedItems: Array<HierarchyTree> = [];
private pinnedItems: Array<HierarchyTreeNode> = [];
private pinnedIds: Array<string> = [];
private selectedHierarchyTree: HierarchyTree | null = null;
private previousEntry: TreeFlickerItem | null = null;
private entry: TreeFlickerItem | null = null;
private selectedHierarchyTree: HierarchyTreeNode | null = null;
private previousEntry: TreeNodeTrace | null = null;
private entry: TreeNodeTrace | null = null;
private hierarchyUserOptions: UserOptions = {
showDiff: {
name: "Show diff",

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { HierarchyTree, PropertiesTree } from "viewers/common/tree_utils";
import { HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/tree_utils";
import { UserOptions } from "viewers/common/user_options";
import { TraceType } from "common/trace/trace_type";
import { Rectangle } from "viewers/common/rectangle";
@@ -23,9 +23,9 @@ export class UiData {
rects: Rectangle[] = [];
displayIds: number[] = [];
highlightedItems: Array<string> = [];
pinnedItems: Array<HierarchyTree> = [];
pinnedItems: Array<HierarchyTreeNode> = [];
hierarchyUserOptions: UserOptions = {};
propertiesUserOptions: UserOptions = {};
tree: HierarchyTree | null = null;
propertiesTree: PropertiesTree | null = null;
tree: HierarchyTreeNode | null = null;
propertiesTree: PropertiesTreeNode | null = null;
}