1/* 2 * Copyright (C) 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 {RelativeEntryIndex, TraceEntryEager} from './trace'; 18 19export enum CustomQueryType { 20 SF_LAYERS_ID_AND_NAME, 21 VIEW_CAPTURE_METADATA, 22 VSYNCID, 23 WM_WINDOWS_TOKEN_AND_TITLE, 24} 25 26export class ProcessParserResult { 27 static [CustomQueryType.SF_LAYERS_ID_AND_NAME]<T>( 28 parserResult: CustomQueryParserResultTypeMap[CustomQueryType.SF_LAYERS_ID_AND_NAME], 29 ): CustomQueryResultTypeMap<T>[CustomQueryType.SF_LAYERS_ID_AND_NAME] { 30 return parserResult; 31 } 32 33 static [CustomQueryType.VIEW_CAPTURE_METADATA]<T>( 34 parserResult: CustomQueryParserResultTypeMap[CustomQueryType.VIEW_CAPTURE_METADATA], 35 ): CustomQueryResultTypeMap<T>[CustomQueryType.VIEW_CAPTURE_METADATA] { 36 return parserResult; 37 } 38 39 static [CustomQueryType.VSYNCID]<T>( 40 parserResult: CustomQueryParserResultTypeMap[CustomQueryType.VSYNCID], 41 makeTraceEntry: ( 42 index: RelativeEntryIndex, 43 vsyncId: bigint, 44 ) => TraceEntryEager<T, bigint>, 45 ): CustomQueryResultTypeMap<T>[CustomQueryType.VSYNCID] { 46 return parserResult.map((vsyncId, index) => { 47 return makeTraceEntry(index, vsyncId); 48 }); 49 } 50 51 static [CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE]<T>( 52 parserResult: CustomQueryParserResultTypeMap[CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE], 53 ): CustomQueryResultTypeMap<T>[CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE] { 54 return parserResult; 55 } 56} 57 58export interface CustomQueryParamTypeMap { 59 [CustomQueryType.SF_LAYERS_ID_AND_NAME]: never; 60 [CustomQueryType.VIEW_CAPTURE_METADATA]: never; 61 [CustomQueryType.VSYNCID]: never; 62 [CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE]: never; 63} 64 65export interface CustomQueryParserResultTypeMap { 66 [CustomQueryType.SF_LAYERS_ID_AND_NAME]: Array<{id: number; name: string}>; 67 [CustomQueryType.VIEW_CAPTURE_METADATA]: { 68 packageName: string; 69 windowName: string; 70 }; 71 [CustomQueryType.VSYNCID]: Array<bigint>; 72 [CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE]: Array<{ 73 token: string; 74 title: string; 75 }>; 76} 77 78export interface CustomQueryResultTypeMap<T> { 79 [CustomQueryType.SF_LAYERS_ID_AND_NAME]: Array<{id: number; name: string}>; 80 [CustomQueryType.VIEW_CAPTURE_METADATA]: { 81 packageName: string; 82 windowName: string; 83 }; 84 [CustomQueryType.VSYNCID]: Array<TraceEntryEager<T, bigint>>; 85 [CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE]: Array<{ 86 token: string; 87 title: string; 88 }>; 89} 90 91export class VisitableParserCustomQuery<Q extends CustomQueryType> { 92 private readonly type: CustomQueryType; 93 private result: Promise<CustomQueryParserResultTypeMap[Q]> | undefined; 94 95 constructor(type: Q) { 96 this.type = type; 97 } 98 99 visit<R extends CustomQueryType>( 100 type: R, 101 visitor: () => Promise<CustomQueryParserResultTypeMap[R]>, 102 ): VisitableParserCustomQuery<Q> { 103 if (type !== this.type) { 104 return this; 105 } 106 this.result = visitor() as Promise<CustomQueryParserResultTypeMap[Q]>; 107 return this; 108 } 109 110 getResult(): Promise<CustomQueryParserResultTypeMap[Q]> { 111 if (this.result === undefined) { 112 throw new Error( 113 `No result available. Looks like custom query (type: ${this.type}) is not implemented!`, 114 ); 115 } 116 return this.result; 117 } 118} 119