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