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