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