diff --git a/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts b/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts index a507093cd..d28931b3a 100644 --- a/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts +++ b/tools/winscope-ng/src/common/trace/flickerlib/ObjectFormatter.ts @@ -88,7 +88,7 @@ export default class ObjectFormatter { * @param obj The raw object to format * @return The formatted object */ - static format(obj: any): {} { + static format(obj: any): any { const properties = this.getProperties(obj); const sortedProperties = properties.sort() diff --git a/tools/winscope-ng/src/test/unit/hierarchy_tree_builder.ts b/tools/winscope-ng/src/test/unit/hierarchy_tree_builder.ts new file mode 100644 index 000000000..9ba551c7b --- /dev/null +++ b/tools/winscope-ng/src/test/unit/hierarchy_tree_builder.ts @@ -0,0 +1,162 @@ +/* + * 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 { HierarchyTree } from "viewers/common/tree_utils"; +import Chip from "viewers/common/chip"; + +class HierarchyTreeBuilder { + stableId = ""; + name = ""; + kind = ""; + children: HierarchyTree[] = []; + shortName?: string; + type?: string; + id?: string | number; + layerId?: number; + displayId?: number; + stackId?: number; + isVisible?: boolean; + isMissing?: boolean; + hwcCompositionType?: number; + zOrderRelativeOfId?: number; + zOrderRelativeOf?: any; + zOrderRelativeParentOf?: any; + isRootLayer?: boolean; + showInFilteredView = true; + showInOnlyVisibleView?: boolean; + simplifyNames = false; + chips: Chip[] = []; + diffType?: string; + skip?: any; + + setId(id: number) { + this.id = id; + return this; + } + + setKind(kind: string) { + this.kind = kind; + return this; + } + + setStableId(stableId: string) { + this.stableId = stableId; + return this; + } + + setName(name: string) { + this.name = name; + return this; + } + + setShortName(shortName: string) { + this.shortName = shortName; + return this; + } + + setChips(chips: Chip[]) { + this.chips = chips; + return this; + } + + setDiffType(diffType: string) { + this.diffType = diffType; + return this; + } + + setChildren(children: HierarchyTree[]) { + this.children = children; + return this; + } + + setDisplayId(displayId: number) { + this.displayId = displayId; + return this; + } + + setLayerId(layerId: number) { + this.layerId = layerId; + return this; + } + + setStackId(stackId: number) { + this.stackId = stackId; + return this; + } + + setIsVisible(isVisible: boolean) { + this.isVisible = isVisible; + return this; + } + + setVisibleView(showInOnlyVisibleView: boolean) { + this.showInOnlyVisibleView = showInOnlyVisibleView; + return this; + } + + setFilteredView(showInFilteredView: boolean) { + this.showInFilteredView = showInFilteredView; + return this; + } + + setSimplifyNames(simplifyNames: boolean) { + this.simplifyNames = simplifyNames; + return this; + } + + build(): HierarchyTree { + const node = new HierarchyTree(this.name, this.kind, this.stableId, this.children); + + node.chips = this.chips; + node.showInFilteredView = this.showInFilteredView; + node.simplifyNames = this.simplifyNames; + + if (this.id) { + node.id = this.id; + } + + if (this.diffType) { + node.diffType = this.diffType; + } + + if (this.displayId) { + node.displayId = this.displayId; + } + + if (this.layerId) { + node.layerId = this.layerId; + } + + if (this.stackId) { + node.stackId = this.stackId; + } + + if (this.isVisible) { + node.isVisible = this.isVisible; + } + + if (this.showInOnlyVisibleView) { + node.showInOnlyVisibleView = this.showInOnlyVisibleView; + } + + if (this.shortName) { + node.shortName = this.shortName; + } + + return node; + } +} + +export {HierarchyTreeBuilder}; diff --git a/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts b/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts index 2fed8fde5..0da5f9d76 100644 --- a/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts +++ b/tools/winscope-ng/src/viewers/common/tree_generator.spec.ts @@ -13,237 +13,105 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { DiffType, getFilter } from "viewers/common/tree_utils"; +import { DiffType, getFilter, HierarchyTree, TreeFlickerItem } from "viewers/common/tree_utils"; import { TreeGenerator } from "viewers/common/tree_generator"; +import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; describe("TreeGenerator", () => { - it("generates tree", () => { - const tree = { + let entry: TreeFlickerItem; + beforeAll(async () => { + entry = { kind: "entry", name: "BaseLayerTraceEntry", - shortName: "BLTE", + stableId: "BaseLayerTraceEntry", id: 0, chips: [], children: [{ kind: "3", - id: "3", + id: 3, name: "Child1", + stableId: "3 Child1", children: [ { kind: "2", - id: "2", + id: 2, name: "Child2", + stableId: "2 Child2", children: [] } ]}] }; - const expected = { - simplifyNames: false, - name: "BaseLayerTraceEntry", - id: 0, - children: [ - { - id: "3", - name: "Child1", - children: [{ - kind: "2", - id: "2", - name: "Child2", - children: [], - simplifyNames: false, - showInFilteredView: true, - stableId: undefined, - shortName: undefined, - chips: [] - }], - kind: "3", - simplifyNames: false, - showInFilteredView: true, - stableId: undefined, - shortName: undefined, - chips: [], - } - ], - kind: "entry", - stableId: undefined, - shortName: "BLTE", - chips: [], - showInFilteredView: true, - }; + }); + it("generates tree", () => { + const expected: HierarchyTree = 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 generator = new TreeGenerator(tree, filter); + const generator = new TreeGenerator(entry, filter); expect(generator.generateTree()).toEqual(expected); }); it("generates diff tree with no diff", () => { - const tree = { - kind: "entry", - name: "BaseLayerTraceEntry", - shortName: "BLTE", - stableId: "0", - chips: [], - id: 0, - children: [{ - kind: "3", - id: "3", - stableId: "3", - name: "Child1", - children: [ - { - kind: "2", - id: "2", - stableId: "2", - name: "Child2", - } - ]}] - }; - const newTree = tree; - const expected = { - simplifyNames: false, - name: "BaseLayerTraceEntry", - id: 0, - stableId: "0", - children: [ - { - id: "3", - stableId: "3", - name: "Child1", - children: [{ - kind: "2", - id: "2", - name: "Child2", - children: [], - simplifyNames: false, - showInFilteredView: true, - stableId: "2", - shortName: undefined, - diffType: DiffType.NONE, - chips: [] - }], - kind: "3", - shortName: undefined, - simplifyNames: false, - showInFilteredView: true, - chips: [], - diffType: DiffType.NONE - } - ], - kind: "entry", - shortName: "BLTE", - chips: [], - diffType: DiffType.NONE, - showInFilteredView: true, - }; + const expected: HierarchyTree = 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 generator = new TreeGenerator(tree, filter); - expect(generator.withUniqueNodeId((node: any) => { + const tree = new TreeGenerator(entry, filter).withUniqueNodeId((node: any) => { if (node) return node.stableId; else return null; - }).compareWith(newTree).generateFinalDiffTree()).toEqual(expected); + }).compareWith(entry).generateFinalTreeWithDiff(); + expect(tree).toEqual(expected); }); it("generates diff tree with moved node", () => { - const tree = { + const prevEntry: TreeFlickerItem = { kind: "entry", name: "BaseLayerTraceEntry", - shortName: "BLTE", - stableId: "0", - chips: [], - id: 0, - children: [{ - kind: "3", - id: "3", - stableId: "3", - name: "Child1", - children: [ - { - kind: "2", - id: "2", - stableId: "2", - name: "Child2", - } - ]}] - }; - const newTree = { - kind: "entry", - name: "BaseLayerTraceEntry", - shortName: "BLTE", - stableId: "0", + stableId: "BaseLayerTraceEntry", chips: [], id: 0, + children: [ { kind: "3", - id: "3", - stableId: "3", + id: 3, + stableId: "3 Child1", name: "Child1", children: [] }, { kind: "2", - id: "2", - stableId: "2", + id: 2, + stableId: "2 Child2", name: "Child2", + children: [], } ] }; - const expected = { - simplifyNames: false, - name: "BaseLayerTraceEntry", - id: 0, - stableId: "0", - children: [ - { - id: "3", - stableId: "3", - name: "Child1", - children: [ { - kind: "2", - id: "2", - name: "Child2", - children: [], - simplifyNames: false, - showInFilteredView: true, - stableId: "2", - shortName: undefined, - diffType: DiffType.ADDED_MOVE, - chips: [] - }], - kind: "3", - shortName: undefined, - simplifyNames: false, - showInFilteredView: true, - chips: [], - diffType: DiffType.NONE - }, - { - kind: "2", - id: "2", - name: "Child2", - children: [], - simplifyNames: false, - showInFilteredView: true, - stableId: "2", - shortName: undefined, - chips: [], - diffType: DiffType.DELETED_MOVE - } - ], - kind: "entry", - shortName: "BLTE", - chips: [], - diffType: DiffType.NONE, - showInFilteredView: true - }; + + const expected: HierarchyTree = 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() + ]).setId(3).setDiffType(DiffType.NONE).build(), + 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 generator = new TreeGenerator(tree, filter); + const generator = new TreeGenerator(entry, filter); const newDiffTree = generator.withUniqueNodeId((node: any) => { if (node) return node.stableId; else return null; - }).compareWith(newTree).generateFinalDiffTree(); + }).compareWith(prevEntry).generateFinalTreeWithDiff(); + expect(newDiffTree).toEqual(expected); }); }); diff --git a/tools/winscope-ng/src/viewers/common/tree_generator.ts b/tools/winscope-ng/src/viewers/common/tree_generator.ts index 13de1b3a3..34f7af2e2 100644 --- a/tools/winscope-ng/src/viewers/common/tree_generator.ts +++ b/tools/winscope-ng/src/viewers/common/tree_generator.ts @@ -15,10 +15,11 @@ */ import { FilterType, - Tree, + TreeFlickerItem, DiffType, isVisibleNode, - isParentNode + isParentNode, + HierarchyTree } from "./tree_utils"; import ObjectFormatter from "common/trace/flickerlib/ObjectFormatter"; import { @@ -30,11 +31,9 @@ import { RELATIVE_Z_PARENT_CHIP } from "viewers/common/chip"; -type GetNodeIdCallbackType = (node: Tree | null) => number | null; -type IsModifiedCallbackType = (newTree: Tree | null, oldTree: Tree | null) => boolean; -interface IdNodeMap { - [key: string]: Tree -} +type GetNodeIdCallbackType = (node: TreeFlickerItem | null) => string | null; +type IsModifiedCallbackType = (newTree: TreeFlickerItem | null, oldTree: TreeFlickerItem | null) => boolean; + const HwcCompositionType = { CLIENT: 1, DEVICE: 2, @@ -46,49 +45,49 @@ export class TreeGenerator { private isSimplifyNames = false; private isFlatView = false; private filter: FilterType; - private tree: Tree; - private diffWithTree: Tree | null = null; + private inputEntry: TreeFlickerItem; + private previousEntry: TreeFlickerItem | null = null; private getNodeId?: GetNodeIdCallbackType; private isModified?: IsModifiedCallbackType; - private newMapping: IdNodeMap | null = null; - private oldMapping: IdNodeMap | null = null; + private newMapping: Map | null = null; + private oldMapping: Map | null = null; private readonly pinnedIds: Array; - private pinnedItems: Array = []; - private relZParentIds: Array = []; - private flattenedChildren: Array = []; + private pinnedItems: Array = []; + private relZParentIds: Array = []; + private flattenedChildren: Array = []; - constructor(tree: Tree, filter: FilterType, pinnedIds?: Array) { - this.tree = tree; + constructor(inputEntry: TreeFlickerItem, filter: FilterType, pinnedIds?: Array) { + this.inputEntry = inputEntry; this.filter = filter; this.pinnedIds = pinnedIds ?? []; } - public setIsOnlyVisibleView(enabled: boolean) { + public setIsOnlyVisibleView(enabled: boolean): TreeGenerator { this.isOnlyVisibleView = enabled; return this; } - public setIsSimplifyNames(enabled: boolean) { + public setIsSimplifyNames(enabled: boolean): TreeGenerator { this.isSimplifyNames = enabled; return this; } - public setIsFlatView(enabled: boolean) { + public setIsFlatView(enabled: boolean): TreeGenerator { this.isFlatView = enabled; return this; } - public generateTree(): Tree { - return this.getCustomisedTree(this.tree); + public generateTree(): HierarchyTree | null { + return this.getCustomisedTree(this.inputEntry); } - public compareWith(tree: Tree | null): TreeGenerator { - this.diffWithTree = tree; + public compareWith(previousEntry: TreeFlickerItem | null): TreeGenerator { + this.previousEntry = previousEntry; return this; } public withUniqueNodeId(getNodeId?: GetNodeIdCallbackType): TreeGenerator { - this.getNodeId = (node: Tree | null) => { + this.getNodeId = (node: TreeFlickerItem | null) => { const id = getNodeId ? getNodeId(node) : this.defaultNodeIdCallback(node); if (id === null || id === undefined) { console.error("Null node ID for node", node); @@ -104,11 +103,11 @@ export class TreeGenerator { return this; } - public generateFinalDiffTree(): Tree { - this.newMapping = this.generateIdToNodeMapping(this.tree); - this.oldMapping = this.diffWithTree ? this.generateIdToNodeMapping(this.diffWithTree) : null; + public generateFinalTreeWithDiff(): HierarchyTree | null { + this.newMapping = this.generateIdToNodeMapping(this.inputEntry); + this.oldMapping = this.previousEntry ? this.generateIdToNodeMapping(this.previousEntry) : null; - const diffTrees = this.generateDiffTree(this.tree, this.diffWithTree, [], []); + const diffTrees = this.generateDiffTree(this.inputEntry, this.previousEntry, [], []); let diffTree; if (diffTrees.length > 1) { @@ -124,23 +123,24 @@ export class TreeGenerator { return this.getCustomisedTree(diffTree); } - private getCustomisedTree(tree: Tree | null) { + private getCustomisedTree(tree: TreeFlickerItem | null): HierarchyTree | null { if (!tree) return null; - tree = this.generateTreeWithUserOptions(tree, false); - tree = this.updateTreeWithRelZParentChips(tree); + let newTree = this.generateTreeWithUserOptions(tree, false); + if (!newTree) return null; + newTree = this.updateTreeWithRelZParentChips(newTree); - if (this.isFlatView && tree.children) { - this.flattenChildren(tree.children); - tree.children = this.flattenedChildren; + if (this.isFlatView && newTree.children) { + this.flattenChildren(newTree.children); + newTree.children = this.flattenedChildren; } - return Object.freeze(tree); + return Object.freeze(newTree); } - public getPinnedItems() { + public getPinnedItems(): Array { return this.pinnedItems; } - private flattenChildren(children: Array): Tree { + private flattenChildren(children: Array) { for (let i = 0; i < children.length; i++) { const child = children[i]; const childIsVisibleNode = child.isVisible && isVisibleNode(child.kind, child.type); @@ -155,27 +155,26 @@ export class TreeGenerator { } } - private filterMatches(item: Tree | null): boolean { + private filterMatches(item: HierarchyTree | null): boolean { return this.filter(item) ?? false; } private generateTreeWithUserOptions( - tree: Tree | null, + tree: TreeFlickerItem, parentFilterMatch: boolean - ): Tree | null { - return tree ? this.applyChecks( + ): HierarchyTree | null { + return this.applyChecks( tree, - this.cloneNode(tree, true), parentFilterMatch - ) : null; + ); } - private updateTreeWithRelZParentChips(tree: Tree): Tree { + private updateTreeWithRelZParentChips(tree: HierarchyTree): HierarchyTree { return this.applyRelZParentCheck(tree); } - private applyRelZParentCheck(tree: Tree) { - if (this.relZParentIds.includes(tree.id)) { + private applyRelZParentCheck(tree: HierarchyTree) { + if (tree.id && tree.chips && this.relZParentIds.includes(`${tree.id}`)) { tree.chips.push(RELATIVE_Z_PARENT_CHIP); } @@ -187,7 +186,7 @@ export class TreeGenerator { return tree; } - private addChips(tree: Tree) { + private addChips(tree: HierarchyTree): HierarchyTree { tree.chips = []; if (tree.hwcCompositionType == HwcCompositionType.CLIENT) { tree.chips.push(GPU_CHIP); @@ -205,7 +204,7 @@ export class TreeGenerator { && !tree.isRootLayer ) { tree.chips.push(RELATIVE_Z_CHIP); - this.relZParentIds.push(tree.zOrderRelativeOfId); + this.relZParentIds.push(`${tree.zOrderRelativeOfId}`); } if (tree.isMissing) { tree.chips.push(MISSING_LAYER); @@ -214,16 +213,13 @@ export class TreeGenerator { } private applyChecks( - tree: Tree | null, - newTree: Tree | null, + tree: TreeFlickerItem, parentFilterMatch: boolean - ): Tree | null { - if (!tree || !newTree) { - return null; - } + ): HierarchyTree | null { + let newTree = this.getTreeNode(tree); // add id field to tree if id does not exist (e.g. for WM traces) - if (!newTree.id && newTree.layerId) { + if (!newTree?.id && newTree?.layerId) { newTree.id = newTree.layerId; } @@ -275,15 +271,15 @@ export class TreeGenerator { return newTree; } - private generateIdToNodeMapping(node: Tree, acc?: IdNodeMap): IdNodeMap { - acc = acc || {}; + private generateIdToNodeMapping(node: TreeFlickerItem, acc?: Map): Map { + acc = acc || new Map(); - const nodeId = this.getNodeId!(node)!; + const nodeId: string = this.getNodeId!(node)!; - if (acc[nodeId]) { + if (acc.get(nodeId)) { throw new Error(`Duplicate node id '${nodeId}' detected...`); } - acc[nodeId] = node; + acc.set(nodeId, node); if (node.children) { for (const child of node.children) { @@ -293,7 +289,7 @@ export class TreeGenerator { return acc; } - private cloneNode(node: Tree | null, postDiff = false): Tree | null { + private cloneDiffTreeNode(node: TreeFlickerItem | null): TreeFlickerItem | null { const clone = ObjectFormatter.cloneObject(node); if (node) { clone.children = node.children; @@ -301,22 +297,41 @@ export class TreeGenerator { clone.kind = node.kind; clone.stableId = node.stableId; clone.shortName = node.shortName; - if ("chips" in node) { + if (node.chips) { clone.chips = node.chips.slice(); } - if (postDiff && "diffType" in node) { - clone.diffType = node.diffType; - } } return clone; } + private getTreeNode(node: TreeFlickerItem): HierarchyTree { + const clone = new HierarchyTree( + node.name, + node.kind, + node.stableId, + ); + if (node.shortName) clone.shortName = node.shortName; + if (node.type) clone.type = node.type; + if (node.id) clone.id = node.id; + if (node.layerId) clone.layerId = node.layerId; + if (node.isVisible) clone.isVisible = node.isVisible; + if (node.isMissing) clone.isMissing = node.isMissing; + if (node.hwcCompositionType) clone.hwcCompositionType = node.hwcCompositionType; + if (node.zOrderRelativeOfId) clone.zOrderRelativeOfId = node.zOrderRelativeOfId; + if (node.isRootLayer) clone.isRootLayer = node.isRootLayer; + if (node.chips) clone.chips = node.chips.slice(); + if (node.diffType) clone.diffType = node.diffType; + if (node.skip) clone.skip = node.skip; + + return clone; + } + private generateDiffTree( - newTree: Tree | null, - oldTree: Tree | null, - newTreeSiblings: Array, - oldTreeSiblings: Array - ): Array { + newTree: TreeFlickerItem | null, + oldTree: TreeFlickerItem | null, + newTreeSiblings: Array, + oldTreeSiblings: Array + ): Array { const diffTrees = []; // NOTE: A null ID represents a non existent node. if (!this.getNodeId) { @@ -330,24 +345,24 @@ export class TreeGenerator { if (newTree) { // Clone is required because trees are frozen objects — we can't modify the original tree object. - const diffTree = this.cloneNode(newTree)!; + const diffTree = this.cloneDiffTreeNode(newTree)!; // Default to no changes diffTree.diffType = DiffType.NONE; if (!isParentNode(newTree.kind) && newId !== oldId) { // A move, addition, or deletion has occurred - let nextOldTree = null; + let nextOldTree: TreeFlickerItem | null = null; // Check if newTree has been added or moved if (newId && !oldTreeSiblingIds.includes(newId)) { - if (this.oldMapping && this.oldMapping[newId]) { + if (this.oldMapping && this.oldMapping.get(newId)) { // Objected existed in old tree, so DELETED_MOVE will be/has been flagged and added to the // diffTree when visiting it in the oldTree. diffTree.diffType = DiffType.ADDED_MOVE; // Switch out oldTree for new one to compare against - nextOldTree = this.oldMapping[newId]; + nextOldTree = this.oldMapping.get(newId) ?? null; } else { diffTree.diffType = DiffType.ADDED; @@ -358,9 +373,9 @@ export class TreeGenerator { // Check if oldTree has been deleted of moved if (oldId && oldTree && !newTreeSiblingIds.includes(oldId)) { - const deletedTreeDiff = this.cloneNode(oldTree)!; + const deletedTreeDiff = this.cloneDiffTreeNode(oldTree)!; - if (this.newMapping![oldId]) { + if (this.newMapping && this.newMapping.get(oldId)) { deletedTreeDiff.diffType = DiffType.DELETED_MOVE; // Stop comparing against oldTree, will be/has been @@ -388,10 +403,10 @@ export class TreeGenerator { } else if (oldTree) { if (oldId && !newTreeSiblingIds.includes(oldId)) { // Deep clone oldTree omitting children field - const diffTree = this.cloneNode(oldTree)!; + const diffTree = this.cloneDiffTreeNode(oldTree)!; // newTree doesn't exist, oldTree has either been moved or deleted. - if (this.newMapping![oldId]) { + if (this.newMapping && this.newMapping.get(oldId)) { diffTree.diffType = DiffType.DELETED_MOVE; } else { diffTree.diffType = DiffType.DELETED; @@ -407,39 +422,38 @@ export class TreeGenerator { return diffTrees; } - private visitChildren(newTree: Tree | null, oldTree: Tree | null) { + private visitChildren(newTree: TreeFlickerItem | null, oldTree: TreeFlickerItem | null): Array { // Recursively traverse all children of new and old tree. const diffChildren = []; - - if (!newTree) newTree = {}; - if (!oldTree) oldTree = {}; - const numOfChildren = Math.max(newTree.children?.length ?? 0, oldTree.children?.length ?? 0); + const numOfChildren = Math.max(newTree?.children?.length ?? 0, oldTree?.children?.length ?? 0); for (let i = 0; i < numOfChildren; i++) { - const newChild = newTree.children ? newTree.children[i] : null; - const oldChild = oldTree.children ? oldTree.children[i] : null; + const newChild = newTree?.children ? newTree.children[i] : null; + const oldChild = oldTree?.children ? oldTree.children[i] : null; const childDiffTrees = this.generateDiffTree( newChild, oldChild, - newTree.children ?? [], oldTree.children ?? [], - ); + newTree?.children ?? [], oldTree?.children ?? [], + ).filter(tree => tree != null); diffChildren.push(...childDiffTrees); } return diffChildren; } - private defaultNodeIdCallback(node: Tree | null): number | null { + private defaultNodeIdCallback(node: TreeFlickerItem | null): string | null { return node ? node.stableId : null; } - private defaultModifiedCheck(newNode: Tree | null, oldNode: Tree | null): boolean { + private defaultModifiedCheck(newNode: TreeFlickerItem | null, oldNode: TreeFlickerItem | null): boolean { if (!newNode && !oldNode) { return false; } else if (newNode && isParentNode(newNode.kind)) { return false; } else if ((newNode && !oldNode) || (!newNode && oldNode)) { return true; + } else if (newNode?.equals) { + return !newNode.equals(oldNode); } - return !newNode.equals(oldNode); + return false; } } diff --git a/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts b/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts index f78a597a8..ea57d7c77 100644 --- a/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts +++ b/tools/winscope-ng/src/viewers/common/tree_transformer.spec.ts @@ -14,21 +14,19 @@ * limitations under the License. */ import { TreeTransformer } from "viewers/common/tree_transformer"; -import { DiffType, getFilter, Terminal } from "viewers/common/tree_utils"; +import { DiffType, getFilter, HierarchyTree, Terminal, TreeFlickerItem } from "viewers/common/tree_utils"; describe("TreeTransformer", () => { - it("creates ordinary properties tree without show diff enabled", () => { - const selectedTree = { - id: "3", + let entry: TreeFlickerItem; + let selectedTree: HierarchyTree; + beforeAll(async () => { + entry = { + id: 3, name: "Child1", stackId: 0, isVisible: true, kind: "3", stableId: "3 Child1", - shortName: undefined, - simplifyNames: true, - showInFilteredView: true, - skip: null, proto: { barrierLayer: [], id: 3, @@ -37,14 +35,12 @@ describe("TreeTransformer", () => { }, chips: [], children: [{ - id: "2", + id: 2, name: "Child2", stackId: 0, children: [], kind: "2", stableId: "2 Child2", - shortName: undefined, - simplifyNames: true, proto: { barrierLayer: [], id: 2, @@ -52,10 +48,34 @@ describe("TreeTransformer", () => { type: "ContainerLayer", }, isVisible: true, + }], + }; + + selectedTree = { + id: 3, + name: "Child1", + stackId: 0, + isVisible: true, + kind: "3", + stableId: "3 Child1", + showInFilteredView: true, + skip: null, + chips: [], + children: [{ + id: 2, + name: "Child2", + stackId: 0, + children: [], + kind: "2", + stableId: "2 Child2", + isVisible: true, showInFilteredView: true, chips: [], }], }; + }); + + it("creates ordinary properties tree without show diff enabled", () => { const expected = { kind: "", name: "Child1", @@ -63,88 +83,37 @@ describe("TreeTransformer", () => { children: [ { kind: "", - name: "proto", - stableId: "3 Child1.proto", - children: [ - { - kind: "", - name: "id: empty", - stableId: "3 Child1.proto.id", - children: [], - combined: true, - propertyKey: "id", - propertyValue: "empty"}, - { - kind: "", - name: "type: ContainerLayer", - stableId: "3 Child1.proto.type", - children: [], - combined: true, - propertyKey: "type", - propertyValue: "ContainerLayer" - } - ], - propertyKey: "proto", - propertyValue: null, + name: "id: empty", + stableId: "3 Child1.id", + children: [], + combined: true, + propertyKey: "id", + propertyValue: "empty" }, { kind: "", - name: new Terminal(), - stableId: "3 Child1.null", - children: [] - } + name: "type: ContainerLayer", + stableId: "3 Child1.type", + children: [], + combined: true, + propertyKey: "type", + propertyValue: "ContainerLayer" + }, ], propertyKey: "Child1", propertyValue: null }; const filter = getFilter(""); - const transformer = new TreeTransformer(selectedTree, filter); + const transformer = new TreeTransformer(selectedTree, filter) + .showOnlyProtoDump() + .setProperties(entry); const transformedTree = transformer.transform(); - expect(transformedTree).toEqual(expected); }); it("creates properties tree with show diff enabled, comparing to a null previous entry", () => { - const selectedTree = { - id: "3", - name: "Child1", - stackId: 0, - isVisible: true, - kind: "3", - stableId: "3 Child1", - shortName: undefined, - simplifyNames: true, - showInFilteredView: true, - skip: null, - proto: { - barrierLayer: [], - id: 3, - parent: 1, - type: "ContainerLayer", - }, - chips: [], - children: [{ - id: "2", - name: "Child2", - stackId: 0, - children: [], - kind: "2", - stableId: "2 Child2", - shortName: undefined, - simplifyNames: true, - proto: { - barrierLayer: [], - id: 2, - parent: 3, - type: "ContainerLayer", - }, - isVisible: true, - showInFilteredView: true, - chips: [], - }], - }; const expected = { kind: "", name: "Child1", @@ -152,34 +121,24 @@ describe("TreeTransformer", () => { children: [ { kind: "", - name: "proto", - stableId: "3 Child1.proto", - children: [ - { - kind: "", - name: "id: empty", - stableId: "3 Child1.proto.id", - children: [], - combined: true, - diffType: DiffType.ADDED, - propertyKey: "id", - propertyValue: "empty", - }, - { - kind: "", - name: "type: ContainerLayer", - stableId: "3 Child1.proto.type", - children: [], - combined: true, - diffType: DiffType.ADDED, - propertyKey: "type", - propertyValue: "ContainerLayer", - } - ], + name: "id: empty", diffType: DiffType.ADDED, - propertyKey: "proto", - propertyValue: null, - } + stableId: "3 Child1.id", + children: [], + combined: true, + propertyKey: "id", + propertyValue: "empty" + }, + { + kind: "", + name: "type: ContainerLayer", + diffType: DiffType.ADDED, + stableId: "3 Child1.type", + children: [], + combined: true, + propertyKey: "type", + propertyValue: "ContainerLayer" + }, ], diffType: DiffType.NONE, propertyKey: "Child1", @@ -189,6 +148,8 @@ describe("TreeTransformer", () => { const filter = getFilter(""); const transformer = new TreeTransformer(selectedTree, filter) .setIsShowDiff(true) + .showOnlyProtoDump() + .setProperties(entry) .setDiffProperties(null); const transformedTree = transformer.transform(); diff --git a/tools/winscope-ng/src/viewers/common/tree_transformer.ts b/tools/winscope-ng/src/viewers/common/tree_transformer.ts index fb8698c8d..9592e3541 100644 --- a/tools/winscope-ng/src/viewers/common/tree_transformer.ts +++ b/tools/winscope-ng/src/viewers/common/tree_transformer.ts @@ -18,9 +18,11 @@ import ObjectFormatter from "common/trace/flickerlib/ObjectFormatter"; import { FilterType, PropertiesTree, - Tree, DiffType, - Terminal + Terminal, + TreeFlickerItem, + HierarchyTree, + PropertiesDump } from "./tree_utils"; interface TransformOptions { @@ -32,10 +34,6 @@ interface TreeTransformerOptions { skip?: any; formatter?: any; } -interface TransformedPropertiesObject { - properties: any; - diffType?: string; -} export class TreeTransformer { private stableId: string; @@ -43,32 +41,37 @@ export class TreeTransformer { private isShowDefaults = false; private isShowDiff = false; private filter: FilterType; - private properties: PropertiesTree; - private compareWithProperties: PropertiesTree | null = null; + private properties: PropertiesDump | Terminal | null = null; + private compareWithProperties: PropertiesDump | Terminal | null = null; private options?: TreeTransformerOptions; + private onlyProtoDump = false; private transformOptions: TransformOptions = { keepOriginal: false, freeze: true, metadataKey: null, }; - constructor(tree: Tree, filter: FilterType) { - this.stableId = this.compatibleStableId(tree); - this.rootName = tree.name; + constructor(selectedTree: HierarchyTree, filter: FilterType) { + this.stableId = this.compatibleStableId(selectedTree); + this.rootName = selectedTree.name; this.filter = filter; - this.setProperties(tree); this.setTransformerOptions({}); } - public setIsShowDefaults(enabled: boolean) { + public showOnlyProtoDump(): TreeTransformer { + this.onlyProtoDump = true; + return this; + } + + public setIsShowDefaults(enabled: boolean): TreeTransformer { this.isShowDefaults = enabled; return this; } - public setIsShowDiff(enabled: boolean) { + public setIsShowDiff(enabled: boolean): TreeTransformer { this.isShowDiff = enabled; return this; } - public setTransformerOptions(options: TreeTransformerOptions) { + public setTransformerOptions(options: TreeTransformerOptions): TreeTransformer { this.options = options; if (!this.options.formatter) { this.options.formatter = this.formatProto; @@ -76,66 +79,97 @@ export class TreeTransformer { return this; } - public setProperties(tree: Tree) { - const target = tree.obj ?? tree; + public setProperties(currentEntry: TreeFlickerItem): TreeTransformer { + const currFlickerItem = this.getOriginalFlickerItem(currentEntry, this.stableId); + const target = currFlickerItem ? currFlickerItem.obj ?? currFlickerItem : null; ObjectFormatter.displayDefaults = this.isShowDefaults; - this.properties = this.getPropertiesForDisplay(target); + this.properties = this.onlyProtoDump ? this.getProtoDumpPropertiesForDisplay(target) : this.getPropertiesForDisplay(target); + return this; } - public setDiffProperties(previousEntry: any) { + public setDiffProperties(previousEntry: TreeFlickerItem | null): TreeTransformer { if (this.isShowDiff) { - const tree = this.findTree(previousEntry, this.stableId); - const target = tree ? tree.obj ?? tree : null; - this.compareWithProperties = this.getPropertiesForDisplay(target); + const prevFlickerItem = this.findFlickerItem(previousEntry, this.stableId); + const target = prevFlickerItem ? prevFlickerItem.obj ?? prevFlickerItem : null; + this.compareWithProperties = this.onlyProtoDump ? this.getProtoDumpPropertiesForDisplay(target) : this.getPropertiesForDisplay(target); } return this; } - public getOriginalLayer(entry: any, stableId: string) { - return this.findTree(entry, stableId); + public getOriginalFlickerItem(entry: TreeFlickerItem, stableId: string): TreeFlickerItem | null { + return this.findFlickerItem(entry, stableId); } - private getPropertiesForDisplay(entry: any): any { + private getProtoDumpPropertiesForDisplay(entry: TreeFlickerItem): PropertiesDump | null { if (!entry) { - return; + return null; } - let obj: any = {}; - obj.proto = Object.assign({}, entry.proto); - if (obj.proto.children) delete obj.proto.children; - if (obj.proto.childWindows) delete obj.proto.childWindows; - if (obj.proto.childrenWindows) delete obj.proto.childrenWindows; - if (obj.proto.childContainers) delete obj.proto.childContainers; - if (obj.proto.windowToken) delete obj.proto.windowToken; - if (obj.proto.rootDisplayArea) delete obj.proto.rootDisplayArea; - if (obj.proto.rootWindowContainer) delete obj.proto.rootWindowContainer; - if (obj.proto.windowContainer?.children) delete obj.proto.windowContainer.children; + const obj: PropertiesDump = {}; + const proto = ObjectFormatter.format(entry.proto); + if (proto) { + Object.keys(proto).forEach((prop: string) => { + obj[prop] = proto[prop] ?? "empty"; - obj = ObjectFormatter.format(obj); + if (Object.keys(obj[prop]).length === 0) { + obj[prop]= "empty"; + } + }); + } - Object.keys(obj.proto).forEach((prop: string) => { - if (Object.keys(obj.proto[prop]).length === 0) { - obj.proto[prop] = "empty"; - } - }); return obj; } - private findTree(tree: any, stableId: string) { - if (!tree) { + private getPropertiesForDisplay(entry: TreeFlickerItem): PropertiesDump | null { + if (!entry) { return null; } - if (tree.stableId && tree.stableId === stableId) { - return tree; - } + let obj: PropertiesDump = {}; - if (!tree.children) { + const properties = ObjectFormatter.getProperties(entry); + properties.forEach(prop => { + if (entry.get) obj[prop] = entry.get(prop); + }); + if (obj["children"]) delete obj["children"]; + if (obj["proto"]) delete obj["proto"]; + + obj["proto"] = Object.assign({}, entry.proto); + if (obj["proto"].children) delete obj["proto"].children; + if (obj["proto"].childWindows) delete obj["proto"].childWindows; + if (obj["proto"].childrenWindows) delete obj["proto"].childrenWindows; + if (obj["proto"].childContainers) delete obj["proto"].childContainers; + if (obj["proto"].windowToken) delete obj["proto"].windowToken; + if (obj["proto"].rootDisplayArea) delete obj["proto"].rootDisplayArea; + if (obj["proto"].rootWindowContainer) delete obj["proto"].rootWindowContainer; + if (obj["proto"].windowContainer?.children) delete obj["proto"].windowContainer.children; + + obj = ObjectFormatter.format(obj); + + Object.keys(obj["proto"]).forEach((prop: string) => { + if (Object.keys(obj["proto"][prop]).length === 0) { + obj["proto"][prop] = "empty"; + } + }); + + return obj; + } + + private findFlickerItem(entryFlickerItem: TreeFlickerItem | null, stableId: string): TreeFlickerItem | null { + if (!entryFlickerItem) { return null; } - for (const child of tree.children) { - const foundEntry: any = this.findTree(child, stableId); + if (entryFlickerItem.stableId && entryFlickerItem.stableId === stableId) { + return entryFlickerItem; + } + + if (!entryFlickerItem.children) { + return null; + } + + for (const child of entryFlickerItem.children) { + const foundEntry: any = this.findFlickerItem(child, stableId); if (foundEntry) { return foundEntry; } @@ -145,7 +179,7 @@ export class TreeTransformer { } - public transform() { + public transform(): PropertiesTree { const {formatter} = this.options!; if (!formatter) { throw new Error("Missing formatter, please set with setOptions()"); @@ -154,18 +188,17 @@ export class TreeTransformer { const transformedTree = this.transformTree(this.properties, this.rootName, this.compareWithProperties, this.rootName, this.stableId, this.transformOptions); - return transformedTree; } private transformTree( - properties: PropertiesTree | Terminal, + properties: PropertiesDump | null | Terminal, name: string | Terminal, - compareWithProperties: PropertiesTree | Terminal, + compareWithProperties: PropertiesDump | null | Terminal, compareWithName: string | Terminal, stableId: string, transformOptions: TransformOptions, - ) { + ): PropertiesTree { const originalProperties = properties; const metadata = this.getMetadata( originalProperties, transformOptions.metadataKey @@ -173,12 +206,12 @@ export class TreeTransformer { const children: any[] = []; - if (!this.isTerminal(properties)) { + if (properties && !this.isTerminal(properties)) { const transformedProperties = this.transformProperties(properties, transformOptions.metadataKey); properties = transformedProperties.properties; } - if (!this.isTerminal(compareWithProperties)) { + if (compareWithProperties && !this.isTerminal(compareWithProperties)) { const transformedProperties = this.transformProperties( compareWithProperties, transformOptions.metadataKey @@ -187,10 +220,10 @@ export class TreeTransformer { } for (const key in properties) { - if (properties[key]) { + if (!(properties instanceof Terminal) && properties[key]) { let compareWithChild = new Terminal(); let compareWithChildName = new Terminal(); - if (compareWithProperties[key]) { + if (compareWithProperties && !(compareWithProperties instanceof Terminal) && compareWithProperties[key]) { compareWithChild = compareWithProperties[key]; compareWithChildName = key; } @@ -204,7 +237,8 @@ export class TreeTransformer { // Takes care of adding deleted items to final tree for (const key in compareWithProperties) { - if (!properties[key] && compareWithProperties[key]) { + if (properties && !(properties instanceof Terminal) && !properties[key] && + !(compareWithProperties instanceof Terminal) && compareWithProperties[key]) { const child = this.transformTree(new Terminal(), new Terminal(), compareWithProperties[key], key, `${stableId}.${key}`, transformOptions); @@ -268,11 +302,10 @@ export class TreeTransformer { !this.hasChildMatchingFilter(transformedProperties?.children)) { transformedProperties.propertyKey = new Terminal(); } - return transformOptions.freeze ? Object.freeze(transformedProperties) : transformedProperties; } - private hasChildMatchingFilter(children: PropertiesTree[] | null | undefined) { + private hasChildMatchingFilter(children: PropertiesTree[] | null | undefined): boolean { if (!children || children.length === 0) return false; let match = false; @@ -285,8 +318,11 @@ export class TreeTransformer { return match; } - private getMetadata(obj: PropertiesTree, metadataKey: string | null) { - if (metadataKey && obj[metadataKey]) { + private getMetadata(obj: PropertiesDump | null | Terminal, metadataKey: string | null): any { + if (obj == null) { + return null; + } + if (metadataKey && !(obj instanceof Terminal) && obj[metadataKey]) { const metadata = obj[metadataKey]; obj[metadataKey] = undefined; return metadata; @@ -295,28 +331,28 @@ export class TreeTransformer { } } - private getPropertyKey(item: PropertiesTree) { - if (!item.children || item.children.length === 0) { - return item.name.split(": ")[0]; + private getPropertyKey(item: PropertiesDump): string { + if (item["name"] && (!item["children"] || item["children"].length === 0)) { + return item["name"].split(": ")[0]; } - return item.name; + return item["name"]; } - private getPropertyValue(item: PropertiesTree) { - if (!item.children || item.children.length === 0) { - return item.name.split(": ").slice(1).join(": "); + private getPropertyValue(item: PropertiesDump): string | null { + if (item["name"] && (!item["children"] || item["children"].length === 0)) { + return item["name"].split(": ").slice(1).join(": "); } return null; } - private filterMatches(item: PropertiesTree | null): boolean { + private filterMatches(item: PropertiesDump | null): boolean { return this.filter(item) ?? false; } - private transformProperties(properties: PropertiesTree, metadataKey: string | null) { + private transformProperties(properties: PropertiesDump, metadataKey: string | null): PropertiesTree { const {skip, formatter} = this.options!; - const transformedProperties: TransformedPropertiesObject = { + const transformedProperties: PropertiesTree = { properties: {}, }; let formatted = undefined; @@ -351,7 +387,7 @@ export class TreeTransformer { return transformedProperties; } - private getDiff(val: string | Terminal, compareVal: string | Terminal) { + private getDiff(val: string | Terminal, compareVal: string | Terminal): string { if (val && this.isTerminal(compareVal)) { return DiffType.ADDED; } else if (this.isTerminal(val) && compareVal) { @@ -363,7 +399,7 @@ export class TreeTransformer { } } - private compatibleStableId(item: Tree) { + private compatibleStableId(item: HierarchyTree): string { // For backwards compatibility // (the only item that doesn't have a unique stable ID in the tree) if (item.stableId === "winToken|-|") { @@ -378,7 +414,7 @@ export class TreeTransformer { } } - private isTerminal(item: any) { + private isTerminal(item: any): boolean { return item instanceof Terminal; } } diff --git a/tools/winscope-ng/src/viewers/common/tree_utils.ts b/tools/winscope-ng/src/viewers/common/tree_utils.ts index f19a41d1e..9528c249e 100644 --- a/tools/winscope-ng/src/viewers/common/tree_utils.ts +++ b/tools/winscope-ng/src/viewers/common/tree_utils.ts @@ -13,12 +13,87 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Layer, BaseLayerTraceEntry } from "common/trace/flickerlib/common"; -export type FilterType = (item: Tree | null) => boolean; -export type Tree = Layer | BaseLayerTraceEntry; -export type PropertiesTree = any; //TODO: make specific -export type TreeSummary = Array<{key: string, value: string}> +import Chip from "./chip"; + +export type FilterType = (item: HierarchyTree | PropertiesTree | null) => boolean; + +export type Tree = HierarchyTree | PropertiesTree; + +export class HierarchyTree { + constructor( + public name: string, + public kind: string, + public stableId: string, + children?: HierarchyTree[] + ) { + this.children = children ?? []; + } + + children: HierarchyTree[]; + shortName?: string; + type?: string; + id?: string | number; + layerId?: number; + displayId?: number; + stackId?: number; + isVisible?: boolean; + isMissing?: boolean; + hwcCompositionType?: number; + zOrderRelativeOfId?: number; + zOrderRelativeOf?: any; + zOrderRelativeParentOf?: any; + isRootLayer?: boolean; + showInFilteredView?: boolean; + showInOnlyVisibleView?: boolean; + simplifyNames?: boolean; + chips?: Chip[] = []; + diffType?: string; + 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 { + properties?: any; + kind?: string; + stableId?: string; + children?: PropertiesTree[]; + propertyKey?: string | Terminal | null; + propertyValue?: string | Terminal | null; + name?: string | Terminal; + diffType?: string; + combined?: boolean; +} //TODO: make specific export const DiffType = { NONE: "none", @@ -32,18 +107,18 @@ export const DiffType = { export class Terminal {} export function diffClass(item: Tree): string { - const diffType = item!.diffType; + const diffType = item.diffType; return diffType ?? ""; } export function isHighlighted(item: Tree, highlightedItems: Array) { - return highlightedItems.includes(`${item.id}`); + return item instanceof HierarchyTree && highlightedItems.includes(`${item.id}`); } export function getFilter(filterString: string): FilterType { const filterStrings = filterString.split(","); - const positive: Tree | null[] = []; - const negative: Tree | null[] = []; + const positive: any[] = []; + const negative: any[] = []; filterStrings.forEach((f) => { f = f.trim(); if (f.startsWith("!")) { diff --git a/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts b/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts index aae6c5dc7..face16397 100644 --- a/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/hierarchy.component.spec.ts @@ -22,6 +22,8 @@ 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 { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; describe("HierarchyComponent", () => { let fixture: ComponentFixture; @@ -51,14 +53,11 @@ describe("HierarchyComponent", () => { fixture = TestBed.createComponent(HierarchyComponent); component = fixture.componentInstance; htmlElement = fixture.nativeElement; - component.tree = { - simplifyNames: false, - kind: "entry", - name: "BaseLayerTraceEntry", - shortName: "BLTE", - chips: [], - children: [{kind: "3", id: "3", name: "Child1"}] - }; + + component.tree = new HierarchyTreeBuilder().setName("BaseLayerTraceEntry").setKind("entry").setStableId("BaseEntry") + .setChildren([new HierarchyTreeBuilder().setName("Child1").setStableId("3 Child1").build()]) + .build(); + component.store = new PersistentStore(); component.userOptions = { onlyVisible: { @@ -66,14 +65,7 @@ describe("HierarchyComponent", () => { enabled: false }, }; - component.pinnedItems = [{ - simplifyNames: false, - kind: "entry", - name: "BaseLayerTraceEntry", - shortName: "BLTE", - chips: [], - children: [{kind: "3", id: "3", name: "Child1"}] - }]; + component.pinnedItems = [component.tree]; component.diffClass = jasmine.createSpy().and.returnValue("none"); }); diff --git a/tools/winscope-ng/src/viewers/components/hierarchy.component.ts b/tools/winscope-ng/src/viewers/components/hierarchy.component.ts index b6195d0c9..6ee155bd0 100644 --- a/tools/winscope-ng/src/viewers/components/hierarchy.component.ts +++ b/tools/winscope-ng/src/viewers/components/hierarchy.component.ts @@ -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 { Tree, diffClass, isHighlighted } from "viewers/common/tree_utils"; +import { HierarchyTree, diffClass, isHighlighted, Tree } 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"; @@ -56,7 +56,7 @@ import { TraceType } from "common/trace/trace_type"; [isPinned]="true" [isInPinnedSection]="true" (pinNodeChange)="pinnedItemChange($event)" - (click)="onPinnedNodeClick($event, pinnedItem.id, pinnedItem)" + (click)="onPinnedNodeClick($event, pinnedItem)" > @@ -150,10 +150,10 @@ export class HierarchyComponent { diffClass = diffClass; isHighlighted = isHighlighted; - @Input() tree!: Tree | null; + @Input() tree!: HierarchyTree | null; @Input() dependencies: Array = []; @Input() highlightedItems: Array = []; - @Input() pinnedItems: Array = []; + @Input() pinnedItems: Array = []; @Input() store!: PersistentStore; @Input() userOptions: UserOptions = {}; @@ -172,12 +172,12 @@ export class HierarchyComponent { }; } - public onPinnedNodeClick(event: MouseEvent, pinnedItemId: string, pinnedItem: Tree) { + public onPinnedNodeClick(event: MouseEvent, pinnedItem: HierarchyTree) { event.preventDefault(); if (window.getSelection()?.type === "range") { return; } - this.highlightedItemChange(`${pinnedItemId}`); + if (pinnedItem.id) this.highlightedItemChange(`${pinnedItem.id}`); this.selectedTreeChange(pinnedItem); } @@ -212,6 +212,9 @@ export class HierarchyComponent { } public selectedTreeChange(item: Tree) { + if (!(item instanceof HierarchyTree)) { + return; + } const event: CustomEvent = new CustomEvent( ViewerEvents.SelectedTreeChange, { @@ -222,6 +225,9 @@ export class HierarchyComponent { } public pinnedItemChange(item: Tree) { + if (!(item instanceof HierarchyTree)) { + return; + } const event: CustomEvent = new CustomEvent( ViewerEvents.HierarchyPinnedChange, { diff --git a/tools/winscope-ng/src/viewers/components/properties.component.spec.ts b/tools/winscope-ng/src/viewers/components/properties.component.spec.ts index 7c86cf197..9ed4a89ff 100644 --- a/tools/winscope-ng/src/viewers/components/properties.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/properties.component.spec.ts @@ -54,9 +54,8 @@ describe("PropertiesComponent", () => { fixture = TestBed.createComponent(PropertiesComponent); component = fixture.componentInstance; htmlElement = fixture.nativeElement; - component.selectedTree = {}; - component.selectedLayer = {}; - component.summary = []; + component.propertiesTree = {}; + component.selectedFlickerItem = null; component.userOptions = { showDefaults: { name: "Show defaults", diff --git a/tools/winscope-ng/src/viewers/components/properties.component.ts b/tools/winscope-ng/src/viewers/components/properties.component.ts index 4d9866647..68fdddd60 100644 --- a/tools/winscope-ng/src/viewers/components/properties.component.ts +++ b/tools/winscope-ng/src/viewers/components/properties.component.ts @@ -16,8 +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, TreeSummary, Terminal } from "viewers/common/tree_utils"; -import { Layer } from "common/trace/flickerlib/common"; +import { PropertiesTree, Terminal, TreeFlickerItem } from "viewers/common/tree_utils"; @Component({ selector: "properties-view", @@ -44,22 +43,21 @@ import { Layer } from "common/trace/flickerlib/common"; [matTooltip]="userOptions[option].tooltip ?? ''" >{{userOptions[option].name}} -
+
+ Properties - Proto Dump
@@ -136,10 +134,9 @@ export class PropertiesComponent { filterString = ""; @Input() userOptions: UserOptions = {}; - @Input() selectedTree: PropertiesTree = {}; - @Input() selectedLayer: Layer = {}; + @Input() propertiesTree: PropertiesTree = {}; + @Input() selectedFlickerItem: TreeFlickerItem | null = null; @Input() propertyGroups = false; - @Input() summary?: TreeSummary = []; constructor( @Inject(ElementRef) private elementRef: ElementRef, @@ -182,4 +179,8 @@ export class PropertiesComponent { return !item.children || item.children.length === 0 || item.children.filter((c: any) => !(c instanceof Terminal)).length === 0; } + + public itemIsSelected() { + return this.selectedFlickerItem && Object.keys(this.selectedFlickerItem).length > 0; + } } diff --git a/tools/winscope-ng/src/viewers/components/property_groups.component.ts b/tools/winscope-ng/src/viewers/components/property_groups.component.ts index fcec7d76b..bf462a410 100644 --- a/tools/winscope-ng/src/viewers/components/property_groups.component.ts +++ b/tools/winscope-ng/src/viewers/components/property_groups.component.ts @@ -14,13 +14,28 @@ * limitations under the License. */ import { Component, Input } from "@angular/core"; -import { TreeSummary } from "viewers/common/tree_utils"; import { Layer } from "common/trace/flickerlib/common"; @Component({ selector: "property-groups", template: `
+
+ + Visibility + +
+ Flags: + {{ item.flags }} +
+
+
+ {{ reason.key }}: + {{ reason.value }} +
+
+
+
Geometry
@@ -76,24 +91,24 @@ import { Layer } from "common/trace/flickerlib/common"; Destination Frame: {{ getDestinationFrame() }}
Destination Frame ignored because layer has eIgnoreDestinationFrame + >Destination Frame ignored because item has eIgnoreDestinationFrame flag set.
- Container layer + Container item
- Effect layer + Effect item
@@ -107,7 +122,7 @@ import { Layer } from "common/trace/flickerlib/common";
relative parent: @@ -133,7 +148,7 @@ import { Layer } from "common/trace/flickerlib/common"; Corner Radius Crop: {{ item.cornerRadiusCrop }} @@ -175,21 +190,21 @@ import { Layer } from "common/trace/flickerlib/common"; Input -
+
To Display Transform:
Touchable Region: {{ item.inputRegion }}
-
+
Config:
Focusable: {{ item.proto?.inputWindowInfo.focusable }}
- Crop touch region with layer: + Crop touch region with item: {{ item.proto?.inputWindowInfo.cropLayerId <= 0 @@ -205,28 +220,11 @@ import { Layer } from "common/trace/flickerlib/common"; }}
-
+
No input channel set
- -
- - Visibility - -
- Flags: - {{ item.flags }} -
-
-
- {{ reason.key }}: - {{ reason.value }} -
-
-
-
`, styles: [ @@ -285,7 +283,10 @@ import { Layer } from "common/trace/flickerlib/common"; export class PropertyGroupsComponent { @Input() item!: Layer; - @Input() summary?: TreeSummary | null = null; + + public hasInputChannel() { + return this.item.proto?.inputWindowInfo; + } public getDestinationFrame() { const frame = this.item.proto?.destinationFrame; @@ -302,4 +303,41 @@ export class PropertyGroupsComponent { public formatFloat(num: number) { return Math.round(num * 100) / 100; } + + + public summary(): TreeSummary { + const summary = []; + + if (this.item?.visibilityReason?.length > 0) { + let reason = ""; + if (Array.isArray(this.item.visibilityReason)) { + reason = this.item.visibilityReason.join(", "); + } else { + reason = this.item.visibilityReason; + } + + summary.push({key: "Invisible due to", value: reason}); + } + + if (this.item?.occludedBy?.length > 0) { + summary.push({key: "Occluded by", value: this.item.occludedBy.map((it: any) => it.id).join(", ")}); + } + + if (this.item?.partiallyOccludedBy?.length > 0) { + summary.push({ + key: "Partially occluded by", + value: this.item.partiallyOccludedBy.map((it: any) => it.id).join(", "), + }); + } + + if (this.item?.coveredBy?.length > 0) { + summary.push({key: "Covered by", value: this.item.coveredBy.map((it: any) => it.id).join(", ")}); + } + + return summary; + } + } + + +type TreeSummary = Array<{key: string, value: string}> \ No newline at end of file diff --git a/tools/winscope-ng/src/viewers/components/rects/canvas_graphics.ts b/tools/winscope-ng/src/viewers/components/rects/canvas_graphics.ts index ab4bd54c6..e777da493 100644 --- a/tools/winscope-ng/src/viewers/components/rects/canvas_graphics.ts +++ b/tools/winscope-ng/src/viewers/components/rects/canvas_graphics.ts @@ -23,11 +23,11 @@ export class CanvasGraphics { constructor() { //set up camera const left = -this.CAMERA_HALF_WIDTH, - right = this.CAMERA_HALF_WIDTH, - top = this.CAMERA_HALF_HEIGHT, - bottom = -this.CAMERA_HALF_HEIGHT, - near = 0.001, - far = 100; + right = this.CAMERA_HALF_WIDTH, + top = this.CAMERA_HALF_HEIGHT, + bottom = -this.CAMERA_HALF_HEIGHT, + near = 0.001, + far = 100; this.camera = new THREE.OrthographicCamera( left, right, top, bottom, near, far ); diff --git a/tools/winscope-ng/src/viewers/components/tree.component.ts b/tools/winscope-ng/src/viewers/components/tree.component.ts index 1430a53d4..b0941e906 100644 --- a/tools/winscope-ng/src/viewers/components/tree.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree.component.ts @@ -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 } from "viewers/common/tree_utils"; +import { Tree, diffClass, isHighlighted, PropertiesTree, Terminal, isParentNode, HierarchyTree } from "viewers/common/tree_utils"; import { TraceType } from "common/trace/trace_type"; @Component({ @@ -39,7 +39,6 @@ import { TraceType } from "common/trace/trace_type"; [flattened]="isFlattened" [isLeaf]="isLeaf(this.item)" [isCollapsed]="isAlwaysCollapsed ?? isCollapsed()" - [isPropertiesTreeNode]="isPropertiesTree" [hasChildren]="hasChildren()" [isPinned]="isPinned()" (toggleTreeChange)="toggleTree()" @@ -58,7 +57,6 @@ import { TraceType } from "common/trace/trace_type"; [isLeaf]="isLeaf" [dependencies]="dependencies" [isFlattened]="isFlattened" - [isPropertiesTree]="isPropertiesTree" [isShaded]="!isShaded" [useGlobalCollapsedState]="useGlobalCollapsedState" [initialDepth]="initialDepth + 1" @@ -82,17 +80,16 @@ export class TreeComponent { diffClass = diffClass; isHighlighted = isHighlighted; - @Input() item!: Tree | PropertiesTree | Terminal; + @Input() item!: Tree; @Input() dependencies: Array = []; @Input() store!: PersistentStore; @Input() isFlattened? = false; @Input() isShaded? = false; @Input() initialDepth = 0; @Input() highlightedItems: Array = []; - @Input() pinnedItems?: Array = []; + @Input() pinnedItems?: Array = []; @Input() itemsClickable?: boolean; @Input() useGlobalCollapsedState?: boolean; - @Input() isPropertiesTree?: boolean; @Input() isAlwaysCollapsed?: boolean; @Input() showNode: (item?: any) => boolean = () => true; @Input() isLeaf: (item: any) => boolean = (item: any) => !item.children || item.children.length === 0; @@ -126,7 +123,7 @@ export class TreeComponent { } ngOnChanges() { - if (isHighlighted(this.item, this.highlightedItems)) { + if (this.item instanceof HierarchyTree && isHighlighted(this.item, this.highlightedItems)) { this.selectedTreeChange.emit(this.item); } } @@ -162,16 +159,18 @@ export class TreeComponent { } private updateHighlightedItems() { - if (this.item && this.item.id) { - this.highlightedItemChange.emit(`${this.item.id}`); - } else if (!this.item.id) { - this.selectedTreeChange.emit(this.item); + if (this.item instanceof HierarchyTree) { + if (this.item && this.item.id) { + this.highlightedItemChange.emit(`${this.item.id}`); + } else if (!this.item.id) { + this.selectedTreeChange.emit(this.item); + } } } public isPinned() { - if (this.item) { - return this.pinnedItems?.map((item: Tree) => `${item.id}`).includes(`${this.item.id}`); + if (this.item instanceof HierarchyTree) { + return this.pinnedItems?.map(item => `${item.id}`).includes(`${this.item.id}`); } return false; } @@ -206,18 +205,18 @@ export class TreeComponent { } if (this.useGlobalCollapsedState) { - return this.store.getFromStore(`collapsedState.item.${this.dependencies}.${this.item.id}`)==="true" + return this.store.getFromStore(`collapsedState.item.${this.dependencies}.${this.item.stableId}`)==="true" ?? this.isCollapsedByDefault; } return this.localCollapsedState; } - public children() { - return this.item.children; + public children(): Tree[] { + return this.item.children ?? []; } public hasChildren() { - const isParentEntryInFlatView = isParentNode(this.item.kind) && this.isFlattened; + const isParentEntryInFlatView = isParentNode(this.item.kind ?? "") && this.isFlattened; return (!this.isFlattened || isParentEntryInFlatView) && !this.isLeaf(this.item); } @@ -241,7 +240,7 @@ export class TreeComponent { private setCollapseValue(isCollapsed: boolean) { if (this.useGlobalCollapsedState) { - this.store.addToStore(`collapsedState.item.${this.dependencies}.${this.item.id}`, `${isCollapsed}`); + this.store.addToStore(`collapsedState.item.${this.dependencies}.${this.item.stableId}`, `${isCollapsed}`); } else { this.localCollapsedState = isCollapsed; } diff --git a/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts b/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts index b76035a90..035319abf 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node.component.spec.ts @@ -54,7 +54,6 @@ describe("TreeNodeComponent", () => { [isPinned]="false" [isInPinnedSection]="false" [hasChildren]="false" - [isPropertiesTreeNode]="false" > ` }) diff --git a/tools/winscope-ng/src/viewers/components/tree_node.component.ts b/tools/winscope-ng/src/viewers/components/tree_node.component.ts index d8e48173b..fee32e573 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node.component.ts @@ -15,7 +15,7 @@ */ import { Component, Input, Output, EventEmitter } from "@angular/core"; import { nodeInnerItemStyles } from "viewers/components/styles/node.styles"; -import { PropertiesTree, Tree, DiffType, isParentNode } from "viewers/common/tree_utils"; +import { Tree, DiffType, isParentNode, HierarchyTree } from "viewers/common/tree_utils"; @Component({ selector: "tree-node", @@ -50,11 +50,11 @@ import { PropertiesTree, Tree, DiffType, isParentNode } from "viewers/common/tre
@@ -76,14 +76,13 @@ import { PropertiesTree, Tree, DiffType, isParentNode } from "viewers/common/tre }) export class TreeNodeComponent { - @Input() item!: Tree | PropertiesTree; + @Input() item!: Tree; @Input() isLeaf?: boolean; @Input() flattened?: boolean; @Input() isCollapsed?: boolean; @Input() hasChildren?: boolean = false; @Input() isPinned?: boolean = false; @Input() isInPinnedSection?: boolean = false; - @Input() isPropertiesTreeNode?: boolean; @Input() isAlwaysCollapsed?: boolean; @Output() toggleTreeChange = new EventEmitter(); @@ -96,8 +95,12 @@ export class TreeNodeComponent { this.collapseDiffClass = this.updateCollapseDiffClass(); } + public isPropertiesTreeNode() { + return !(this.item instanceof HierarchyTree); + } + public showPinNodeIcon() { - return (!this.isPropertiesTreeNode && !isParentNode(this.item.kind)) ?? false; + return (!this.isPropertiesTreeNode() && !isParentNode(this.item.kind ?? "")) ?? false; } public toggleTree(event: MouseEvent) { @@ -145,7 +148,7 @@ export class TreeNodeComponent { return DiffType.MODIFIED; } - private getAllDiffTypesOfChildren(item: Tree | PropertiesTree) { + private getAllDiffTypesOfChildren(item: Tree) { if (!item.children) { return new Set(); } diff --git a/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts b/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts index 4cd513f08..5ec6f929b 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node_data_view.component.ts @@ -15,7 +15,7 @@ */ import { Component, Input } from "@angular/core"; import { treeNodeDataViewStyles } from "viewers/components/styles/tree_node_data_view.styles"; -import { Tree } from "viewers/common/tree_utils"; +import { Terminal, HierarchyTree, Tree } from "viewers/common/tree_utils"; import Chip from "viewers/common/chip"; @Component({ @@ -24,10 +24,10 @@ import Chip from "viewers/common/chip"; {{item.kind}} - - {{ item.shortName }} + {{ itemShortName() }} {{item.name}}
{{chip.short}}
@@ -39,8 +39,23 @@ import Chip from "viewers/common/chip"; export class TreeNodeDataViewComponent { @Input() item!: Tree; + public chips() { + return (this.item instanceof HierarchyTree) ? this.item.chips : []; + } + + public itemShortName() { + return (this.item instanceof HierarchyTree)? this.item.shortName : ""; + } + + public itemTooltip() { + if (this.item.name instanceof Terminal) { + return ""; + } + return this.item.name ?? ""; + } + public showShortName() { - return this.item.simplifyNames && this.item.shortName !== this.item.name; + return (this.item instanceof HierarchyTree) && this.item.simplifyNames && this.item.shortName !== this.item.name; } public chipClass(chip: Chip) { diff --git a/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts b/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts index 07a4392ee..0867981b4 100644 --- a/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts +++ b/tools/winscope-ng/src/viewers/components/tree_node_properties_data_view.component.ts @@ -49,7 +49,7 @@ export class TreeNodePropertiesDataViewComponent { return "false"; } - if (!isNaN(this.item.propertyValue)) { + if (!isNaN(Number(this.item.propertyValue))) { return "number"; } return null; diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts index a1359800d..cbbc52712 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.spec.ts @@ -17,57 +17,25 @@ import { Presenter } from "./presenter"; import { UiData } from "./ui_data"; import { UserOptions } from "viewers/common/user_options"; import { TraceType } from "common/trace/trace_type"; -import { RELATIVE_Z_CHIP, VISIBLE_CHIP } from "viewers/common/chip"; import { LayerTraceEntry } from "common/trace/flickerlib/common"; -import { DiffType, PropertiesTree, Terminal, Tree } from "viewers/common/tree_utils"; +import { HierarchyTree, PropertiesTree } from "viewers/common/tree_utils"; import { UnitTestUtils } from "test/unit/utils"; +import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder"; describe("PresenterSurfaceFlinger", () => { let presenter: Presenter; let uiData: UiData; let entries: Map; - let selectedItem: Tree; + let selectedTree: HierarchyTree; beforeAll(async () => { entries = new Map(); const entry: LayerTraceEntry = await UnitTestUtils.getLayerTraceEntry(); - selectedItem = { - id: "3", - name: "Child1", - stackId: 0, - isVisible: true, - kind: "3", - stableId: "3 Child1", - shortName: undefined, - simplifyNames: true, - showInFilteredView: true, - proto: { - barrierLayer: [], - id: 3, - parent: 1, - type: "ContainerLayer", - }, - chips: [ VISIBLE_CHIP, RELATIVE_Z_CHIP ], - children: [{ - id: "2", - name: "Child2", - stackId: 0, - children: [], - kind: "2", - stableId: "2 Child2", - shortName: undefined, - simplifyNames: true, - proto: { - barrierLayer: [], - id: 2, - parent: 3, - type: "ContainerLayer", - }, - isVisible: true, - showInFilteredView: true, - chips: [ VISIBLE_CHIP, RELATIVE_Z_CHIP ], - }], - }; + + + selectedTree = new HierarchyTreeBuilder().setName("Dim layer#53").setStableId("EffectLayer 53 Dim layer#53") + .setFilteredView(true).setKind("53").setDiffType("EffectLayer").setId(53).build(); + entries.set(TraceType.SURFACE_FLINGER, [entry, null]); }); @@ -92,12 +60,12 @@ describe("PresenterSurfaceFlinger", () => { expect(propertyOpts).toBeTruthy(); // does not check specific tree values as tree generation method may change - expect(Object.keys(uiData.tree).length > 0).toBeTrue(); + expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); it("can handle unavailable trace entry", () => { presenter.notifyCurrentTraceEntries(entries); - expect(Object.keys(uiData.tree).length > 0).toBeTrue(); + expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); const emptyEntries = new Map(); presenter.notifyCurrentTraceEntries(emptyEntries); expect(uiData.tree).toBeFalsy(); @@ -105,13 +73,8 @@ describe("PresenterSurfaceFlinger", () => { it("can update pinned items", () => { expect(uiData.pinnedItems).toEqual([]); - const pinnedItem = { - name: "FirstPinnedItem", - kind: "4", - id: 4, - type: "TestItem", - stableId: "TestItem 4 FirstPinnedItem" - }; + const pinnedItem = new HierarchyTreeBuilder().setName("FirstPinnedItem") + .setStableId("TestItem 4").setLayerId(4).build(); presenter.updatePinnedItems(pinnedItem); expect(uiData.pinnedItems).toContain(pinnedItem); }); @@ -145,12 +108,12 @@ describe("PresenterSurfaceFlinger", () => { }; presenter.notifyCurrentTraceEntries(entries); - expect(uiData.tree.children.length).toEqual(3); + expect(uiData.tree?.children.length).toEqual(3); presenter.updateHierarchyTree(userOptions); expect(uiData.hierarchyUserOptions).toEqual(userOptions); // nested children should now be on same level as initial parents - expect(uiData.tree.children.length).toEqual(94); + expect(uiData.tree?.children.length).toEqual(94); }); it("can filter hierarchy tree", () => { @@ -171,21 +134,21 @@ describe("PresenterSurfaceFlinger", () => { name: "Flat", enabled: true } - } + }; presenter.notifyCurrentTraceEntries(entries); presenter.updateHierarchyTree(userOptions); - expect(uiData.tree.children.length).toEqual(94); + expect(uiData.tree?.children.length).toEqual(94); presenter.filterHierarchyTree("Wallpaper"); // All but four layers should be filtered out - expect(uiData.tree.children.length).toEqual(4); + expect(uiData.tree?.children.length).toEqual(4); }); it("can set new properties tree and associated ui data", () => { presenter.notifyCurrentTraceEntries(entries); - presenter.newPropertiesTree(selectedItem); + presenter.newPropertiesTree(selectedTree); // does not check specific tree values as tree transformation method may change - expect(Object.keys(uiData.selectedTree).length > 0).toBeTrue(); + expect(uiData.propertiesTree).toBeTruthy(); }); it("can update properties tree", () => { @@ -207,33 +170,27 @@ describe("PresenterSurfaceFlinger", () => { }; presenter.notifyCurrentTraceEntries(entries); - presenter.newPropertiesTree(selectedItem); + presenter.newPropertiesTree(selectedTree); + expect(uiData.propertiesTree?.diffType).toBeFalsy(); presenter.updatePropertiesTree(userOptions); expect(uiData.propertiesUserOptions).toEqual(userOptions); //check that diff type added - expect(uiData.selectedTree.diffType).toEqual(DiffType.NONE); + expect(uiData.propertiesTree?.diffType).toBeTruthy(); }); it("can filter properties tree", () => { presenter.notifyCurrentTraceEntries(entries); - presenter.newPropertiesTree(selectedItem); + presenter.newPropertiesTree(selectedTree); + let nonTerminalChildren = uiData.propertiesTree?.children?.filter( + (child: PropertiesTree) => typeof child.propertyKey === "string" + ) ?? []; - let nonTerminalChildren = uiData.selectedTree - .children[0] - .children.filter( - (child: PropertiesTree) => !(child.propertyKey instanceof Terminal) - ); + expect(nonTerminalChildren.length).toEqual(55); + presenter.filterPropertiesTree("bound"); - expect(nonTerminalChildren.length).toEqual(2); - - presenter.filterPropertiesTree("ContainerLayer"); - - // one child should be filtered out - nonTerminalChildren = uiData.selectedTree - .children[0] - .children.filter( - (child: PropertiesTree) => !(child.propertyKey instanceof Terminal) - ); - expect(nonTerminalChildren.length).toEqual(1); + nonTerminalChildren = uiData.propertiesTree?.children?.filter( + (child: PropertiesTree) => typeof child.propertyKey === "string" + ) ?? []; + expect(nonTerminalChildren.length).toEqual(3); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts index 857beb3cf..9b59740ea 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/presenter.ts @@ -18,9 +18,10 @@ 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, TreeSummary } from "viewers/common/tree_utils"; +import { getFilter, FilterType, HierarchyTree, Tree, TreeFlickerItem, PropertiesTree } 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"; type NotifyViewCallbackType = (uiData: UiData) => void; @@ -31,7 +32,7 @@ export class Presenter { this.notifyViewCallback(this.uiData); } - public updatePinnedItems(pinnedItem: Tree) { + public updatePinnedItems(pinnedItem: HierarchyTree) { const pinnedId = `${pinnedItem.id}`; if (this.pinnedItems.map(item => `${item.id}`).includes(pinnedId)) { this.pinnedItems = this.pinnedItems.filter(pinned => `${pinned.id}` != pinnedId); @@ -47,7 +48,7 @@ export class Presenter { if (this.highlightedItems.includes(id)) { this.highlightedItems = this.highlightedItems.filter(hl => hl != id); } else { - this.highlightedItems = []; //if multi-select implemented, remove this line + this.highlightedItems = []; //if multi-select surfaces implemented, remove this line this.highlightedItems.push(id); } this.uiData.highlightedItems = this.highlightedItems; @@ -78,12 +79,12 @@ export class Presenter { this.updateSelectedTreeUiData(); } - public newPropertiesTree(selectedItem: any) { - this.selectedTree = selectedItem; + public newPropertiesTree(selectedItem: HierarchyTree) { + this.selectedHierarchyTree = selectedItem; this.updateSelectedTreeUiData(); } - public notifyCurrentTraceEntries(entries: Map) { + public notifyCurrentTraceEntries(entries: Map) { this.uiData = new UiData(); this.uiData.hierarchyUserOptions = this.hierarchyUserOptions; this.uiData.propertiesUserOptions = this.propertiesUserOptions; @@ -127,49 +128,13 @@ export class Presenter { } private updateSelectedTreeUiData() { - if (this.selectedTree) { - this.uiData.selectedTree = this.getTreeWithTransformedProperties(this.selectedTree); - this.uiData.selectedTreeSummary = this.getSelectedTreeSummary(this.selectedTree); + if (this.selectedHierarchyTree) { + this.uiData.propertiesTree = this.getTreeWithTransformedProperties(this.selectedHierarchyTree); + this.uiData.selectedLayer = this.selectedLayer; } this.notifyViewCallback(this.uiData); } - private getSelectedTreeSummary(layer: Tree): TreeSummary | undefined { - const summary = []; - - if (layer?.visibilityReason?.length > 0) { - let reason = ""; - if (Array.isArray(layer.visibilityReason)) { - reason = layer.visibilityReason.join(", "); - } else { - reason = layer.visibilityReason; - } - - summary.push({key: "Invisible due to", value: reason}); - } - - if (layer?.occludedBy?.length > 0) { - summary.push({key: "Occluded by", value: layer.occludedBy.map((it:Tree) => it.id).join(", ")}); - } - - if (layer?.partiallyOccludedBy?.length > 0) { - summary.push({ - key: "Partially occluded by", - value: layer.partiallyOccludedBy.map((it:Tree) => it.id).join(", "), - }); - } - - if (layer?.coveredBy?.length > 0) { - summary.push({key: "Covered by", value: layer.coveredBy.map((it:Tree) => it.id).join(", ")}); - } - - if (summary.length === 0) { - return undefined; - } - - return summary; - } - private generateTree() { if (!this.entry) { return null; @@ -180,13 +145,13 @@ export class Presenter { .setIsSimplifyNames(this.hierarchyUserOptions["simplifyNames"]?.enabled) .setIsFlatView(this.hierarchyUserOptions["flat"]?.enabled) .withUniqueNodeId(); - let tree: Tree; + let tree: HierarchyTree | null; if (!this.hierarchyUserOptions["showDiff"]?.enabled) { tree = generator.generateTree(); } else { tree = generator.compareWith(this.previousEntry) .withModifiedCheck() - .generateFinalDiffTree(); + .generateFinalTreeWithDiff(); } this.pinnedItems = generator.getPinnedItems(); this.uiData.pinnedItems = this.pinnedItems; @@ -245,13 +210,15 @@ export class Presenter { } } - private getTreeWithTransformedProperties(selectedTree: Tree) { + private getTreeWithTransformedProperties(selectedTree: HierarchyTree): PropertiesTree { const transformer = new TreeTransformer(selectedTree, this.propertiesFilter) + .showOnlyProtoDump() .setIsShowDefaults(this.propertiesUserOptions["showDefaults"]?.enabled) .setIsShowDiff(this.propertiesUserOptions["showDiff"]?.enabled) .setTransformerOptions({skip: selectedTree.skip}) + .setProperties(this.entry) .setDiffProperties(this.previousEntry); - this.uiData.selectedLayer = transformer.getOriginalLayer(this.entry, selectedTree.stableId); + this.selectedLayer = transformer.getOriginalFlickerItem(this.entry, selectedTree.stableId); const transformedTree = transformer.transform(); return transformedTree; } @@ -262,11 +229,12 @@ export class Presenter { private propertiesFilter: FilterType = getFilter(""); private highlightedItems: Array = []; private displayIds: Array = []; - private pinnedItems: Array = []; + private pinnedItems: Array = []; private pinnedIds: Array = []; - private selectedTree: any = null; - private previousEntry: any = null; - private entry: any = null; + private selectedHierarchyTree: HierarchyTree | null = null; + private selectedLayer: LayerTraceEntry | Layer | null = null; + private previousEntry: LayerTraceEntry | null = null; + private entry: LayerTraceEntry | null = null; private hierarchyUserOptions: UserOptions = { showDiff: { name: "Show diff", diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts index 1bc159838..0039fe774 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/ui_data.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Tree, TreeSummary } from "viewers/common/tree_utils"; +import { HierarchyTree, PropertiesTree } 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"; @@ -21,15 +21,14 @@ import { Rectangle } from "viewers/common/rectangle"; export class UiData { dependencies: Array = [TraceType.SURFACE_FLINGER]; - rects?: Rectangle[] = []; - displayIds?: number[] = []; - hasVirtualDisplays? = false; - highlightedItems?: Array = []; - pinnedItems?: Array = []; - hierarchyUserOptions?: UserOptions = {}; - propertiesUserOptions?: UserOptions = {}; - tree?: Tree | null = null; - selectedTree?: any = {}; - selectedLayer?: Layer = {}; - selectedTreeSummary?: TreeSummary = []; + rects: Rectangle[] = []; + displayIds: number[] = []; + hasVirtualDisplays = false; + highlightedItems: Array = []; + pinnedItems: Array = []; + hierarchyUserOptions: UserOptions = {}; + propertiesUserOptions: UserOptions = {}; + tree: HierarchyTree | null = null; + propertiesTree: PropertiesTree | null = null; + selectedLayer: Layer = {}; } diff --git a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts index de77dd00f..ac18e83e7 100644 --- a/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts +++ b/tools/winscope-ng/src/viewers/viewer_surface_flinger/viewer_surface_flinger.component.ts @@ -38,7 +38,7 @@ import { PersistentStore } from "common/persistent_store";
diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts index 6ce86dc6f..c07055ed5 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.spec.ts @@ -1,4 +1,4 @@ -9/* +9;/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,64 +18,26 @@ 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 { DiffType, PropertiesTree, Terminal, Tree } from "viewers/common/tree_utils"; +import { PropertiesTree, Terminal, HierarchyTree } 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"; describe("PresenterWindowManager", () => { let presenter: Presenter; let uiData: UiData; let entries: Map; - let selectedItem: Tree; + let selectedTree: HierarchyTree; beforeAll(async () => { entries = new Map(); const entry: WindowManagerState = await UnitTestUtils.getWindowManagerState(); - selectedItem = { - layerId: "3", - name: "Child1", - displayId: 0, - isVisible: true, - stableId: "3 Child1", - shortName: undefined, - simplifyNames: true, - showInFilteredView: true, - proto: { - name: "KeepInFilter", - }, - chips: [], - children: [ - { - layerId: "2", - name: "Child2", - displayId: 0, - children: [], - stableId: "2 Child2", - shortName: undefined, - simplifyNames: true, - proto: { - name: "KeepInFilter", - }, - isVisible: true, - showInFilteredView: true, - chips: [], - }, - { - layerId: "8", - name: "Child8", - displayId: 0, - children: [], - stableId: "8 Child8", - shortName: undefined, - simplifyNames: true, - proto: { - name: "RejectFromFilter", - }, - isVisible: true, - showInFilteredView: true, - chips: [], - }, - ], - }; + + selectedTree = new HierarchyTreeBuilder().setName("ScreenDecorOverlayBottom") + .setStableId("WindowState 2088ac1 ScreenDecorOverlayBottom").setKind("WindowState") + .setSimplifyNames(true).setShortName("ScreenDecorOverlayBottom").setLayerId(61) + .setFilteredView(true).setIsVisible(true).setChips([VISIBLE_CHIP]).build(); + entries.set(TraceType.WINDOW_MANAGER, [entry, null]); }); @@ -100,12 +62,12 @@ describe("PresenterWindowManager", () => { expect(propertyOpts).toBeTruthy(); // does not check specific tree values as tree generation method may change - expect(Object.keys(uiData.tree).length > 0).toBeTrue(); + expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); }); it("can handle unavailable trace entry", () => { presenter.notifyCurrentTraceEntries(entries); - expect(Object.keys(uiData.tree).length > 0).toBeTrue(); + expect(Object.keys(uiData.tree!).length > 0).toBeTrue(); const emptyEntries = new Map(); presenter.notifyCurrentTraceEntries(emptyEntries); expect(uiData.tree).toBeFalsy(); @@ -114,11 +76,10 @@ describe("PresenterWindowManager", () => { it("can update pinned items", () => { presenter.notifyCurrentTraceEntries(entries); expect(uiData.pinnedItems).toEqual([]); - const pinnedItem = { - name: "FirstPinnedItem", - layerId: 4, - stableId: "TestItem 4 FirstPinnedItem" - }; + + const pinnedItem = new HierarchyTreeBuilder().setName("FirstPinnedItem") + .setStableId("TestItem 4").setLayerId(4).build(); + presenter.updatePinnedItems(pinnedItem); expect(uiData.pinnedItems).toContain(pinnedItem); }); @@ -152,12 +113,11 @@ describe("PresenterWindowManager", () => { }; presenter.notifyCurrentTraceEntries(entries); - expect(uiData.tree.children.length).toEqual(1); - + expect(uiData.tree?.children.length).toEqual(1); presenter.updateHierarchyTree(userOptions); expect(uiData.hierarchyUserOptions).toEqual(userOptions); // nested children should now be on same level initial parent - expect(uiData.tree.children.length).toEqual(72); + expect(uiData.tree?.children.length).toEqual(72); }); it("can filter hierarchy tree", () => { @@ -178,21 +138,21 @@ describe("PresenterWindowManager", () => { name: "Flat", enabled: true } - } + }; presenter.notifyCurrentTraceEntries(entries); presenter.updateHierarchyTree(userOptions); - expect(uiData.tree.children.length).toEqual(72); + expect(uiData.tree?.children.length).toEqual(72); presenter.filterHierarchyTree("ScreenDecor"); // All but two window states should be filtered out - expect(uiData.tree.children.length).toEqual(2); + expect(uiData.tree?.children.length).toEqual(2); }); it("can set new properties tree and associated ui data", () => { presenter.notifyCurrentTraceEntries(entries); - presenter.newPropertiesTree(selectedItem); + presenter.newPropertiesTree(selectedTree); // does not check specific tree values as tree transformation method may change - expect(Object.keys(uiData.selectedTree).length > 0).toBeTrue(); + expect(uiData.propertiesTree).toBeTruthy(); }); it("can update properties tree", () => { @@ -214,31 +174,28 @@ describe("PresenterWindowManager", () => { }; presenter.notifyCurrentTraceEntries(entries); - presenter.newPropertiesTree(selectedItem); + presenter.newPropertiesTree(selectedTree); + expect(uiData.propertiesTree?.diffType).toBeFalsy(); presenter.updatePropertiesTree(userOptions); expect(uiData.propertiesUserOptions).toEqual(userOptions); //check that diff type added - expect(uiData.selectedTree.diffType).toEqual(DiffType.NONE); + expect(uiData.propertiesTree?.diffType).toBeTruthy(); }); it("can filter properties tree", () => { presenter.notifyCurrentTraceEntries(entries); - presenter.newPropertiesTree(selectedItem); + presenter.newPropertiesTree(selectedTree); - let nonTerminalChildren = uiData.selectedTree - .children.filter( - (child: PropertiesTree) => !(child.propertyKey instanceof Terminal) - ); + let nonTerminalChildren = uiData.propertiesTree?.children?.filter( + (child: PropertiesTree) => typeof child.propertyKey === "string" + ) ?? []; - expect(nonTerminalChildren.length).toEqual(2); + expect(nonTerminalChildren.length).toEqual(45); + presenter.filterPropertiesTree("visible"); - presenter.filterPropertiesTree("KeepInFilter"); - - // one child should be filtered out - nonTerminalChildren = uiData.selectedTree - .children.filter( - (child: PropertiesTree) => !(child.propertyKey instanceof Terminal) - ); - expect(nonTerminalChildren.length).toEqual(1); + nonTerminalChildren = uiData.propertiesTree?.children?.filter( + (child: PropertiesTree) => typeof child.propertyKey === "string" + ) ?? []; + expect(nonTerminalChildren.length).toEqual(4); }); }); diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts index 3d893ba6a..3826a5936 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/presenter.ts @@ -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 } from "viewers/common/tree_utils"; +import { getFilter, FilterType, Tree, HierarchyTree, PropertiesTree, TreeFlickerItem } 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: Tree) { + public updatePinnedItems(pinnedItem: HierarchyTree) { const pinnedId = `${pinnedItem.id}`; if (this.pinnedItems.map(item => `${item.id}`).includes(pinnedId)) { this.pinnedItems = this.pinnedItems.filter(pinned => `${pinned.id}` != pinnedId); @@ -78,8 +78,8 @@ export class Presenter { this.updateSelectedTreeUiData(); } - public newPropertiesTree(selectedItem: any) { - this.selectedTree = selectedItem; + public newPropertiesTree(selectedTree: HierarchyTree) { + this.selectedHierarchyTree = selectedTree; this.updateSelectedTreeUiData(); } @@ -103,7 +103,7 @@ export class Presenter { } private generateRects(): Rectangle[] { - const displayRects = this.entry.displays.map((display: DisplayContent) => { + const displayRects = this.entry?.displays?.map((display: DisplayContent) => { const rect = display.displayRect; rect.label = display.title; rect.id = display.layerId; @@ -113,7 +113,7 @@ export class Presenter { return rect; }) ?? []; this.displayIds = []; - const rects = this.entry.windowStates.reverse() + const rects = this.entry?.windowStates?.reverse() .map((it: any) => { const rect = it.rect; rect.id = it.layerId; @@ -122,13 +122,13 @@ export class Presenter { this.displayIds.push(it.displayId); } return rect; - }); + }) ?? []; return this.rectsToUiData(rects.concat(displayRects)); } private updateSelectedTreeUiData() { - if (this.selectedTree) { - this.uiData.selectedTree = this.getTreeWithTransformedProperties(this.selectedTree); + if (this.selectedHierarchyTree) { + this.uiData.propertiesTree = this.getTreeWithTransformedProperties(this.selectedHierarchyTree); } this.notifyViewCallback(this.uiData); } @@ -143,13 +143,13 @@ export class Presenter { .setIsSimplifyNames(this.hierarchyUserOptions["simplifyNames"]?.enabled) .setIsFlatView(this.hierarchyUserOptions["flat"]?.enabled) .withUniqueNodeId(); - let tree: Tree; + let tree: HierarchyTree | null; if (!this.hierarchyUserOptions["showDiff"]?.enabled) { tree = generator.generateTree(); } else { tree = generator.compareWith(this.previousEntry) .withModifiedCheck() - .generateFinalDiffTree(); + .generateFinalTreeWithDiff(); } this.pinnedItems = generator.getPinnedItems(); this.uiData.pinnedItems = this.pinnedItems; @@ -208,11 +208,16 @@ export class Presenter { } } - private getTreeWithTransformedProperties(selectedTree: Tree) { + private getTreeWithTransformedProperties(selectedTree: HierarchyTree): PropertiesTree { + if (!this.entry) { + return {}; + } const transformer = new TreeTransformer(selectedTree, this.propertiesFilter) + .showOnlyProtoDump() .setIsShowDefaults(this.propertiesUserOptions["showDefaults"]?.enabled) .setIsShowDiff(this.propertiesUserOptions["showDiff"]?.enabled) .setTransformerOptions({skip: selectedTree.skip}) + .setProperties(this.entry) .setDiffProperties(this.previousEntry); const transformedTree = transformer.transform(); return transformedTree; @@ -224,11 +229,11 @@ export class Presenter { private propertiesFilter: FilterType = getFilter(""); private highlightedItems: Array = []; private displayIds: Array = []; - private pinnedItems: Array = []; + private pinnedItems: Array = []; private pinnedIds: Array = []; - private selectedTree: any = null; - private previousEntry: any = null; - private entry: any = null; + private selectedHierarchyTree: HierarchyTree | null = null; + private previousEntry: TreeFlickerItem | null = null; + private entry: TreeFlickerItem | null = null; private hierarchyUserOptions: UserOptions = { showDiff: { name: "Show diff", diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts index f0881fc12..e4b0bfc54 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/ui_data.ts @@ -13,19 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Tree } from "viewers/common/tree_utils"; +import { HierarchyTree, PropertiesTree } 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"; export class UiData { dependencies: Array = [TraceType.WINDOW_MANAGER]; - rects?: Rectangle[] = []; - displayIds?: number[] = []; - highlightedItems?: Array = []; - pinnedItems?: Array = []; - hierarchyUserOptions?: UserOptions = {}; - propertiesUserOptions?: UserOptions = {}; - tree?: Tree | null = null; - selectedTree?: any = {}; + rects: Rectangle[] = []; + displayIds: number[] = []; + highlightedItems: Array = []; + pinnedItems: Array = []; + hierarchyUserOptions: UserOptions = {}; + propertiesUserOptions: UserOptions = {}; + tree: HierarchyTree | null = null; + propertiesTree: PropertiesTree | null = null; } diff --git a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts index 827405186..300ff0093 100644 --- a/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts +++ b/tools/winscope-ng/src/viewers/viewer_window_manager/viewer_window_manager.component.ts @@ -37,7 +37,7 @@ import { PersistentStore } from "common/persistent_store";