1/* 2 * Copyright 2023, 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 {Transition, TransitionsTrace} from 'trace/flickerlib/common'; 19import {Parser} from 'trace/parser'; 20import {Timestamp, TimestampType} from 'trace/timestamp'; 21import {TraceType} from 'trace/trace_type'; 22import {AbstractTracesParser} from './abstract_traces_parser'; 23 24export class TracesParserTransitions extends AbstractTracesParser<Transition> { 25 private readonly wmTransitionTrace: Parser<object> | undefined; 26 private readonly shellTransitionTrace: Parser<object> | undefined; 27 private readonly descriptors: string[]; 28 private decodedEntries: Transition[] | undefined; 29 30 constructor(parsers: Array<Parser<object>>) { 31 super(); 32 const wmTransitionTraces = parsers.filter( 33 (it) => it.getTraceType() === TraceType.WM_TRANSITION 34 ); 35 if (wmTransitionTraces.length > 0) { 36 this.wmTransitionTrace = wmTransitionTraces[0]; 37 } 38 const shellTransitionTraces = parsers.filter( 39 (it) => it.getTraceType() === TraceType.SHELL_TRANSITION 40 ); 41 if (shellTransitionTraces.length > 0) { 42 this.shellTransitionTrace = shellTransitionTraces[0]; 43 } 44 if (this.wmTransitionTrace !== undefined && this.shellTransitionTrace !== undefined) { 45 this.descriptors = this.wmTransitionTrace 46 .getDescriptors() 47 .concat(this.shellTransitionTrace.getDescriptors()); 48 } else { 49 this.descriptors = []; 50 } 51 } 52 53 override async parse() { 54 if (this.wmTransitionTrace === undefined) { 55 throw new Error('Missing WM Transition trace'); 56 } 57 58 if (this.shellTransitionTrace === undefined) { 59 throw new Error('Missing Shell Transition trace'); 60 } 61 62 const wmTransitionEntries: Transition[] = []; 63 for (let index = 0; index < this.wmTransitionTrace.getLengthEntries(); index++) { 64 wmTransitionEntries.push(await this.wmTransitionTrace.getEntry(index, TimestampType.REAL)); 65 } 66 67 const shellTransitionEntries: Transition[] = []; 68 for (let index = 0; index < this.shellTransitionTrace.getLengthEntries(); index++) { 69 shellTransitionEntries.push( 70 await this.shellTransitionTrace.getEntry(index, TimestampType.REAL) 71 ); 72 } 73 74 const transitionsTrace = new TransitionsTrace( 75 wmTransitionEntries.concat(shellTransitionEntries) 76 ); 77 78 this.decodedEntries = transitionsTrace.asCompressed().entries as Transition[]; 79 80 await this.parseTimestamps(); 81 } 82 83 override getLengthEntries(): number { 84 return assertDefined(this.decodedEntries).length; 85 } 86 87 override getEntry(index: number, timestampType: TimestampType): Promise<Transition> { 88 const entry = assertDefined(this.decodedEntries)[index]; 89 return Promise.resolve(entry); 90 } 91 92 override getDescriptors(): string[] { 93 return this.descriptors; 94 } 95 96 override getTraceType(): TraceType { 97 return TraceType.TRANSITION; 98 } 99 100 override getTimestamp(type: TimestampType, transition: Transition): undefined | Timestamp { 101 if (type === TimestampType.ELAPSED) { 102 return new Timestamp(type, BigInt(transition.timestamp.elapsedNanos.toString())); 103 } else if (type === TimestampType.REAL) { 104 return new Timestamp(type, BigInt(transition.timestamp.unixNanos.toString())); 105 } 106 return undefined; 107 } 108} 109