/* * Copyright (C) 2024 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 {TransformType} from 'parsers/surface_flinger/transform_utils'; import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node'; import {PropertyTreeNode} from 'trace/tree_node/property_tree_node'; import {DEFAULT_PROPERTY_TREE_NODE_FACTORY} from 'trace/tree_node/property_tree_node_factory'; import {TreeNode} from 'trace/tree_node/tree_node'; import {DiffNode} from 'viewers/common/diff_node'; import {UiHierarchyTreeNode} from 'viewers/common/ui_hierarchy_tree_node'; import {UiPropertyTreeNode} from 'viewers/common/ui_property_tree_node'; import {ChildHierarchy, HierarchyTreeBuilder} from './hierarchy_tree_builder'; import {PropertyTreeBuilder} from './property_tree_builder'; export class TreeNodeUtils { static makeRectNode( left: number | undefined, top: number | undefined, right: number | undefined, bottom: number | undefined, id = 'test node', ): PropertyTreeNode { const children = []; if (left !== undefined) children.push({name: 'left', value: left}); if (top !== undefined) children.push({name: 'top', value: top}); if (right !== undefined) children.push({name: 'right', value: right}); if (bottom !== undefined) children.push({name: 'bottom', value: bottom}); return new PropertyTreeBuilder() .setRootId(id) .setName('rect') .setChildren(children) .build(); } static makeColorNode( r: number | undefined, g: number | undefined, b: number | undefined, a: number | undefined, ): PropertyTreeNode { const children = []; if (r !== undefined) children.push({name: 'r', value: r}); if (g !== undefined) children.push({name: 'g', value: g}); if (b !== undefined) children.push({name: 'b', value: b}); if (a !== undefined) children.push({name: 'a', value: a}); return new PropertyTreeBuilder() .setRootId('test node') .setName('color') .setChildren(children) .build(); } static makeBufferNode(): PropertyTreeNode { return new PropertyTreeBuilder() .setRootId('test node') .setName('buffer') .setChildren([ {name: 'height', value: 0}, {name: 'width', value: 1}, {name: 'stride', value: 0}, {name: 'format', value: 1}, ]) .build(); } static makeMatrixNode( dsdx: number, dtdx: number, dsdy: number, dtdy: number, ): PropertyTreeNode { return new PropertyTreeBuilder() .setRootId('test node') .setName('matrix') .setChildren([ {name: 'dsdx', value: dsdx}, {name: 'dtdx', value: dtdx}, {name: 'dsdy', value: dsdy}, {name: 'dtdy', value: dtdy}, ]) .build(); } static makeTransformNode(type: TransformType): PropertyTreeNode { return new PropertyTreeBuilder() .setRootId('test node') .setName('transform') .setChildren([{name: 'type', value: type}]) .build(); } static makeSizeNode( w: number | undefined, h: number | undefined, ): PropertyTreeNode { return new PropertyTreeBuilder() .setRootId('test node') .setName('size') .setChildren([ {name: 'w', value: w}, {name: 'h', value: h}, ]) .build(); } static makePositionNode( x: number | undefined, y: number | undefined, ): PropertyTreeNode { return new PropertyTreeBuilder() .setRootId('test node') .setName('pos') .setChildren([ {name: 'x', value: x}, {name: 'y', value: y}, ]) .build(); } static makeHierarchyNode( proto: any, children: ChildHierarchy[] = [], ): HierarchyTreeNode { return new HierarchyTreeBuilder() .setId(`${proto.id}`) .setName(proto.name) .setProperties(proto) .setChildren(children) .build(); } static makePropertyNode( rootId: string, name: string, value: any, ): PropertyTreeNode { return DEFAULT_PROPERTY_TREE_NODE_FACTORY.makeProtoProperty( rootId, name, value, ); } static makeCalculatedPropertyNode( rootId: string, name: string, value: any, ): PropertyTreeNode { return DEFAULT_PROPERTY_TREE_NODE_FACTORY.makeCalculatedProperty( rootId, name, value, ); } static makeUiHierarchyNode(proto: any): UiHierarchyTreeNode { return UiHierarchyTreeNode.from(TreeNodeUtils.makeHierarchyNode(proto)); } static makeUiPropertyNode( rootId: string, name: string, value: any, ): UiPropertyTreeNode { return UiPropertyTreeNode.from( TreeNodeUtils.makePropertyNode(rootId, name, value), ); } static treeNodeEqualityTester(first: any, second: any): boolean | undefined { if (first instanceof TreeNode && second instanceof TreeNode) { return TreeNodeUtils.testTreeNodes(first, second); } return undefined; } private static testTreeNodes( node: TreeNode, expectedNode: TreeNode, ): boolean { if (node.id !== expectedNode.id) return false; if (node.name !== expectedNode.name) return false; if ((node as DiffNode).getDiff && (expectedNode as DiffNode).getDiff) { if ( (node as DiffNode).getDiff() !== (expectedNode as DiffNode).getDiff() ) { return false; } } const nodeChildren = node.getAllChildren(); const expectedChildren = expectedNode.getAllChildren(); if (nodeChildren.length !== expectedChildren.length) return false; for (let i = 0; i < nodeChildren.length; i++) { const nodeChild = nodeChildren[i]; const expectedChild = expectedChildren[i]; if (!TreeNodeUtils.testTreeNodes(nodeChild, expectedChild)) { return false; } } return true; } }