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 {assertTrue} from 'common/assert_utils';
18import {Timestamp} from 'common/time';
19import {Trace, TraceEntry} from 'trace/trace';
20import {TracePosition} from 'trace/trace_position';
21import {View, Viewer, ViewType} from 'viewers/viewer';
22
23export enum WinscopeEventType {
24  APP_INITIALIZED,
25  APP_FILES_COLLECTED,
26  APP_FILES_UPLOADED,
27  APP_RESET_REQUEST,
28  APP_TRACE_VIEW_REQUEST,
29  APP_REFRESH_DUMPS_REQUEST,
30  REMOTE_TOOL_DOWNLOAD_START,
31  REMOTE_TOOL_FILES_RECEIVED,
32  REMOTE_TOOL_TIMESTAMP_RECEIVED,
33  TABBED_VIEW_SWITCHED,
34  TABBED_VIEW_SWITCH_REQUEST,
35  TRACE_POSITION_UPDATE,
36  VIEWERS_LOADED,
37  VIEWERS_UNLOADED,
38  EXPANDED_TIMELINE_TOGGLED,
39  ACTIVE_TRACE_CHANGED,
40  DARK_MODE_TOGGLED,
41}
42
43interface TypeMap {
44  [WinscopeEventType.APP_INITIALIZED]: AppInitialized;
45  [WinscopeEventType.APP_FILES_COLLECTED]: AppFilesCollected;
46  [WinscopeEventType.APP_FILES_UPLOADED]: AppFilesUploaded;
47  [WinscopeEventType.APP_RESET_REQUEST]: AppResetRequest;
48  [WinscopeEventType.APP_TRACE_VIEW_REQUEST]: AppTraceViewRequest;
49  [WinscopeEventType.APP_REFRESH_DUMPS_REQUEST]: AppRefreshDumpsRequest;
50  [WinscopeEventType.REMOTE_TOOL_DOWNLOAD_START]: RemoteToolDownloadStart;
51  [WinscopeEventType.REMOTE_TOOL_FILES_RECEIVED]: RemoteToolFilesReceived;
52  [WinscopeEventType.REMOTE_TOOL_TIMESTAMP_RECEIVED]: RemoteToolTimestampReceived;
53  [WinscopeEventType.TABBED_VIEW_SWITCHED]: TabbedViewSwitched;
54  [WinscopeEventType.TABBED_VIEW_SWITCH_REQUEST]: TabbedViewSwitchRequest;
55  [WinscopeEventType.TRACE_POSITION_UPDATE]: TracePositionUpdate;
56  [WinscopeEventType.VIEWERS_LOADED]: ViewersLoaded;
57  [WinscopeEventType.VIEWERS_UNLOADED]: ViewersUnloaded;
58  [WinscopeEventType.EXPANDED_TIMELINE_TOGGLED]: ExpandedTimelineToggled;
59  [WinscopeEventType.ACTIVE_TRACE_CHANGED]: ActiveTraceChanged;
60  [WinscopeEventType.DARK_MODE_TOGGLED]: DarkModeToggled;
61}
62
63export abstract class WinscopeEvent {
64  abstract readonly type: WinscopeEventType;
65
66  async visit<T extends WinscopeEventType>(
67    type: T,
68    callback: (event: TypeMap[T]) => Promise<void>,
69  ) {
70    if (this.type === type) {
71      const event = this as unknown as TypeMap[T];
72      await callback(event);
73    }
74  }
75}
76
77export class AppInitialized extends WinscopeEvent {
78  override readonly type = WinscopeEventType.APP_INITIALIZED;
79}
80
81export class AppFilesCollected extends WinscopeEvent {
82  override readonly type = WinscopeEventType.APP_FILES_COLLECTED;
83
84  constructor(readonly files: File[]) {
85    super();
86  }
87}
88
89export class AppFilesUploaded extends WinscopeEvent {
90  override readonly type = WinscopeEventType.APP_FILES_UPLOADED;
91
92  constructor(readonly files: File[]) {
93    super();
94  }
95}
96
97export class AppResetRequest extends WinscopeEvent {
98  override readonly type = WinscopeEventType.APP_RESET_REQUEST;
99}
100
101export class AppTraceViewRequest extends WinscopeEvent {
102  override readonly type = WinscopeEventType.APP_TRACE_VIEW_REQUEST;
103}
104
105export class AppRefreshDumpsRequest extends WinscopeEvent {
106  override readonly type = WinscopeEventType.APP_REFRESH_DUMPS_REQUEST;
107}
108
109export class RemoteToolDownloadStart extends WinscopeEvent {
110  override readonly type = WinscopeEventType.REMOTE_TOOL_DOWNLOAD_START;
111}
112
113export class RemoteToolFilesReceived extends WinscopeEvent {
114  override readonly type = WinscopeEventType.REMOTE_TOOL_FILES_RECEIVED;
115
116  constructor(
117    readonly files: File[],
118    readonly deferredTimestamp?: () => Timestamp | undefined,
119  ) {
120    super();
121  }
122}
123
124export class RemoteToolTimestampReceived extends WinscopeEvent {
125  override readonly type = WinscopeEventType.REMOTE_TOOL_TIMESTAMP_RECEIVED;
126
127  constructor(readonly deferredTimestamp: () => Timestamp | undefined) {
128    super();
129  }
130}
131
132export class TabbedViewSwitched extends WinscopeEvent {
133  override readonly type = WinscopeEventType.TABBED_VIEW_SWITCHED;
134  readonly newFocusedView: View;
135
136  constructor(view: View) {
137    super();
138    assertTrue(view.type === ViewType.TAB);
139    this.newFocusedView = view;
140  }
141}
142
143export class TabbedViewSwitchRequest extends WinscopeEvent {
144  override readonly type = WinscopeEventType.TABBED_VIEW_SWITCH_REQUEST;
145
146  readonly newActiveTrace: Trace<object>;
147
148  constructor(newActiveTrace: Trace<object>) {
149    super();
150    this.newActiveTrace = newActiveTrace;
151  }
152}
153
154export class TracePositionUpdate extends WinscopeEvent {
155  override readonly type = WinscopeEventType.TRACE_POSITION_UPDATE;
156  readonly position: TracePosition;
157  readonly updateTimeline: boolean;
158
159  constructor(position: TracePosition, updateTimeline = false) {
160    super();
161    this.position = position;
162    this.updateTimeline = updateTimeline;
163  }
164
165  static fromTimestamp(
166    timestamp: Timestamp,
167    updateTimeline = false,
168  ): TracePositionUpdate {
169    const position = TracePosition.fromTimestamp(timestamp);
170    return new TracePositionUpdate(position, updateTimeline);
171  }
172
173  static fromTraceEntry(
174    entry: TraceEntry<object>,
175    updateTimeline = false,
176  ): TracePositionUpdate {
177    const position = TracePosition.fromTraceEntry(entry);
178    return new TracePositionUpdate(position, updateTimeline);
179  }
180}
181
182export class ViewersLoaded extends WinscopeEvent {
183  override readonly type = WinscopeEventType.VIEWERS_LOADED;
184
185  constructor(readonly viewers: Viewer[]) {
186    super();
187  }
188}
189
190export class ViewersUnloaded extends WinscopeEvent {
191  override readonly type = WinscopeEventType.VIEWERS_UNLOADED;
192}
193
194export class ExpandedTimelineToggled extends WinscopeEvent {
195  override readonly type = WinscopeEventType.EXPANDED_TIMELINE_TOGGLED;
196  constructor(readonly isTimelineExpanded: boolean) {
197    super();
198  }
199}
200
201export class ActiveTraceChanged extends WinscopeEvent {
202  override readonly type = WinscopeEventType.ACTIVE_TRACE_CHANGED;
203  constructor(readonly trace: Trace<object>) {
204    super();
205  }
206}
207
208export class DarkModeToggled extends WinscopeEvent {
209  override readonly type = WinscopeEventType.DARK_MODE_TOGGLED;
210  constructor(readonly isDarkMode: boolean) {
211    super();
212  }
213}
214