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 {assertDefined} from 'common/assert_utils'; 18import {SetFormatters} from 'parsers/operations/set_formatters'; 19import {OperationChain} from 'trace/tree_node/operations/operation_chain'; 20import { 21 PropertySource, 22 PropertyTreeNode, 23} from 'trace/tree_node/property_tree_node'; 24import {DEFAULT_PROPERTY_TREE_NODE_FACTORY} from './property_tree_node_factory'; 25 26export type LazyPropertiesStrategyType = () => Promise<PropertyTreeNode>; 27 28export class PropertiesProvider { 29 private eagerPropertiesRoot: PropertyTreeNode; 30 private lazyPropertiesRoot: PropertyTreeNode | undefined; 31 private allPropertiesRoot: PropertyTreeNode | undefined; 32 33 constructor( 34 eagerPropertiesRoot: PropertyTreeNode, 35 private readonly lazyPropertiesStrategy: 36 | LazyPropertiesStrategyType 37 | undefined, 38 private readonly commonOperations: OperationChain<PropertyTreeNode>, 39 private readonly eagerOperations: OperationChain<PropertyTreeNode>, 40 private readonly lazyOperations: OperationChain<PropertyTreeNode>, 41 ) { 42 this.eagerPropertiesRoot = this.commonOperations.apply( 43 this.eagerOperations.apply(eagerPropertiesRoot), 44 ); 45 } 46 47 getEagerProperties(): PropertyTreeNode { 48 return this.eagerPropertiesRoot; 49 } 50 51 addEagerProperty(property: PropertyTreeNode) { 52 new SetFormatters().apply(property); 53 this.eagerPropertiesRoot.addOrReplaceChild(property); 54 } 55 56 async getAll(): Promise<PropertyTreeNode> { 57 if (this.allPropertiesRoot) return this.allPropertiesRoot; 58 59 const root = DEFAULT_PROPERTY_TREE_NODE_FACTORY.makePropertyRoot( 60 this.eagerPropertiesRoot.id, 61 this.eagerPropertiesRoot.name, 62 PropertySource.PROTO, 63 undefined, 64 ); 65 const children = [...this.eagerPropertiesRoot.getAllChildren()]; 66 67 // all eager properties have already had operations applied so no need to reapply 68 const mustFetchLazyProperties = 69 !this.lazyPropertiesRoot && this.lazyPropertiesStrategy !== undefined; 70 if (mustFetchLazyProperties) { 71 this.lazyPropertiesRoot = this.commonOperations.apply( 72 this.lazyOperations.apply( 73 await assertDefined(this.lazyPropertiesStrategy)(), 74 ), 75 ); 76 } 77 if (this.lazyPropertiesRoot) { 78 children.push(...this.lazyPropertiesRoot.getAllChildren()); 79 } 80 81 children.forEach((child) => root.addOrReplaceChild(child)); 82 83 root.setIsRoot(true); 84 85 this.allPropertiesRoot = root; 86 return this.allPropertiesRoot; 87 } 88} 89