/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {assertTrue} from 'common/assert_utils'; import {Timestamp} from 'common/time'; import {Trace, TraceEntry} from 'trace/trace'; import {TracePosition} from 'trace/trace_position'; import {View, Viewer, ViewType} from 'viewers/viewer'; export enum WinscopeEventType { APP_INITIALIZED, APP_FILES_COLLECTED, APP_FILES_UPLOADED, APP_RESET_REQUEST, APP_TRACE_VIEW_REQUEST, APP_REFRESH_DUMPS_REQUEST, REMOTE_TOOL_DOWNLOAD_START, REMOTE_TOOL_FILES_RECEIVED, REMOTE_TOOL_TIMESTAMP_RECEIVED, TABBED_VIEW_SWITCHED, TABBED_VIEW_SWITCH_REQUEST, TRACE_POSITION_UPDATE, VIEWERS_LOADED, VIEWERS_UNLOADED, EXPANDED_TIMELINE_TOGGLED, ACTIVE_TRACE_CHANGED, DARK_MODE_TOGGLED, } interface TypeMap { [WinscopeEventType.APP_INITIALIZED]: AppInitialized; [WinscopeEventType.APP_FILES_COLLECTED]: AppFilesCollected; [WinscopeEventType.APP_FILES_UPLOADED]: AppFilesUploaded; [WinscopeEventType.APP_RESET_REQUEST]: AppResetRequest; [WinscopeEventType.APP_TRACE_VIEW_REQUEST]: AppTraceViewRequest; [WinscopeEventType.APP_REFRESH_DUMPS_REQUEST]: AppRefreshDumpsRequest; [WinscopeEventType.REMOTE_TOOL_DOWNLOAD_START]: RemoteToolDownloadStart; [WinscopeEventType.REMOTE_TOOL_FILES_RECEIVED]: RemoteToolFilesReceived; [WinscopeEventType.REMOTE_TOOL_TIMESTAMP_RECEIVED]: RemoteToolTimestampReceived; [WinscopeEventType.TABBED_VIEW_SWITCHED]: TabbedViewSwitched; [WinscopeEventType.TABBED_VIEW_SWITCH_REQUEST]: TabbedViewSwitchRequest; [WinscopeEventType.TRACE_POSITION_UPDATE]: TracePositionUpdate; [WinscopeEventType.VIEWERS_LOADED]: ViewersLoaded; [WinscopeEventType.VIEWERS_UNLOADED]: ViewersUnloaded; [WinscopeEventType.EXPANDED_TIMELINE_TOGGLED]: ExpandedTimelineToggled; [WinscopeEventType.ACTIVE_TRACE_CHANGED]: ActiveTraceChanged; [WinscopeEventType.DARK_MODE_TOGGLED]: DarkModeToggled; } export abstract class WinscopeEvent { abstract readonly type: WinscopeEventType; async visit<T extends WinscopeEventType>( type: T, callback: (event: TypeMap[T]) => Promise<void>, ) { if (this.type === type) { const event = this as unknown as TypeMap[T]; await callback(event); } } } export class AppInitialized extends WinscopeEvent { override readonly type = WinscopeEventType.APP_INITIALIZED; } export class AppFilesCollected extends WinscopeEvent { override readonly type = WinscopeEventType.APP_FILES_COLLECTED; constructor(readonly files: File[]) { super(); } } export class AppFilesUploaded extends WinscopeEvent { override readonly type = WinscopeEventType.APP_FILES_UPLOADED; constructor(readonly files: File[]) { super(); } } export class AppResetRequest extends WinscopeEvent { override readonly type = WinscopeEventType.APP_RESET_REQUEST; } export class AppTraceViewRequest extends WinscopeEvent { override readonly type = WinscopeEventType.APP_TRACE_VIEW_REQUEST; } export class AppRefreshDumpsRequest extends WinscopeEvent { override readonly type = WinscopeEventType.APP_REFRESH_DUMPS_REQUEST; } export class RemoteToolDownloadStart extends WinscopeEvent { override readonly type = WinscopeEventType.REMOTE_TOOL_DOWNLOAD_START; } export class RemoteToolFilesReceived extends WinscopeEvent { override readonly type = WinscopeEventType.REMOTE_TOOL_FILES_RECEIVED; constructor( readonly files: File[], readonly deferredTimestamp?: () => Timestamp | undefined, ) { super(); } } export class RemoteToolTimestampReceived extends WinscopeEvent { override readonly type = WinscopeEventType.REMOTE_TOOL_TIMESTAMP_RECEIVED; constructor(readonly deferredTimestamp: () => Timestamp | undefined) { super(); } } export class TabbedViewSwitched extends WinscopeEvent { override readonly type = WinscopeEventType.TABBED_VIEW_SWITCHED; readonly newFocusedView: View; constructor(view: View) { super(); assertTrue(view.type === ViewType.TAB); this.newFocusedView = view; } } export class TabbedViewSwitchRequest extends WinscopeEvent { override readonly type = WinscopeEventType.TABBED_VIEW_SWITCH_REQUEST; readonly newActiveTrace: Trace<object>; constructor(newActiveTrace: Trace<object>) { super(); this.newActiveTrace = newActiveTrace; } } export class TracePositionUpdate extends WinscopeEvent { override readonly type = WinscopeEventType.TRACE_POSITION_UPDATE; readonly position: TracePosition; readonly updateTimeline: boolean; constructor(position: TracePosition, updateTimeline = false) { super(); this.position = position; this.updateTimeline = updateTimeline; } static fromTimestamp( timestamp: Timestamp, updateTimeline = false, ): TracePositionUpdate { const position = TracePosition.fromTimestamp(timestamp); return new TracePositionUpdate(position, updateTimeline); } static fromTraceEntry( entry: TraceEntry<object>, updateTimeline = false, ): TracePositionUpdate { const position = TracePosition.fromTraceEntry(entry); return new TracePositionUpdate(position, updateTimeline); } } export class ViewersLoaded extends WinscopeEvent { override readonly type = WinscopeEventType.VIEWERS_LOADED; constructor(readonly viewers: Viewer[]) { super(); } } export class ViewersUnloaded extends WinscopeEvent { override readonly type = WinscopeEventType.VIEWERS_UNLOADED; } export class ExpandedTimelineToggled extends WinscopeEvent { override readonly type = WinscopeEventType.EXPANDED_TIMELINE_TOGGLED; constructor(readonly isTimelineExpanded: boolean) { super(); } } export class ActiveTraceChanged extends WinscopeEvent { override readonly type = WinscopeEventType.ACTIVE_TRACE_CHANGED; constructor(readonly trace: Trace<object>) { super(); } } export class DarkModeToggled extends WinscopeEvent { override readonly type = WinscopeEventType.DARK_MODE_TOGGLED; constructor(readonly isDarkMode: boolean) { super(); } }