xref: /aosp_15_r20/development/tools/winscope/src/parsers/legacy/parser_factory.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
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 */
16import {assertTrue} from 'common/assert_utils';
17import {ParserTimestampConverter} from 'common/timestamp_converter';
18import {UserNotifier} from 'common/user_notifier';
19import {ProgressListener} from 'messaging/progress_listener';
20import {
21  InvalidLegacyTrace,
22  UnsupportedFileFormat,
23} from 'messaging/user_warnings';
24import {ParserEventLog} from 'parsers/events/parser_eventlog';
25import {FileAndParser} from 'parsers/file_and_parser';
26import {ParserInputMethodClients} from 'parsers/input_method/legacy/parser_input_method_clients';
27import {ParserInputMethodManagerService} from 'parsers/input_method/legacy/parser_input_method_manager_service';
28import {ParserInputMethodService} from 'parsers/input_method/legacy/parser_input_method_service';
29import {ParserProtoLog} from 'parsers/protolog/legacy/parser_protolog';
30import {ParserScreenshot} from 'parsers/screenshot/parser_screenshot';
31import {ParserScreenRecording} from 'parsers/screen_recording/parser_screen_recording';
32import {ParserScreenRecordingLegacy} from 'parsers/screen_recording/parser_screen_recording_legacy';
33import {ParserSurfaceFlinger} from 'parsers/surface_flinger/legacy/parser_surface_flinger';
34import {ParserTransactions} from 'parsers/transactions/legacy/parser_transactions';
35import {ParserTransitionsShell} from 'parsers/transitions/legacy/parser_transitions_shell';
36import {ParserTransitionsWm} from 'parsers/transitions/legacy/parser_transitions_wm';
37import {ParserViewCapture} from 'parsers/view_capture/legacy/parser_view_capture';
38import {ParserWindowManager} from 'parsers/window_manager/legacy/parser_window_manager';
39import {ParserWindowManagerDump} from 'parsers/window_manager/legacy/parser_window_manager_dump';
40import {Parser} from 'trace/parser';
41import {TraceFile} from 'trace/trace_file';
42import {TraceMetadata} from 'trace/trace_metadata';
43
44export class ParserFactory {
45  static readonly PARSERS = [
46    ParserInputMethodClients,
47    ParserInputMethodManagerService,
48    ParserInputMethodService,
49    ParserProtoLog,
50    ParserScreenRecording,
51    ParserScreenRecordingLegacy,
52    ParserSurfaceFlinger,
53    ParserTransactions,
54    ParserWindowManager,
55    ParserWindowManagerDump,
56    ParserEventLog,
57    ParserTransitionsWm,
58    ParserTransitionsShell,
59    ParserViewCapture,
60    ParserScreenshot,
61  ];
62
63  async createParsers(
64    traceFiles: TraceFile[],
65    timestampConverter: ParserTimestampConverter,
66    metadata: TraceMetadata,
67    progressListener?: ProgressListener,
68  ): Promise<FileAndParser[]> {
69    const parsers = new Array<{file: TraceFile; parser: Parser<object>}>();
70
71    for (const [index, traceFile] of traceFiles.entries()) {
72      progressListener?.onProgressUpdate(
73        'Parsing proto files',
74        (index / traceFiles.length) * 100,
75      );
76
77      let hasFoundParser = false;
78
79      for (const ParserType of ParserFactory.PARSERS) {
80        try {
81          const p = new ParserType(traceFile, timestampConverter, metadata);
82          await p.parse();
83          hasFoundParser = true;
84
85          if (p instanceof ParserViewCapture) {
86            p.getWindowParsers().forEach((subParser) => {
87              assertTrue(
88                subParser.getLengthEntries() > 0,
89                () => 'Trace has no entries',
90              );
91              parsers.push(new FileAndParser(traceFile, subParser));
92            });
93          } else {
94            assertTrue(p.getLengthEntries() > 0, () => 'Trace has no entries');
95            parsers.push({file: traceFile, parser: p});
96          }
97          break;
98        } catch (error) {
99          if (hasFoundParser) {
100            UserNotifier.add(
101              new InvalidLegacyTrace(
102                traceFile.getDescriptor(),
103                (error as Error).message,
104              ),
105            );
106            break;
107          }
108          // skip current parser
109        }
110      }
111
112      if (!hasFoundParser) {
113        UserNotifier.add(new UnsupportedFileFormat(traceFile.getDescriptor()));
114      }
115    }
116    return parsers;
117  }
118}
119