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'; 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<CustomQueryType, {}>(); 38 private entries?: T[]; 39 private timestamps?: Timestamp[]; 40 private frameMap?: FrameMap; 41 private frameMapBuilder?: FrameMapBuilder; 42 private descriptors: string[] = []; 43 44 setType(type: TraceType): TraceBuilder<T> { 45 this.type = type; 46 return this; 47 } 48 49 setParser(parser: Parser<T>): TraceBuilder<T> { 50 this.parser = parser; 51 return this; 52 } 53 54 setEntries(entries: T[]): TraceBuilder<T> { 55 this.entries = entries; 56 return this; 57 } 58 59 setTimestamps(timestamps: Timestamp[]): TraceBuilder<T> { 60 this.timestamps = timestamps; 61 return this; 62 } 63 64 setFrameMap(frameMap?: FrameMap): TraceBuilder<T> { 65 this.frameMap = frameMap; 66 return this; 67 } 68 69 setFrame(entry: AbsoluteEntryIndex, frame: AbsoluteFrameIndex) { 70 if (!this.entries) { 71 throw new Error(`Can't set frames before specifying the entries`); 72 } 73 if (!this.frameMapBuilder) { 74 this.frameMapBuilder = new FrameMapBuilder(this.entries.length, 1000); 75 } 76 this.frameMapBuilder.setFrames(entry, {start: frame, end: frame + 1}); 77 return this; 78 } 79 80 setParserCustomQueryResult<Q extends CustomQueryType>( 81 type: Q, 82 result: CustomQueryParserResultTypeMap[Q], 83 ): TraceBuilder<T> { 84 this.parserCustomQueryResult.set(type, result); 85 return this; 86 } 87 88 build(): Trace<T> { 89 if (!this.parser) { 90 this.parser = this.createParser(); 91 } 92 93 const entriesRange: EntriesRange = { 94 start: 0, 95 end: this.parser.getLengthEntries(), 96 }; 97 const trace = new Trace<T>( 98 this.type, 99 this.parser, 100 this.descriptors, 101 undefined, 102 entriesRange, 103 ); 104 105 const frameMap = this.getFrameMap(); 106 if (frameMap) { 107 trace.setFrameInfo(frameMap, frameMap.getFullTraceFramesRange()); 108 } 109 110 return trace; 111 } 112 113 private createParser(): Parser<T> { 114 const builder = new ParserBuilder<T>().setType(this.type); 115 116 if (this.timestamps) { 117 builder.setTimestamps(this.timestamps); 118 } 119 120 if (this.entries) { 121 builder.setEntries(this.entries); 122 } 123 124 this.parserCustomQueryResult?.forEach((result, queryType) => { 125 builder.setCustomQueryResult(queryType, result as any); 126 }); 127 128 return builder.build(); 129 } 130 131 private getFrameMap(): FrameMap | undefined { 132 if (this.frameMap && this.frameMapBuilder) { 133 throw new Error( 134 `Cannot set a full frame map as well as individual entry's frames. Pick one of the two options.`, 135 ); 136 } 137 if (this.frameMap) { 138 return this.frameMap; 139 } 140 if (this.frameMapBuilder) { 141 return this.frameMapBuilder.build(); 142 } 143 return undefined; 144 } 145} 146