1/* 2 * Copyright (C) 2022 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 {Timestamp} from 'common/time/time'; 18import { 19 CustomQueryParserResultTypeMap, 20 CustomQueryType, 21} from 'trace/custom_query'; 22import {FrameMap} from 'trace/frame_map'; 23import {FrameMapBuilder} from 'trace/frame_map_builder'; 24import { 25 AbsoluteEntryIndex, 26 AbsoluteFrameIndex, 27 EntriesRange, 28} from 'trace/index_types'; 29import {Parser} from 'trace/parser'; 30import {Trace} from 'trace/trace'; 31import {TraceType} from 'trace/trace_type'; 32import {ParserBuilder} from './parser_builder'; 33 34export class TraceBuilder<T> { 35 private type = TraceType.SURFACE_FLINGER; 36 private parser?: Parser<T>; 37 private parserCustomQueryResult = new Map< 38 CustomQueryType, 39 CustomQueryParserResultTypeMap[CustomQueryType] 40 >(); 41 private entries?: T[]; 42 private timestamps?: Timestamp[]; 43 private frameMap?: FrameMap; 44 private frameMapBuilder?: FrameMapBuilder; 45 private descriptors: string[] = []; 46 private isCorrupted = false; 47 48 setType(type: TraceType): TraceBuilder<T> { 49 this.type = type; 50 return this; 51 } 52 53 setParser(parser: Parser<T>): TraceBuilder<T> { 54 this.parser = parser; 55 return this; 56 } 57 58 setEntries(entries: T[]): TraceBuilder<T> { 59 this.entries = entries; 60 return this; 61 } 62 63 setTimestamps(timestamps: Timestamp[]): TraceBuilder<T> { 64 this.timestamps = timestamps; 65 return this; 66 } 67 68 setFrameMap(frameMap?: FrameMap): TraceBuilder<T> { 69 this.frameMap = frameMap; 70 return this; 71 } 72 73 setFrame(entry: AbsoluteEntryIndex, frame: AbsoluteFrameIndex) { 74 if (!this.entries) { 75 throw new Error(`Can't set frames before specifying the entries`); 76 } 77 if (!this.frameMapBuilder) { 78 this.frameMapBuilder = new FrameMapBuilder(this.entries.length, 1000); 79 } 80 this.frameMapBuilder.setFrames(entry, {start: frame, end: frame + 1}); 81 return this; 82 } 83 84 setParserCustomQueryResult<Q extends CustomQueryType>( 85 type: Q, 86 result: CustomQueryParserResultTypeMap[Q], 87 ): TraceBuilder<T> { 88 this.parserCustomQueryResult.set(type, result ?? {}); 89 return this; 90 } 91 92 setDescriptors(descriptors: string[]): TraceBuilder<T> { 93 this.descriptors = descriptors; 94 return this; 95 } 96 97 setIsCorrupted(value: boolean): TraceBuilder<T> { 98 this.isCorrupted = value; 99 return this; 100 } 101 102 build(): Trace<T> { 103 if (!this.parser) { 104 this.parser = this.createParser(); 105 } 106 107 const entriesRange: EntriesRange = { 108 start: 0, 109 end: this.parser.getLengthEntries(), 110 }; 111 const trace = new Trace<T>( 112 this.type, 113 this.parser, 114 this.descriptors, 115 undefined, 116 entriesRange, 117 ); 118 119 const frameMap = this.getFrameMap(); 120 if (frameMap) { 121 trace.setFrameInfo(frameMap, frameMap.getFullTraceFramesRange()); 122 } 123 124 return trace; 125 } 126 127 private createParser(): Parser<T> { 128 const builder = new ParserBuilder<T>() 129 .setType(this.type) 130 .setIsCorrupted(this.isCorrupted); 131 132 if (this.timestamps) { 133 builder.setTimestamps(this.timestamps); 134 } 135 136 if (this.entries) { 137 builder.setEntries(this.entries); 138 } 139 140 if (this.descriptors.length > 0) { 141 builder.setDescriptors(this.descriptors); 142 } 143 144 this.parserCustomQueryResult?.forEach((result, queryType) => { 145 builder.setCustomQueryResult(queryType, result); 146 }); 147 148 return builder.build(); 149 } 150 151 private getFrameMap(): FrameMap | undefined { 152 if (this.frameMap && this.frameMapBuilder) { 153 throw new Error( 154 `Cannot set a full frame map as well as individual entry's frames. Pick one of the two options.`, 155 ); 156 } 157 if (this.frameMap) { 158 return this.frameMap; 159 } 160 if (this.frameMapBuilder) { 161 return this.frameMapBuilder.build(); 162 } 163 return undefined; 164 } 165} 166