1/* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import {TransformType} from 'parsers/surface_flinger/transform_utils'; 18import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node'; 19import {PropertyTreeNode} from 'trace/tree_node/property_tree_node'; 20import {DEFAULT_PROPERTY_TREE_NODE_FACTORY} from 'trace/tree_node/property_tree_node_factory'; 21import {TreeNode} from 'trace/tree_node/tree_node'; 22import {DiffNode} from 'viewers/common/diff_node'; 23import {UiHierarchyTreeNode} from 'viewers/common/ui_hierarchy_tree_node'; 24import {UiPropertyTreeNode} from 'viewers/common/ui_property_tree_node'; 25import {ChildHierarchy, HierarchyTreeBuilder} from './hierarchy_tree_builder'; 26import {PropertyTreeBuilder} from './property_tree_builder'; 27 28export class TreeNodeUtils { 29 static makeRectNode( 30 left: number | undefined, 31 top: number | undefined, 32 right: number | undefined, 33 bottom: number | undefined, 34 id = 'test node', 35 ): PropertyTreeNode { 36 const children = []; 37 if (left !== undefined) children.push({name: 'left', value: left}); 38 if (top !== undefined) children.push({name: 'top', value: top}); 39 if (right !== undefined) children.push({name: 'right', value: right}); 40 if (bottom !== undefined) children.push({name: 'bottom', value: bottom}); 41 42 return new PropertyTreeBuilder() 43 .setRootId(id) 44 .setName('rect') 45 .setChildren(children) 46 .build(); 47 } 48 49 static makeColorNode( 50 r: number | undefined, 51 g: number | undefined, 52 b: number | undefined, 53 a: number | undefined, 54 ): PropertyTreeNode { 55 const children = []; 56 if (r !== undefined) children.push({name: 'r', value: r}); 57 if (g !== undefined) children.push({name: 'g', value: g}); 58 if (b !== undefined) children.push({name: 'b', value: b}); 59 if (a !== undefined) children.push({name: 'a', value: a}); 60 61 return new PropertyTreeBuilder() 62 .setRootId('test node') 63 .setName('color') 64 .setChildren(children) 65 .build(); 66 } 67 68 static makeBufferNode(): PropertyTreeNode { 69 return new PropertyTreeBuilder() 70 .setRootId('test node') 71 .setName('buffer') 72 .setChildren([ 73 {name: 'height', value: 0}, 74 {name: 'width', value: 1}, 75 {name: 'stride', value: 0}, 76 {name: 'format', value: 1}, 77 ]) 78 .build(); 79 } 80 81 static makeMatrixNode( 82 dsdx: number, 83 dtdx: number, 84 dsdy: number, 85 dtdy: number, 86 ): PropertyTreeNode { 87 return new PropertyTreeBuilder() 88 .setRootId('test node') 89 .setName('matrix') 90 .setChildren([ 91 {name: 'dsdx', value: dsdx}, 92 {name: 'dtdx', value: dtdx}, 93 {name: 'dsdy', value: dsdy}, 94 {name: 'dtdy', value: dtdy}, 95 ]) 96 .build(); 97 } 98 99 static makeTransformNode(type: TransformType): PropertyTreeNode { 100 return new PropertyTreeBuilder() 101 .setRootId('test node') 102 .setName('transform') 103 .setChildren([{name: 'type', value: type}]) 104 .build(); 105 } 106 107 static makeSizeNode( 108 w: number | undefined, 109 h: number | undefined, 110 ): PropertyTreeNode { 111 return new PropertyTreeBuilder() 112 .setRootId('test node') 113 .setName('size') 114 .setChildren([ 115 {name: 'w', value: w}, 116 {name: 'h', value: h}, 117 ]) 118 .build(); 119 } 120 121 static makePositionNode( 122 x: number | undefined, 123 y: number | undefined, 124 ): PropertyTreeNode { 125 return new PropertyTreeBuilder() 126 .setRootId('test node') 127 .setName('pos') 128 .setChildren([ 129 {name: 'x', value: x}, 130 {name: 'y', value: y}, 131 ]) 132 .build(); 133 } 134 135 static makeHierarchyNode( 136 proto: any, 137 children: ChildHierarchy[] = [], 138 ): HierarchyTreeNode { 139 return new HierarchyTreeBuilder() 140 .setId(`${proto.id}`) 141 .setName(proto.name) 142 .setProperties(proto) 143 .setChildren(children) 144 .build(); 145 } 146 147 static makePropertyNode( 148 rootId: string, 149 name: string, 150 value: any, 151 ): PropertyTreeNode { 152 return DEFAULT_PROPERTY_TREE_NODE_FACTORY.makeProtoProperty( 153 rootId, 154 name, 155 value, 156 ); 157 } 158 159 static makeCalculatedPropertyNode( 160 rootId: string, 161 name: string, 162 value: any, 163 ): PropertyTreeNode { 164 return DEFAULT_PROPERTY_TREE_NODE_FACTORY.makeCalculatedProperty( 165 rootId, 166 name, 167 value, 168 ); 169 } 170 171 static makeUiHierarchyNode(proto: any): UiHierarchyTreeNode { 172 return UiHierarchyTreeNode.from(TreeNodeUtils.makeHierarchyNode(proto)); 173 } 174 175 static makeUiPropertyNode( 176 rootId: string, 177 name: string, 178 value: any, 179 ): UiPropertyTreeNode { 180 return UiPropertyTreeNode.from( 181 TreeNodeUtils.makePropertyNode(rootId, name, value), 182 ); 183 } 184 185 static treeNodeEqualityTester(first: any, second: any): boolean | undefined { 186 if (first instanceof TreeNode && second instanceof TreeNode) { 187 return TreeNodeUtils.testTreeNodes(first, second); 188 } 189 return undefined; 190 } 191 192 private static testTreeNodes( 193 node: TreeNode, 194 expectedNode: TreeNode, 195 ): boolean { 196 if (node.id !== expectedNode.id) return false; 197 if (node.name !== expectedNode.name) return false; 198 199 if ((node as DiffNode).getDiff && (expectedNode as DiffNode).getDiff) { 200 if ( 201 (node as DiffNode).getDiff() !== (expectedNode as DiffNode).getDiff() 202 ) { 203 return false; 204 } 205 } 206 207 const nodeChildren = node.getAllChildren(); 208 const expectedChildren = expectedNode.getAllChildren(); 209 if (nodeChildren.length !== expectedChildren.length) return false; 210 211 for (let i = 0; i < nodeChildren.length; i++) { 212 const nodeChild = nodeChildren[i]; 213 const expectedChild = expectedChildren[i]; 214 215 if (!TreeNodeUtils.testTreeNodes(nodeChild, expectedChild)) { 216 return false; 217 } 218 } 219 return true; 220 } 221} 222